https://github.com/python/cpython/commit/fdec4df45ab69fc25019565992d95b26b4e37523
commit: fdec4df45ab69fc25019565992d95b26b4e37523
branch: main
author: Julian Prolejko <[email protected]>
committer: bitdancer <[email protected]>
date: 2026-10-15T17:29:36-04:00
summary:
gh-159304: Fix AttributeError in email get_body() for nested malformed
multipart (#159306)
MIMEPart._find_body() incorrectly checked self.is_multipart() instead of
part.is_multipart() when recursing.
files:
A Misc/NEWS.d/next/Library/2026-10-13-12-00-00.gh-issue-159304.mFbYq2.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 64e6c1e23cfb47f..093b9012f31666e 100644
--- a/Lib/email/message.py
+++ b/Lib/email/message.py
@@ -1026,7 +1026,7 @@ def _find_body(self, part, preferencelist):
if subtype in preferencelist:
yield (preferencelist.index(subtype), part)
return
- if maintype != 'multipart' or not self.is_multipart():
+ if maintype != 'multipart' or not part.is_multipart():
return
if subtype != 'related':
for subpart in part.iter_parts():
diff --git a/Lib/test/test_email/test_message.py
b/Lib/test/test_email/test_message.py
index 56ad446694d1f88..974b0ceaafbde4e 100644
--- a/Lib/test/test_email/test_message.py
+++ b/Lib/test/test_email/test_message.py
@@ -1081,6 +1081,25 @@ def test_get_body_malformed(self):
# AttributeError: 'str' object has no attribute 'is_attachment'
m.get_body()
+ def test_get_body_malformed_nested_multipart(self):
+ # gh-159304: a nested multipart part without a boundary has a
+ # string payload, which get_body() must not iterate over.
+ msg = textwrap.dedent("""\
+ From: [email protected]
+ To: [email protected]
+ Subject: Malformed
+ Content-Type: multipart/related; boundary=OUTER
+
+ --OUTER
+ Content-Type: multipart/related
+
+ raw body no boundary
+ --OUTER--
+ """)
+ m = self._str_msg(msg)
+ self.assertIsNone(m.get_body(('plain', 'html')))
+ self.assertIs(m.get_body(('related',)), m)
+
def test_get_bytes_payload_with_quoted_printable_encoding(self):
# We use a memoryview to avoid directly changing the private payload
# and to prevent using the dedicated paths for string or bytes objects.
diff --git
a/Misc/NEWS.d/next/Library/2026-10-13-12-00-00.gh-issue-159304.mFbYq2.rst
b/Misc/NEWS.d/next/Library/2026-10-13-12-00-00.gh-issue-159304.mFbYq2.rst
new file mode 100644
index 000000000000000..8f5b61efe039593
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-13-12-00-00.gh-issue-159304.mFbYq2.rst
@@ -0,0 +1,2 @@
+Fix :exc:`AttributeError` in :meth:`email.message.EmailMessage.get_body` when a
+nested ``multipart`` part is malformed and its payload is a string.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]