Index: Lib/email/test/test_email.py =================================================================== --- Lib/email/test/test_email.py (revision 63020) +++ Lib/email/test/test_email.py (working copy) @@ -2550,7 +2550,11 @@ eq(headers, ['A', 'B', 'CC']) eq(msg.get_payload(), 'body') + def test_multipart_with_invalid_cte(self): + msg = self._msgobj("msg_45.txt") + self.assertNotEqual(0, len(msg.defects)) + class TestBase64(unittest.TestCase): def test_len(self): Index: Lib/email/errors.py =================================================================== --- Lib/email/errors.py (revision 63020) +++ Lib/email/errors.py (working copy) @@ -55,3 +55,6 @@ class MultipartInvariantViolationDefect(MessageDefect): """A message claimed to be a multipart but no subparts were found.""" + +class InvalidContentTransferEncoding(MessageDefect): + """A Content-Transfer-Encoding for multpart is invalid.""" Index: Lib/email/feedparser.py =================================================================== --- Lib/email/feedparser.py (revision 63020) +++ Lib/email/feedparser.py (working copy) @@ -209,6 +209,20 @@ # Done with the headers, so parse them and figure out what we're # supposed to see in the body of the message. self._parse_headers(headers) + + + # If an email has an entity of multipart kind, its encoding must be + # either 7bit, 8bit, or binary, says [1]. + # + # [1]: http://tools.ietf.org/html/rfc2045#section-6.4 + # + cte = self._cur.get('Content-Transfer-Encoding') + ct = self._cur.get('Content-Type') + if ct and cte: + if ct.startswith('multipart') and cte not in ['7bit', '8bit', 'binary']: + defect = errors.InvalidContentTransferEncoding() + self._cur.defects.append(defect) + # Headers-only parsing is a backwards compatibility hack, which was # necessary in the older parser, which could throw errors. All # remaining lines in the input are thrown into the message body.