bpo-42892: fix email multipart attribute error (GH-26903)
![](https://secure.gravatar.com/avatar/cc7737cd64a84f1b5c61a160798e97ee.jpg?s=120&d=mm&r=g)
https://github.com/python/cpython/commit/e3f877c32d7cccb734f45310f26beeec793... commit: e3f877c32d7cccb734f45310f26beeec793364ce branch: main author: andrei kulakov <andrei.avk@gmail.com> committer: ambv <lukasz@langa.pl> date: 2021-07-30T19:05:49+02:00 summary: bpo-42892: fix email multipart attribute error (GH-26903) files: A Misc/NEWS.d/next/Library/2021-06-24-19-16-20.bpo-42892.qvRNhI.rst M Lib/email/message.py M Lib/test/test_email/test_message.py 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..920a3d6a9cb91b 100644 --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -487,10 +487,14 @@ def message_as_iter_attachment(self, body_parts, attachments, parts, msg): self.assertEqual(list(m.iter_attachments()), attachments) 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] - self.assertEqual(list(m.iter_parts()), parts) + iter_parts = list(m.iter_parts()) if _is_multipart_msg(msg) else [] + self.assertEqual(iter_parts, parts) class _TestContentManager: def get_content(self, msg, *args, **kw): @@ -923,6 +927,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 <email@email.au> + MIME-Version: 1.0 + To: email@email.com <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 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..3c70b0534ecabf --- /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 :class:`email.message.EmailMessage`.
participants (1)
-
ambv