Mailing List Archive

bpo-42892: fix email multipart attribute error (GH-26903) (GH-27492)
https://github.com/python/cpython/commit/6f950023c6a2168b229363d75f59a24ecdd66d19
commit: 6f950023c6a2168b229363d75f59a24ecdd66d19
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
committer: ambv <lukasz@langa.pl>
date: 2021-07-30T19:27:06+02:00
summary:

bpo-42892: fix email multipart attribute error (GH-26903) (GH-27492)

(cherry picked from commit e3f877c32d7cccb734f45310f26beeec793364ce)

Co-authored-by: andrei kulakov <andrei.avk@gmail.com>

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`.

_______________________________________________
Python-checkins mailing list
Python-checkins@python.org
https://mail.python.org/mailman/listinfo/python-checkins