diff --git a/addons/mail/models/mail_thread_main_attachment.py b/addons/mail/models/mail_thread_main_attachment.py index cb1bb678f3b..c48de0fce31 100644 --- a/addons/mail/models/mail_thread_main_attachment.py +++ b/addons/mail/models/mail_thread_main_attachment.py @@ -23,11 +23,16 @@ class MailMainAttachmentMixin(models.AbstractModel): def _message_set_main_attachment_id(self, attachment_ids): if attachment_ids and not self.message_main_attachment_id: + # we filter out attachment with 'xml' and 'octet' types + attachments = self.env['ir.attachment'].browse(attachment_ids).filtered(lambda r: not r.mimetype.endswith('xml') + and not r.mimetype.endswith('application/octet-stream')) + # Assign one of the attachments as the main according to the following priority: pdf, image, other types. - self.with_context(tracking_disable=True).message_main_attachment_id = max( - self.env['ir.attachment'].browse(attachment_ids), - key=lambda r: (r.mimetype.endswith('pdf'), r.mimetype.startswith('image')) - ).id + if attachments: + self.with_context(tracking_disable=True).message_main_attachment_id = max( + attachments, + key=lambda r: (r.mimetype.endswith('pdf'), r.mimetype.startswith('image')) + ).id def _get_mail_thread_data(self, request_list): res = super()._get_mail_thread_data(request_list) diff --git a/addons/test_mail/tests/test_mail_multicompany.py b/addons/test_mail/tests/test_mail_multicompany.py index e219fddf8e0..ac154ef5aca 100644 --- a/addons/test_mail/tests/test_mail_multicompany.py +++ b/addons/test_mail/tests/test_mail_multicompany.py @@ -214,26 +214,35 @@ class TestMultiCompanySetup(TestMailCommon, TestRecipients): with self.assertRaises(AccessError): test_record_c1.write({'name': 'Cannot Write'}) + first_attachment = self.env['ir.attachment'].create({ + 'company_id': self.user_employee_c2.company_id.id, + 'datas': base64.b64encode(b'First attachment'), + 'mimetype': 'text/plain', + 'name': 'TestAttachmentIDS.txt', + 'res_model': 'mail.compose.message', + 'res_id': 0, + }) + message = test_record_c1.message_post( - attachments=[('testAttachment', b'Test attachment')], + attachments=[('testAttachment', b'First attachment')], + attachment_ids=first_attachment.ids, body='My Body', message_type='comment', subtype_xmlid='mail.mt_comment', ) - self.assertEqual(message.attachment_ids.mapped('name'), ['testAttachment']) - first_attachment = message.attachment_ids + self.assertTrue('testAttachment' in message.attachment_ids.mapped('name')) self.assertEqual(test_record_c1.message_main_attachment_id, first_attachment) new_attach = self.env['ir.attachment'].create({ 'company_id': self.user_employee_c2.company_id.id, - 'datas': base64.b64encode(b'Test attachment'), + 'datas': base64.b64encode(b'Second attachment'), 'mimetype': 'text/plain', 'name': 'TestAttachmentIDS.txt', 'res_model': 'mail.compose.message', 'res_id': 0, }) message = test_record_c1.message_post( - attachments=[('testAttachment', b'Test attachment')], + attachments=[('testAttachment', b'Second attachment')], attachment_ids=new_attach.ids, body='My Body', message_type='comment', diff --git a/addons/test_mail/tests/test_message_post.py b/addons/test_mail/tests/test_message_post.py index 99aa1a72673..26885df6658 100644 --- a/addons/test_mail/tests/test_message_post.py +++ b/addons/test_mail/tests/test_message_post.py @@ -939,6 +939,70 @@ class TestMessagePost(TestMessagePostCommon, CronMixinCase): self.assertFalse(self.env['mail.message.schedule'].sudo()._update_message_scheduled_datetime(msg, now - timedelta(hours=1)), 'Mail scheduler: should return False when no schedule is found') + @mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.addons.mail.models.mail_message_schedule') + def test_message_post_w_attachments_filtering(self): + """ + Test the message_main_attachment heuristics with an emphasis on the XML/Octet/PDF types. + -> we don't want XML nor Octet-Stream files to be set as message_main_attachment + """ + xml_attachment, octet_attachment, pdf_attachment = [('List1', b'My xml attachment')], \ + [('List2', b'My octet-stream attachment')], \ + [('List3', b'My pdf attachment')] + + xml_attachment_data, octet_attachment_data, pdf_attachment_data = self.env['ir.attachment'].create( + self._generate_attachments_data(3, 'mail.compose.message', 0) + ) + xml_attachment_data.write({'mimetype': 'application/xml'}) + octet_attachment_data.write({'mimetype': 'application/octet-stream'}) + pdf_attachment_data.write({'mimetype': 'application/pdf'}) + + test_record = self.env['mail.test.simple.main.attachment'].with_context(self._test_context).create({ + 'name': 'Test', + 'email_from': 'ignasse@example.com', + }) + self.assertFalse(test_record.message_main_attachment_id) + + # test with xml attachment + with self.mock_mail_gateway(): + test_record.message_post( + attachments=xml_attachment, + attachment_ids=xml_attachment_data.ids, + body='Post XML', + message_type='comment', + partner_ids=[self.partner_1.id], + subject='Test', + subtype_xmlid='mail.mt_comment', + ) + self.assertFalse(test_record.message_main_attachment_id, + 'MailThread: main attachment should not be set with an XML') + + # test with octet attachment + with self.mock_mail_gateway(): + test_record.message_post( + attachments=octet_attachment, + attachment_ids=octet_attachment_data.ids, + body='Post Octet-Stream', + message_type='comment', + partner_ids=[self.partner_1.id], + subject='Test', + subtype_xmlid='mail.mt_comment', + ) + self.assertFalse(test_record.message_main_attachment_id, + 'MailThread: main attachment should not be set with an Octet-Stream') + # test with pdf attachment + with self.mock_mail_gateway(): + test_record.message_post( + attachments=pdf_attachment, + attachment_ids=pdf_attachment_data.ids, + body='Post PDF', + message_type='comment', + partner_ids=[self.partner_1.id], + subject='Test', + subtype_xmlid='mail.mt_comment', + ) + self.assertEqual(test_record.message_main_attachment_id, pdf_attachment_data, + 'MailThread: main attachment should be set to application/pdf') + @users('employee') @mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.addons.mail.models.mail_message_schedule') def test_message_post_w_attachments_on_main_attachment_model(self):