From 91672b1cabd2702a71a5ece19dfc557eb1cdf985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 4 Jan 2023 14:04:40 +0000 Subject: [PATCH] [IMP] mail: log a warning when having invalid headers on mail.mail In this commit we add some logs when we fail to evaluate the 'headers' field on a 'mail.mail' record, used to populate the headers of outgoing emails. Some tests are added to ensure we do not crash if headers is malformed, and to cover the feature itself as it was still not really done. Task-2710804 (Mail: Clean MailThread Posting API) Task-3093268 (Mail: Stop spamming CCs) Prepares Task-2684479 (Mail: Better report errors when sending emails) Part-of: odoo/odoo#99482 --- addons/mail/models/mail_mail.py | 14 +++++++++-- addons/test_mail/tests/test_mail_mail.py | 31 +++++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py index ce415643fad..1fed4e7045c 100644 --- a/addons/mail/models/mail_mail.py +++ b/addons/mail/models/mail_mail.py @@ -352,8 +352,18 @@ class MailMail(models.Model): if self.headers: try: headers.update(ast.literal_eval(self.headers)) - except Exception: - pass + except (ValueError, TypeError) as e: + _logger.warning( + 'Evaluation error when evaluating mail headers (received %r): %s', + self.headers, e, + ) + # global except as we don't want to crash the queue just due to a malformed + # headers value + except Exception as e: + _logger.warning( + 'Unknown error when evaluating mail headers (received %r): %s', + self.headers, e, + ) # prepare recipients: use email_to if defined then check recipient_ids # that receive a specific email, notably due to link shortening / redirect diff --git a/addons/test_mail/tests/test_mail_mail.py b/addons/test_mail/tests/test_mail_mail.py index 5979b1a3030..164161079ca 100644 --- a/addons/test_mail/tests/test_mail_mail.py +++ b/addons/test_mail/tests/test_mail_mail.py @@ -11,7 +11,7 @@ from OpenSSL.SSL import Error as SSLError from socket import gaierror, timeout from unittest.mock import call, patch -from odoo import api, Command, tools +from odoo import api, Command from odoo.addons.base.models.ir_mail_server import MailDeliveryException from odoo.addons.test_mail.tests.common import TestMailCommon from odoo.exceptions import AccessError @@ -126,6 +126,35 @@ class TestMailMail(TestMailCommon): self.assertEqual(mail.sudo().restricted_attachment_count, 2) self.assertEqual(len(mail.sudo().unrestricted_attachment_ids), 0) + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mail_mail_headers(self): + """ Test headers management when set on outgoing mail. """ + # mail without thread-enabled record + base_values = { + 'body_html': '

Test

', + 'email_to': 'test@example.com', + 'headers': {'foo': 'bar'}, + } + + for headers, expected in [ + ({'foo': 'bar'}, {'foo': 'bar'}), + ("{'foo': 'bar'}", {'foo': 'bar'}), + ("{'foo': 'bar', 'baz': '3+2'}", {'foo': 'bar', 'baz': '3+2'}), + (['not_a_dict'], {}), + ('alsonotadict', {}), + ("['not_a_dict']", {}), + ("{'invaliddict'}", {}), + ]: + with self.subTest(headers=headers, expected=expected): + mail = self.env['mail.mail'].create([ + dict(base_values, headers=headers) + ]) + with self.mock_mail_gateway(): + mail.send() + for key, value in expected.items(): + self.assertIn(key, self._mails[0]['headers']) + self.assertEqual(self._mails[0]['headers'][key], value) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_mail_mail_recipients(self): """ Partner_ids is a field used from mail_message, but not from mail_mail. """