[Python-checkins] [3.7] bpo-33972: Fix EmailMessage.iter_attachments raising AttributeError. (GH-14119) (GH-14381)

Miss Islington (bot) webhook-mailer at python.org
Tue Jun 25 14:40:46 EDT 2019


https://github.com/python/cpython/commit/01b23948038d35b119cededd149110231ecce00d
commit: 01b23948038d35b119cededd149110231ecce00d
branch: 3.7
author: Abhilash Raj <maxking at users.noreply.github.com>
committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
date: 2019-06-25T11:40:41-07:00
summary:

[3.7] bpo-33972: Fix EmailMessage.iter_attachments raising AttributeError. (GH-14119) (GH-14381)



When certain malformed messages have content-type set to 'mulitpart/*' but
still have a single part body, iter_attachments can raise AttributeError. This
patch fixes it by returning a None value instead when the body is single part.
(cherry picked from commit 02257012f6d3821d816cb6a7e8461a88a05b9a08)

Co-authored-by: Abhilash Raj <maxking at users.noreply.github.com>



https://bugs.python.org/issue33972

files:
A Misc/NEWS.d/next/Library/2019-06-15-14-39-50.bpo-33972.XxnNPw.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 b6512f2198af..126260261796 100644
--- a/Lib/email/message.py
+++ b/Lib/email/message.py
@@ -1041,7 +1041,16 @@ def iter_attachments(self):
         maintype, subtype = self.get_content_type().split('/')
         if maintype != 'multipart' or subtype == 'alternative':
             return
-        parts = self.get_payload().copy()
+        payload = self.get_payload()
+        # Certain malformed messages can have content type set to `multipart/*`
+        # but still have single part body, in which case payload.copy() can
+        # fail with AttributeError.
+        try:
+            parts = payload.copy()
+        except AttributeError:
+            # payload is not a list, it is most probably a string.
+            return
+
         if maintype == 'multipart' and subtype == 'related':
             # For related, we treat everything but the root as an attachment.
             # The root may be indicated by 'start'; if there's no start or we
diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py
index 5dc46e1b812c..fab97d91882b 100644
--- a/Lib/test/test_email/test_message.py
+++ b/Lib/test/test_email/test_message.py
@@ -929,6 +929,15 @@ def test_set_content_does_not_add_MIME_Version(self):
         m.set_content(content_manager=cm)
         self.assertNotIn('MIME-Version', m)
 
+    def test_string_payload_with_multipart_content_type(self):
+        msg = message_from_string(textwrap.dedent("""\
+        Content-Type: multipart/mixed; charset="utf-8"
+
+        sample text
+        """), policy=policy.default)
+        attachments = msg.iter_attachments()
+        self.assertEqual(list(attachments), [])
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2019-06-15-14-39-50.bpo-33972.XxnNPw.rst b/Misc/NEWS.d/next/Library/2019-06-15-14-39-50.bpo-33972.XxnNPw.rst
new file mode 100644
index 000000000000..ded1570b308f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-06-15-14-39-50.bpo-33972.XxnNPw.rst
@@ -0,0 +1,2 @@
+Email with single part but content-type set to ``multipart/*`` doesn't raise
+AttributeError anymore.



More information about the Python-checkins mailing list