[FIX] mail: prepare mail header References to avoid line breaks

When Odoo routes incoming emails it is looking for existing messages in
database using Message Ids which are coming from e-mail header
References.

In Odoo the message id looks pretty long like

    743570479975566.1584086032.522504091262817-openerp-message-notify@ip-172-31-45-160

As it declared in [RFC2822] long header bodies can be "folded" using
CRLF+WSP. And some mail clients do that very thing. They split
References header body which contains Message Ids by "\n ".  The example
of mail client where it can be reproduced is apps.rackspace.com We
created Sales Order in Odoo, sent this quotation to the client email. He
replied with e-mail, and this email can't be matched with any existing
message id and as result it's not attached to the Sales Order.

RFC2882: https://tools.ietf.org/html/rfc2822#section-2.2.3

closes odoo/odoo#68077

X-original-commit: 559f6cf62711ad45557eddec3af7c66616724eb5
Signed-off-by: Julien Castiaux <Julien00859@users.noreply.github.com>
This commit is contained in:
Veronika Kotovich
2021-03-18 12:10:03 +00:00
committed by Julien Castiaux
parent 0a3c22e33b
commit 43d70a670a
3 changed files with 37 additions and 1 deletions
+5 -1
View File
@@ -861,7 +861,11 @@ class MailThread(models.AbstractModel):
# compute references to find if message is a reply to an existing thread
thread_references = message_dict['references'] or message_dict['in_reply_to']
msg_references = [ref for ref in tools.mail_header_msgid_re.findall(thread_references) if 'reply_to' not in ref]
msg_references = [
re.sub(r'[\r\n\t ]+', r'', ref) # "Unfold" buggy references
for ref in tools.mail_header_msgid_re.findall(thread_references)
if 'reply_to' not in ref
]
mail_messages = self.env['mail.message'].sudo().search([('message_id', 'in', msg_references)], limit=1, order='id desc, message_id')
is_a_reply = bool(mail_messages)
reply_model, reply_thread_id = mail_messages.model, mail_messages.res_id
@@ -931,6 +931,27 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(len(self.test_record.message_ids), init_msg_count + 1)
self.assertEqual(self.fake_email.child_ids, self.test_record.message_ids[0])
@mute_logger('odoo.addons.mail.models.mail_thread')
def test_message_process_references_external_buggy_message_id(self):
"""
Incoming email being a reply to an external email processed by
odoo should update thread accordingly. Special case when the
external mail service wrongly folds the message_id on several
lines.
"""
new_message_id = '<ThisIsTooMuchFake.MonsterEmail.789@agrolait.com>'
buggy_message_id = new_message_id.replace('MonsterEmail', 'Monster\r\n Email')
self.fake_email.write({
'message_id': new_message_id
})
init_msg_count = len(self.test_record.message_ids)
self.format_and_process(
MAIL_TEMPLATE, self.email_from, 'erroneous@test.com',
extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % buggy_message_id)
self.assertEqual(len(self.test_record.message_ids), init_msg_count + 1)
self.assertEqual(self.fake_email.child_ids, self.test_record.message_ids[0])
@mute_logger('odoo.addons.mail.models.mail_thread')
def test_message_process_references_forward(self):
""" Incoming email using references but with alias forward should not go into references destination """
+11
View File
@@ -0,0 +1,11 @@
Belarus, 2021-03-16
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Veronika Kotovich veronika.kotovich@gmail.com https://github.com/veryberry