summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_email/test_parser.py
diff options
context:
space:
mode:
authorR David Murray <rdmurray@bitdance.com>2012-05-28 01:23:34 (GMT)
committerR David Murray <rdmurray@bitdance.com>2012-05-28 01:23:34 (GMT)
commit80e0aee95b8c4a7da8a1b794793a9e9537d021cf (patch)
tree36bc2ab00ee8552d10ea4b92f80f9bf9355a55fd /Lib/test/test_email/test_parser.py
parentadbdcdbd9527a3c4000cd4ff0678ff60151f1f79 (diff)
downloadcpython-80e0aee95b8c4a7da8a1b794793a9e9537d021cf.zip
cpython-80e0aee95b8c4a7da8a1b794793a9e9537d021cf.tar.gz
cpython-80e0aee95b8c4a7da8a1b794793a9e9537d021cf.tar.bz2
#1672568: email now registers defects for base64 payload format errors.
Which also means that it is now producing *something* for any base64 payload, which is what leads to the couple of older test changes in test_email. This is a slightly backward incompatible behavior change, but the new behavior is so much more useful than the old (you can now *reliably* detect errors, and any program that was detecting errors by sniffing for a base64 return from get_payload(decode=True) and then doing its own error-recovery decode will just get the error-recovery decode right away). So this seems to me to be worth the small risk inherent in this behavior change. This patch also refactors the defect tests into a separate test file, since they are no longer just parser tests.
Diffstat (limited to 'Lib/test/test_email/test_parser.py')
-rw-r--r--Lib/test/test_email/test_parser.py256
1 files changed, 0 insertions, 256 deletions
diff --git a/Lib/test/test_email/test_parser.py b/Lib/test/test_email/test_parser.py
index f58e7c1..3abd11a 100644
--- a/Lib/test/test_email/test_parser.py
+++ b/Lib/test/test_email/test_parser.py
@@ -1,9 +1,6 @@
import io
import email
-import textwrap
import unittest
-from email._policybase import Compat32
-from email import errors
from email.message import Message
from test.test_email import TestEmailBase
@@ -35,258 +32,5 @@ class TestCustomMessage(TestEmailBase):
# XXX add tests for other functions that take Message arg.
-class TestMessageDefectDetectionBase:
-
- dup_boundary_msg = textwrap.dedent("""\
- Subject: XX
- From: xx@xx.dk
- To: XX
- Mime-version: 1.0
- Content-type: multipart/mixed;
- boundary="MS_Mac_OE_3071477847_720252_MIME_Part"
-
- --MS_Mac_OE_3071477847_720252_MIME_Part
- Content-type: multipart/alternative;
- boundary="MS_Mac_OE_3071477847_720252_MIME_Part"
-
- --MS_Mac_OE_3071477847_720252_MIME_Part
- Content-type: text/plain; charset="ISO-8859-1"
- Content-transfer-encoding: quoted-printable
-
- text
-
- --MS_Mac_OE_3071477847_720252_MIME_Part
- Content-type: text/html; charset="ISO-8859-1"
- Content-transfer-encoding: quoted-printable
-
- <HTML></HTML>
-
- --MS_Mac_OE_3071477847_720252_MIME_Part--
-
- --MS_Mac_OE_3071477847_720252_MIME_Part
- Content-type: image/gif; name="xx.gif";
- Content-disposition: attachment
- Content-transfer-encoding: base64
-
- Some removed base64 encoded chars.
-
- --MS_Mac_OE_3071477847_720252_MIME_Part--
-
- """)
-
- def test_same_boundary_inner_outer(self):
- # XXX better would be to actually detect the duplicate.
- msg = self._str_msg(self.dup_boundary_msg)
- inner = msg.get_payload(0)
- self.assertTrue(hasattr(inner, 'defects'))
- self.assertEqual(len(self.get_defects(inner)), 1)
- self.assertTrue(isinstance(self.get_defects(inner)[0],
- errors.StartBoundaryNotFoundDefect))
-
- def test_same_boundary_inner_outer_raises_on_defect(self):
- with self.assertRaises(errors.StartBoundaryNotFoundDefect):
- self._str_msg(self.dup_boundary_msg,
- policy=self.policy.clone(raise_on_defect=True))
-
- no_boundary_msg = textwrap.dedent("""\
- Date: Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800)
- From: foobar
- Subject: broken mail
- MIME-Version: 1.0
- Content-Type: multipart/report; report-type=delivery-status;
-
- --JAB03225.986577786/zinfandel.lacita.com
-
- One part
-
- --JAB03225.986577786/zinfandel.lacita.com
- Content-Type: message/delivery-status
-
- Header: Another part
-
- --JAB03225.986577786/zinfandel.lacita.com--
- """)
-
- def test_multipart_no_boundary(self):
- msg = self._str_msg(self.no_boundary_msg)
- self.assertTrue(isinstance(msg.get_payload(), str))
- self.assertEqual(len(self.get_defects(msg)), 2)
- self.assertTrue(isinstance(self.get_defects(msg)[0],
- errors.NoBoundaryInMultipartDefect))
- self.assertTrue(isinstance(self.get_defects(msg)[1],
- errors.MultipartInvariantViolationDefect))
-
- def test_multipart_no_boundary_raise_on_defect(self):
- with self.assertRaises(errors.NoBoundaryInMultipartDefect):
- self._str_msg(self.no_boundary_msg,
- policy=self.policy.clone(raise_on_defect=True))
-
- multipart_msg = textwrap.dedent("""\
- Date: Wed, 14 Nov 2007 12:56:23 GMT
- From: foo@bar.invalid
- To: foo@bar.invalid
- Subject: Content-Transfer-Encoding: base64 and multipart
- MIME-Version: 1.0
- Content-Type: multipart/mixed;
- boundary="===============3344438784458119861=="{}
-
- --===============3344438784458119861==
- Content-Type: text/plain
-
- Test message
-
- --===============3344438784458119861==
- Content-Type: application/octet-stream
- Content-Transfer-Encoding: base64
-
- YWJj
-
- --===============3344438784458119861==--
- """)
-
- def test_multipart_invalid_cte(self):
- msg = self._str_msg(
- self.multipart_msg.format("\nContent-Transfer-Encoding: base64"))
- self.assertEqual(len(self.get_defects(msg)), 1)
- self.assertIsInstance(self.get_defects(msg)[0],
- errors.InvalidMultipartContentTransferEncodingDefect)
-
- def test_multipart_invalid_cte_raise_on_defect(self):
- with self.assertRaises(
- errors.InvalidMultipartContentTransferEncodingDefect):
- self._str_msg(
- self.multipart_msg.format(
- "\nContent-Transfer-Encoding: base64"),
- policy=self.policy.clone(raise_on_defect=True))
-
- def test_multipart_no_cte_no_defect(self):
- msg = self._str_msg(self.multipart_msg.format(''))
- self.assertEqual(len(self.get_defects(msg)), 0)
-
- def test_multipart_valid_cte_no_defect(self):
- for cte in ('7bit', '8bit', 'BINary'):
- msg = self._str_msg(
- self.multipart_msg.format("\nContent-Transfer-Encoding: "+cte))
- self.assertEqual(len(self.get_defects(msg)), 0, "cte="+cte)
-
- lying_multipart_msg = textwrap.dedent("""\
- From: "Allison Dunlap" <xxx@example.com>
- To: yyy@example.com
- Subject: 64423
- Date: Sun, 11 Jul 2004 16:09:27 -0300
- MIME-Version: 1.0
- Content-Type: multipart/alternative;
-
- Blah blah blah
- """)
-
- def test_lying_multipart(self):
- msg = self._str_msg(self.lying_multipart_msg)
- self.assertTrue(hasattr(msg, 'defects'))
- self.assertEqual(len(self.get_defects(msg)), 2)
- self.assertTrue(isinstance(self.get_defects(msg)[0],
- errors.NoBoundaryInMultipartDefect))
- self.assertTrue(isinstance(self.get_defects(msg)[1],
- errors.MultipartInvariantViolationDefect))
-
- def test_lying_multipart_raise_on_defect(self):
- with self.assertRaises(errors.NoBoundaryInMultipartDefect):
- self._str_msg(self.lying_multipart_msg,
- policy=self.policy.clone(raise_on_defect=True))
-
- missing_start_boundary_msg = textwrap.dedent("""\
- Content-Type: multipart/mixed; boundary="AAA"
- From: Mail Delivery Subsystem <xxx@example.com>
- To: yyy@example.com
-
- --AAA
-
- Stuff
-
- --AAA
- Content-Type: message/rfc822
-
- From: webmaster@python.org
- To: zzz@example.com
- Content-Type: multipart/mixed; boundary="BBB"
-
- --BBB--
-
- --AAA--
-
- """)
-
- def test_missing_start_boundary(self):
- # The message structure is:
- #
- # multipart/mixed
- # text/plain
- # message/rfc822
- # multipart/mixed [*]
- #
- # [*] This message is missing its start boundary
- outer = self._str_msg(self.missing_start_boundary_msg)
- bad = outer.get_payload(1).get_payload(0)
- self.assertEqual(len(self.get_defects(bad)), 1)
- self.assertTrue(isinstance(self.get_defects(bad)[0],
- errors.StartBoundaryNotFoundDefect))
-
- def test_missing_start_boundary_raise_on_defect(self):
- with self.assertRaises(errors.StartBoundaryNotFoundDefect):
- self._str_msg(self.missing_start_boundary_msg,
- policy=self.policy.clone(raise_on_defect=True))
-
- def test_first_line_is_continuation_header(self):
- msg = self._str_msg(' Line 1\nSubject: test\n\nbody')
- self.assertEqual(msg.keys(), ['Subject'])
- self.assertEqual(msg.get_payload(), 'body')
- self.assertEqual(len(self.get_defects(msg)), 1)
- self.assertDefectsEqual(self.get_defects(msg),
- [errors.FirstHeaderLineIsContinuationDefect])
- self.assertEqual(self.get_defects(msg)[0].line, ' Line 1\n')
-
- def test_first_line_is_continuation_header_raise_on_defect(self):
- with self.assertRaises(errors.FirstHeaderLineIsContinuationDefect):
- self._str_msg(' Line 1\nSubject: test\n\nbody\n',
- policy=self.policy.clone(raise_on_defect=True))
-
- def test_missing_header_body_separator(self):
- # Our heuristic if we see a line that doesn't look like a header (no
- # leading whitespace but no ':') is to assume that the blank line that
- # separates the header from the body is missing, and to stop parsing
- # headers and start parsing the body.
- msg = self._str_msg('Subject: test\nnot a header\nTo: abc\n\nb\n')
- self.assertEqual(msg.keys(), ['Subject'])
- self.assertEqual(msg.get_payload(), 'not a header\nTo: abc\n\nb\n')
- self.assertDefectsEqual(self.get_defects(msg),
- [errors.MissingHeaderBodySeparatorDefect])
-
- def test_missing_header_body_separator_raise_on_defect(self):
- with self.assertRaises(errors.MissingHeaderBodySeparatorDefect):
- self._str_msg('Subject: test\nnot a header\nTo: abc\n\nb\n',
- policy=self.policy.clone(raise_on_defect=True))
-
-
-class TestMessageDefectDetection(TestMessageDefectDetectionBase, TestEmailBase):
-
- def get_defects(self, obj):
- return obj.defects
-
-
-class TestMessageDefectDetectionCapture(TestMessageDefectDetectionBase,
- TestEmailBase):
-
- class CapturePolicy(Compat32):
- captured = None
- def register_defect(self, obj, defect):
- self.captured.append(defect)
-
- def setUp(self):
- self.policy = self.CapturePolicy(captured=list())
-
- def get_defects(self, obj):
- return self.policy.captured
-
-
if __name__ == '__main__':
unittest.main()