[FIX] mail: bad CTE/QP decoding of rfc822-headers
Based on RFC3462, a Content-Type text/rfc822-headers exists and provide a mechanism to label and return only the RFC 822 headers of a failed message (bounce) These are only the headers and not the full message. The Content-Type-Encoding should be either 7-bit(US-ASCII) or Quoted-Printable (QP) as in the section 2 of the RFC. Spawn the error: After getting reported by a customer, I had to reproduce by spamming wrong outlook addresses and add logging in a sh database on the message_process of mail_thread.py and logged the `message` variable. After few retry, I got one of the part that was defined as followed: Content-Description: Undelivered Message Headers Content-Type: text/rfc822-headers Content-Transfer-Encoding: quoted-printable The `get_payload()`function used was only assuming that there is a full email on that part and that it could only be encoded as an email, which was not the case in this situation (quoted-printable: 76 characters per line, character `=` used as the end of line character). opw-3064589 task-3131561 closes odoo/odoo#110901 X-original-commit: f86f4b671696178f8fa42b81d8753d2591578431 Signed-off-by: Julien Castiaux <juc@odoo.com> Co-authored-by: Baptiste Vergote <bve@odoo.com>
This commit is contained in:
committed by
bve-odoo
co-authored by
Baptiste Vergote
parent
79c6025213
commit
37ca7770a6
@@ -1474,7 +1474,7 @@ class MailThread(models.AbstractModel):
|
||||
if email_part:
|
||||
if email_part.get_content_type() == 'text/rfc822-headers':
|
||||
# Convert the message body into a message itself
|
||||
email_payload = message_from_string(email_part.get_payload(), policy=email.policy.SMTP)
|
||||
email_payload = message_from_string(email_part.get_content(), policy=email.policy.SMTP)
|
||||
else:
|
||||
email_payload = email_part.get_payload()[0]
|
||||
bounced_msg_id = tools.mail_header_msgid_re.findall(tools.decode_message_header(email_payload, 'Message-Id'))
|
||||
|
||||
@@ -958,6 +958,90 @@ OyI+T2RvbzwvYT4uCjwvcD4KPC9kaXY+CiAgICAgICAg
|
||||
--92726A5F09.1555335666/mail2.test.ironsky--
|
||||
"""
|
||||
|
||||
|
||||
MAIL_BOUNCE_QP_RFC822_HEADERS = """\
|
||||
Received: by mailserver.odoo.com (Postfix)
|
||||
id EA0B917B8E4; Tue, 29 Feb 2023 11:11:11 +0100 (CET)
|
||||
From: {email_from}
|
||||
Subject: Undelivered Mail Returned to Sender
|
||||
To: {email_to}
|
||||
Auto-Submitted: auto-replied
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/report; report-type=delivery-status;
|
||||
boundary="DFFDC17AA03.1673346179/mailserver.odoo.com"
|
||||
Message-Id: <40230110102259.EA0B917B8E4@mailserver.odoo.com>
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Delivered-To: {delivered_to}
|
||||
Return-Path: <>
|
||||
|
||||
--DFFDC17AA03.1673346179/mailserver.odoo.com
|
||||
Content-Description: Notification
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
I'm sorry to have to inform you that your message could not
|
||||
be delivered to one or more recipients.
|
||||
|
||||
<rdesfrdgtfdrfesd@outlook.com>: host
|
||||
outlook-com.olc.protection.outlook.com[104.47.56.33] said: 550 5.5.0
|
||||
Requested action not taken: mailbox unavailable (S2017062302). (in re=
|
||||
ply to
|
||||
RCPT TO command)
|
||||
|
||||
--DFFDC17AA03.1673346179/mailserver.odoo.com
|
||||
Content-Description: Delivery report
|
||||
Content-Type: message/delivery-status
|
||||
|
||||
Reporting-MTA: dns; mailserver.odoo.com
|
||||
X-Postfix-Queue-ID: DFFDC17AA03
|
||||
X-Postfix-Sender: rfc822; bounce@xxx.odoo.com
|
||||
Arrival-Date: Tue, 29 Feb 2023 10:10:10 +0100 (CET)
|
||||
|
||||
Final-Recipient: rfc822; rdesfrdgtfdrfesd@outlook.com
|
||||
Original-Recipient: rfc822;rdesfrdgtfdrfesd@outlook.com
|
||||
Action: failed
|
||||
Status: 5.5.0
|
||||
Remote-MTA: dns; outlook-com.olc.protection.outlook.com
|
||||
Diagnostic-Code: smtp; 550 5.5.0 Requested action not taken: mailbox
|
||||
unavailable (S2017062302).
|
||||
|
||||
--DFFDC17AA03.1673346179/mailserver.odoo.com
|
||||
Content-Description: Undelivered Message Headers
|
||||
Content-Type: text/rfc822-headers
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
Return-Path: <bounce@xxx.odoo.com>
|
||||
Received: from eupp00.odoo.com (00.72.79.34.bc.googleusercontent.com [34.=
|
||||
79.72.00])
|
||||
by mailserver.odoo.com (Postfix) with ESMTPS id DFFDC17AA03;
|
||||
Tue, 10 Jan 2023 11:22:57 +0100 (CET)
|
||||
DKIM-Signature: v=3D1; a=3Drsa-sha256; c=3Dsimple/simple; d=3Dxxx.be;
|
||||
s=3Dodoo; t=3D1673346178;
|
||||
bh=3DYPJOqkUi8B28X1MrRUsgmsL8KRz/ZIkpbYyc6wNITXA=3D;
|
||||
h=3Dreferences:Subject:From:Reply-To:To:Date:From;
|
||||
b=3DCMqh7mUvpgUw+JpCeGluv1+MZ3y6EsXd0acmsfzpYBjcoy1InvD6FLT1/lQCcgetf
|
||||
cGyL/8R4vvDKATyE0AtOIpoYDsbpnMoiYWqaSXnDVuLTrEZzyrK/2j10ZTnHZ2uDTC
|
||||
b7wPjFfQ9pted/t6CAUhVT1XydDNalSwEZovy/QI=3D
|
||||
Message-Id: <368396033905967.1673346177.695352554321289-openerp-11-sale.o=
|
||||
rder@eupp00>
|
||||
references: <792105153140463.1673746527.352018594741821-openerp-11-sale.o=
|
||||
rder@xxx.odoo.com> <368396033905967.1673346177.695352554321289-openerp-11=
|
||||
-sale.order@eupp00>
|
||||
Subject: Thi is a SO (Ref SO/11)
|
||||
From: info@xxx.odoo.com
|
||||
Reply-To: "SO/11" <catchall@xxx.odoo.com=
|
||||
>
|
||||
To: "rdesfrdgtfdrfesd@outlook.com" <rdesfrdgtfdrfesd@outlook.com>
|
||||
Date: Tue, 29 Feb 2023 06:09:06 -0000
|
||||
X-Odoo-Objects: sale.order-11
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary=3D"=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
|
||||
=3D=3D=3D=3D=3D5706316606908750110=3D=3D"
|
||||
|
||||
--DFFDC17AA03.1673346179/mailserver.odoo.com--
|
||||
|
||||
"""
|
||||
|
||||
MAIL_NO_BODY = '''\
|
||||
Return-Path: <{email_from}>
|
||||
Delivered-To: catchall@xxxx.xxxx
|
||||
|
||||
@@ -104,6 +104,31 @@ class TestEmailParsing(TestMailCommon):
|
||||
|
||||
self.assertEqual(res['bounced_msg_id'], [msg_id], "Message-Id is not extracted from Text/RFC822-Headers attachment")
|
||||
|
||||
def test_message_parse_extract_bounce_rfc822_headers_qp(self):
|
||||
# Incoming bounce for unexisting Outlook address
|
||||
# bounce back sometimes with a Content-Type `text/rfc822-headers`
|
||||
# and Content-Type-Encoding `quoted-printable`
|
||||
partner = self.env['res.partner'].create({
|
||||
'name':'Mitchelle Admine',
|
||||
'email':'rdesfrdgtfdrfesd@outlook.com'
|
||||
})
|
||||
message = self.env['mail.message'].create({
|
||||
'message_id' : '<368396033905967.1673346177.695352554321289-openerp-11-sale.order@eupp00>'
|
||||
})
|
||||
incoming_bounce = self.format(
|
||||
test_mail_data.MAIL_BOUNCE_QP_RFC822_HEADERS,
|
||||
email_from='MAILER-DAEMON@mailserver.odoo.com (Mail Delivery System)',
|
||||
email_to='bounce@xxx.odoo.com',
|
||||
delivered_to='bounce@xxx.odoo.com'
|
||||
)
|
||||
|
||||
msg_dict = {}
|
||||
msg = self.env['mail.thread']._message_parse_extract_bounce(self.from_string(incoming_bounce), msg_dict)
|
||||
self.assertEqual(msg['bounced_email'], partner.email, "The sender email should be correctly parsed")
|
||||
self.assertEqual(msg['bounced_partner'], partner, "A partner with this email should exist")
|
||||
self.assertEqual(msg['bounced_msg_id'][0], message.message_id, "The sender message-id should correctly parsed")
|
||||
self.assertEqual(msg['bounced_message'], message, "An existing message with this message_id should exist")
|
||||
|
||||
def test_message_parse_plaintext(self):
|
||||
""" Incoming email in plaintext should be stored as html """
|
||||
mail = self.format(test_mail_data.MAIL_TEMPLATE_PLAINTEXT, email_from='"Sylvie Lelitre" <test.sylvie.lelitre@agrolait.com>', to='generic@test.com')
|
||||
|
||||
Reference in New Issue
Block a user