Skip to content

Commit e3f877c

Browse files
authored
bpo-42892: fix email multipart attribute error (pythonGH-26903)
1 parent 4bd9caa commit e3f877c

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

Lib/email/message.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ def _find_body(self, part, preferencelist):
982982
if subtype in preferencelist:
983983
yield (preferencelist.index(subtype), part)
984984
return
985-
if maintype != 'multipart':
985+
if maintype != 'multipart' or not self.is_multipart():
986986
return
987987
if subtype != 'related':
988988
for subpart in part.iter_parts():
@@ -1087,7 +1087,7 @@ def iter_parts(self):
10871087
10881088
Return an empty iterator for a non-multipart.
10891089
"""
1090-
if self.get_content_maintype() == 'multipart':
1090+
if self.is_multipart():
10911091
yield from self.get_payload()
10921092

10931093
def get_content(self, *args, content_manager=None, **kw):

Lib/test/test_email/test_message.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,10 +487,14 @@ def message_as_iter_attachment(self, body_parts, attachments, parts, msg):
487487
self.assertEqual(list(m.iter_attachments()), attachments)
488488

489489
def message_as_iter_parts(self, body_parts, attachments, parts, msg):
490+
def _is_multipart_msg(msg):
491+
return 'Content-Type: multipart' in msg
492+
490493
m = self._str_msg(msg)
491494
allparts = list(m.walk())
492495
parts = [allparts[n] for n in parts]
493-
self.assertEqual(list(m.iter_parts()), parts)
496+
iter_parts = list(m.iter_parts()) if _is_multipart_msg(msg) else []
497+
self.assertEqual(iter_parts, parts)
494498

495499
class _TestContentManager:
496500
def get_content(self, msg, *args, **kw):
@@ -923,6 +927,34 @@ def test_folding_with_utf8_encoding_8(self):
923927
b'123456789-123456789\n 123456789 Hello '
924928
b'=?utf-8?q?W=C3=B6rld!?= 123456789 123456789\n\n')
925929

930+
def test_get_body_malformed(self):
931+
"""test for bpo-42892"""
932+
msg = textwrap.dedent("""\
933+
Message-ID: <674392CA.4347091@email.au>
934+
Date: Wed, 08 Nov 2017 08:50:22 +0700
935+
From: Foo Bar <email@email.au>
936+
MIME-Version: 1.0
937+
To: email@email.com <email@email.com>
938+
Subject: Python Email
939+
Content-Type: multipart/mixed;
940+
boundary="------------879045806563892972123996"
941+
X-Global-filter:Messagescannedforspamandviruses:passedalltests
942+
943+
This is a multi-part message in MIME format.
944+
--------------879045806563892972123996
945+
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
946+
Content-Transfer-Encoding: 7bit
947+
948+
Your message is ready to be sent with the following file or link
949+
attachments:
950+
XU89 - 08.11.2017
951+
""")
952+
m = self._str_msg(msg)
953+
# In bpo-42892, this would raise
954+
# AttributeError: 'str' object has no attribute 'is_attachment'
955+
m.get_body()
956+
957+
926958
class TestMIMEPart(TestEmailMessageBase, TestEmailBase):
927959
# Doing the full test run here may seem a bit redundant, since the two
928960
# classes are almost identical. But what if they drift apart? So we do
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed an exception thrown while parsing a malformed multipart email by :class:`email.message.EmailMessage`.

0 commit comments

Comments
 (0)