summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorR David Murray <rdmurray@bitdance.com>2012-05-28 02:20:42 (GMT)
committerR David Murray <rdmurray@bitdance.com>2012-05-28 02:20:42 (GMT)
commit7ef3ff3f2ea77f496f5386c3ede74f95001a6009 (patch)
treeab17160f5d03de8fa54f02ceb2b38e3f769156a1
parentd0a0e8e070f1c3c74905627380473f21f5457cfb (diff)
downloadcpython-7ef3ff3f2ea77f496f5386c3ede74f95001a6009.zip
cpython-7ef3ff3f2ea77f496f5386c3ede74f95001a6009.tar.gz
cpython-7ef3ff3f2ea77f496f5386c3ede74f95001a6009.tar.bz2
#12515: email now registers a defect if the MIME end boundary is missing.
This commit also restores the news item for 167256 that it looks like Terry inadvertently deleted. (Either that, or I don't understand now merging works...which is equally possible.)
-rw-r--r--Doc/library/email.errors.rst5
-rw-r--r--Lib/email/errors.py3
-rw-r--r--Lib/email/feedparser.py14
-rw-r--r--Lib/test/test_email/test_defect_handling.py33
-rw-r--r--Misc/NEWS7
5 files changed, 59 insertions, 3 deletions
diff --git a/Doc/library/email.errors.rst b/Doc/library/email.errors.rst
index 2bc3164..acfa6b2 100644
--- a/Doc/library/email.errors.rst
+++ b/Doc/library/email.errors.rst
@@ -73,6 +73,11 @@ this class is *not* an exception!
* :class:`StartBoundaryNotFoundDefect` -- The start boundary claimed in the
:mailheader:`Content-Type` header was never found.
+* :class:`CloseBoundaryNotFoundDefect` -- A start boundary was found, but
+ no corresponding close boundary was ever found.
+
+ .. versionadded: 3.3
+
* :class:`FirstHeaderLineIsContinuationDefect` -- The message had a continuation
line as its first header line.
diff --git a/Lib/email/errors.py b/Lib/email/errors.py
index aa836d4..d80b5b9 100644
--- a/Lib/email/errors.py
+++ b/Lib/email/errors.py
@@ -42,6 +42,9 @@ class NoBoundaryInMultipartDefect(MessageDefect):
class StartBoundaryNotFoundDefect(MessageDefect):
"""The claimed start boundary was never found."""
+class CloseBoundaryNotFoundDefect(MessageDefect):
+ """A start boundary was found, but not the corresponding close boundary."""
+
class FirstHeaderLineIsContinuationDefect(MessageDefect):
"""A message had a continuation line as its first header line."""
diff --git a/Lib/email/feedparser.py b/Lib/email/feedparser.py
index c3a67c0..56f50df 100644
--- a/Lib/email/feedparser.py
+++ b/Lib/email/feedparser.py
@@ -324,6 +324,7 @@ class FeedParser:
capturing_preamble = True
preamble = []
linesep = False
+ close_boundary_seen = False
while True:
line = self._input.readline()
if line is NeedMoreData:
@@ -338,6 +339,7 @@ class FeedParser:
# the closing boundary, then we need to initialize the
# epilogue with the empty string (see below).
if mo.group('end'):
+ close_boundary_seen = True
linesep = mo.group('linesep')
break
# We saw an inter-part boundary. Were we in the preamble?
@@ -406,7 +408,6 @@ class FeedParser:
# We've seen either the EOF or the end boundary. If we're still
# capturing the preamble, we never saw the start boundary. Note
# that as a defect and store the captured text as the payload.
- # Everything from here to the EOF is epilogue.
if capturing_preamble:
defect = errors.StartBoundaryNotFoundDefect()
self.policy.handle_defect(self._cur, defect)
@@ -418,8 +419,15 @@ class FeedParser:
continue
self._cur.epilogue = EMPTYSTRING.join(epilogue)
return
- # If the end boundary ended in a newline, we'll need to make sure
- # the epilogue isn't None
+ # If we're not processing the preamble, then we might have seen
+ # EOF without seeing that end boundary...that is also a defect.
+ if not close_boundary_seen:
+ defect = errors.CloseBoundaryNotFoundDefect()
+ self.policy.handle_defect(self._cur, defect)
+ return
+ # Everything from here to the EOF is epilogue. If the end boundary
+ # ended in a newline, we'll need to make sure the epilogue isn't
+ # None
if linesep:
epilogue = ['']
else:
diff --git a/Lib/test/test_email/test_defect_handling.py b/Lib/test/test_email/test_defect_handling.py
index d3df1e4..fe72599 100644
--- a/Lib/test/test_email/test_defect_handling.py
+++ b/Lib/test/test_email/test_defect_handling.py
@@ -278,6 +278,39 @@ class TestMessageDefectDetectionBase:
with self.assertRaises(errors.InvalidBase64CharactersDefect):
msg.get_payload(decode=True)
+ missing_ending_boundary = textwrap.dedent("""\
+ To: 1@harrydomain4.com
+ Subject: Fwd: 1
+ MIME-Version: 1.0
+ Content-Type: multipart/alternative;
+ boundary="------------000101020201080900040301"
+
+ --------------000101020201080900040301
+ Content-Type: text/plain; charset=ISO-8859-1
+ Content-Transfer-Encoding: 7bit
+
+ Alternative 1
+
+ --------------000101020201080900040301
+ Content-Type: text/html; charset=ISO-8859-1
+ Content-Transfer-Encoding: 7bit
+
+ Alternative 2
+
+ """)
+
+ def test_missing_ending_boundary(self):
+ msg = self._str_msg(self.missing_ending_boundary)
+ self.assertEqual(len(msg.get_payload()), 2)
+ self.assertEqual(msg.get_payload(1).get_payload(), 'Alternative 2\n')
+ self.assertDefectsEqual(self.get_defects(msg),
+ [errors.CloseBoundaryNotFoundDefect])
+
+ def test_missing_ending_boundary_raise_on_defect(self):
+ with self.assertRaises(errors.CloseBoundaryNotFoundDefect):
+ self._str_msg(self.missing_ending_boundary,
+ policy=self.policy.clone(raise_on_defect=True))
+
class TestMessageDefectDetection(TestMessageDefectDetectionBase, TestEmailBase):
diff --git a/Misc/NEWS b/Misc/NEWS
index 4b70d45..3e4157e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -49,9 +49,16 @@ Core and Builtins
Library
-------
+- Issue #12515: email now registers a defect if it gets to EOF while parsing
+ a MIME part without seeing the closing MIME boundary.
+
- Issue12510: Attempting to get invalid tooltip no longer closes Idle.
Original patch by Roger Serwy.
+- Issue #1672568: email now always decodes base64 payloads, adding padding and
+ ignoring non-base64-alphabet characters if needed, and registering defects
+ for any such problems.
+
- Issue #14925: email now registers a defect when the parser decides that there
is a missing header/body separator line. MalformedHeaderDefect, which the
existing code would never actually generate, is deprecated.