From 81bc2c14fea2c96ba2d97037183c33874797e128 Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Thu, 24 Jun 2021 15:03:05 -0400 Subject: [PATCH 1/7] Fix an attribute error caused by a malformed msg --- Lib/email/message.py | 4 +-- Lib/test/test_email/test_message.py | 42 ++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Lib/email/message.py b/Lib/email/message.py index db30d9a1708992..6752ce0fa13825 100644 --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -982,7 +982,7 @@ def _find_body(self, part, preferencelist): if subtype in preferencelist: yield (preferencelist.index(subtype), part) return - if maintype != 'multipart': + if maintype != 'multipart' or not self.is_multipart(): return if subtype != 'related': for subpart in part.iter_parts(): @@ -1087,7 +1087,7 @@ def iter_parts(self): Return an empty iterator for a non-multipart. """ - if self.get_content_maintype() == 'multipart': + if self.is_multipart(): yield from self.get_payload() def get_content(self, *args, content_manager=None, **kw): diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py index 7aaf780c042b03..91306e1be9cbcb 100644 --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -419,7 +419,8 @@ class TestEmailMessageBase: From: robot@examp.com this is a message body. - """)), + """), + ), 'mixed_text_message_rfc822': ( (None, None, 1), @@ -444,8 +445,8 @@ class TestEmailMessageBase: this is a message body. --===-- - """)), - + """), + ), } def message_as_get_body(self, body_parts, attachments, parts, msg): @@ -486,11 +487,15 @@ def message_as_iter_attachment(self, body_parts, attachments, parts, msg): attachments = [allparts[n] for n in attachments] self.assertEqual(list(m.iter_attachments()), attachments) + def _is_multipart_msg(self, msg): + return 'Content-Type: multipart' in msg + def message_as_iter_parts(self, body_parts, attachments, parts, msg): m = self._str_msg(msg) allparts = list(m.walk()) parts = [allparts[n] for n in parts] - self.assertEqual(list(m.iter_parts()), parts) + x = (list(m.iter_parts()) if self._is_multipart_msg(msg) else [], parts) + self.assertEqual(*x) class _TestContentManager: def get_content(self, msg, *args, **kw): @@ -500,6 +505,7 @@ def set_content(self, msg, *args, **kw): self.args = args self.kw = kw + def test_get_content_with_cm(self): m = self._str_msg('') cm = self._TestContentManager() @@ -923,6 +929,34 @@ def test_folding_with_utf8_encoding_8(self): b'123456789-123456789\n 123456789 Hello ' b'=?utf-8?q?W=C3=B6rld!?= 123456789 123456789\n\n') + def test_get_body_malformed(self): + """test for bpo-42892""" + msg = textwrap.dedent("""\ + Message-ID: <674392CA.4347091@email.au> + Date: Wed, 08 Nov 2017 08:50:22 +0700 + From: Foo Bar + MIME-Version: 1.0 + To: email@email.com + Subject: Python Email + Content-Type: multipart/mixed; + boundary="------------879045806563892972123996" + X-Global-filter:Messagescannedforspamandviruses:passedalltests + + This is a multi-part message in MIME format. + --------------879045806563892972123996 + Content-Type: text/plain; charset=ISO-8859-1; format=flowed + Content-Transfer-Encoding: 7bit + + Your message is ready to be sent with the following file or link + attachments: + XU89 - 08.11.2017 + """) + m = self._str_msg(msg) + # In bpo-42892, this would raise + # AttributeError: 'str' object has no attribute 'is_attachment' + m.get_body() + + class TestMIMEPart(TestEmailMessageBase, TestEmailBase): # Doing the full test run here may seem a bit redundant, since the two # classes are almost identical. But what if they drift apart? So we do From df240f88765b8a99cc0eb22cd9ac88381439a3e9 Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Thu, 24 Jun 2021 15:05:17 -0400 Subject: [PATCH 2/7] revert formatting change --- Lib/test/test_email/test_message.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py index 91306e1be9cbcb..4fdec40c04fb9f 100644 --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -419,8 +419,7 @@ class TestEmailMessageBase: From: robot@examp.com this is a message body. - """), - ), + """)), 'mixed_text_message_rfc822': ( (None, None, 1), @@ -445,8 +444,8 @@ class TestEmailMessageBase: this is a message body. --===-- - """), - ), + """)), + } def message_as_get_body(self, body_parts, attachments, parts, msg): From f8da1875e9f09a15906859ec9baf8ca38bdfba7f Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Thu, 24 Jun 2021 15:08:25 -0400 Subject: [PATCH 3/7] style update in unit test --- Lib/test/test_email/test_message.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py index 4fdec40c04fb9f..032a8e662bec02 100644 --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -493,8 +493,8 @@ def message_as_iter_parts(self, body_parts, attachments, parts, msg): m = self._str_msg(msg) allparts = list(m.walk()) parts = [allparts[n] for n in parts] - x = (list(m.iter_parts()) if self._is_multipart_msg(msg) else [], parts) - self.assertEqual(*x) + iter_parts = list(m.iter_parts()) if self._is_multipart_msg(msg) else [] + self.assertEqual(iter_parts, parts) class _TestContentManager: def get_content(self, msg, *args, **kw): From f52c03c1c15e03efdf1e30955e490234b4fed582 Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Thu, 24 Jun 2021 15:09:21 -0400 Subject: [PATCH 4/7] stray blank --- Lib/test/test_email/test_message.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py index 032a8e662bec02..7b3e1f26b62c80 100644 --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -504,7 +504,6 @@ def set_content(self, msg, *args, **kw): self.args = args self.kw = kw - def test_get_content_with_cm(self): m = self._str_msg('') cm = self._TestContentManager() From f9325ed9ec55c7e964b85483b1205384f83aad23 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 24 Jun 2021 19:16:21 +0000 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst diff --git a/Misc/NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst b/Misc/NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst new file mode 100644 index 00000000000000..af07b86de140a6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst @@ -0,0 +1 @@ +Fixed an exception thrown while parsing a malformed multipart email by :cls:`email.message.EmailMessage`. \ No newline at end of file From 02dddd8a878d8ed0c7fb6d0d97f2933326f05a4c Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Thu, 24 Jun 2021 23:43:58 -0400 Subject: [PATCH 6/7] Fix doc link to class --- .../next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst b/Misc/NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst index af07b86de140a6..3c70b0534ecabf 100644 --- a/Misc/NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst +++ b/Misc/NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst @@ -1 +1 @@ -Fixed an exception thrown while parsing a malformed multipart email by :cls:`email.message.EmailMessage`. \ No newline at end of file +Fixed an exception thrown while parsing a malformed multipart email by :class:`email.message.EmailMessage`. From 4b89430ac4872e3ee17e373496b2d40ef4ce8304 Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Sun, 27 Jun 2021 21:51:17 -0400 Subject: [PATCH 7/7] moved _is_multipart_msg into message_as_iter_parts() --- Lib/test/test_email/test_message.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py index 7b3e1f26b62c80..920a3d6a9cb91b 100644 --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -486,14 +486,14 @@ def message_as_iter_attachment(self, body_parts, attachments, parts, msg): attachments = [allparts[n] for n in attachments] self.assertEqual(list(m.iter_attachments()), attachments) - def _is_multipart_msg(self, msg): - return 'Content-Type: multipart' in msg - def message_as_iter_parts(self, body_parts, attachments, parts, msg): + def _is_multipart_msg(msg): + return 'Content-Type: multipart' in msg + m = self._str_msg(msg) allparts = list(m.walk()) parts = [allparts[n] for n in parts] - iter_parts = list(m.iter_parts()) if self._is_multipart_msg(msg) else [] + iter_parts = list(m.iter_parts()) if _is_multipart_msg(msg) else [] self.assertEqual(iter_parts, parts) class _TestContentManager: