Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions Lib/email/feedparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,10 +504,9 @@ def _parse_headers(self, lines):
self._input.unreadline(line)
return
else:
# Weirdly placed unix-from line. Note this as a defect
# and ignore it.
# Weirdly placed unix-from line.
defect = errors.MisplacedEnvelopeHeaderDefect(line)
self._cur.defects.append(defect)
self.policy.handle_defect(self._cur, defect)
continue
# Split the line on the colon separating field name from value.
# There will always be a colon, because if there wasn't the part of
Expand All @@ -519,7 +518,7 @@ def _parse_headers(self, lines):
# message. Track the error but keep going.
if i == 0:
defect = errors.InvalidHeaderDefect("Missing header name.")
self._cur.defects.append(defect)
self.policy.handle_defect(self._cur, defect)
continue

assert i>0, "_parse_headers fed line with no : and no leading WS"
Expand Down
43 changes: 41 additions & 2 deletions Lib/test/test_email/test_defect_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ class TestDefectsBase:
def _raise_point(self, defect):
yield

def get_defects(self, obj):
return obj.defects

def check_defect(self, defect, string):
msg = None
with self._raise_point(defect):
msg = self._str_msg(string)
self.assertEqual(len(self.get_defects(msg)), 1)
self.assertDefectsEqual(self.get_defects(msg), [defect])
return msg

def test_same_boundary_inner_outer(self):
source = textwrap.dedent("""\
Subject: XX
Expand Down Expand Up @@ -126,12 +137,10 @@ def test_multipart_invalid_cte(self):
errors.InvalidMultipartContentTransferEncodingDefect)

def test_multipart_no_cte_no_defect(self):
if self.raise_expected: return
msg = self._str_msg(self.multipart_msg.format(''))
self.assertEqual(len(self.get_defects(msg)), 0)

def test_multipart_valid_cte_no_defect(self):
if self.raise_expected: return
for cte in ('7bit', '8bit', 'BINary'):
msg = self._str_msg(
self.multipart_msg.format("\nContent-Transfer-Encoding: "+cte))
Expand Down Expand Up @@ -300,8 +309,38 @@ def test_missing_ending_boundary(self):
self.assertDefectsEqual(self.get_defects(msg),
[errors.CloseBoundaryNotFoundDefect])

def test_line_beginning_colon(self):
msg = self.check_defect(errors.InvalidHeaderDefect,
'Subject: Dummy subject\r\n'
': faulty header line\r\n'
'\r\n'
'body\r\n'
)
if msg:
self.assertEqual(msg.items(), [('Subject', 'Dummy subject')])
self.assertEqual(msg.get_payload(), 'body\r\n')

def test_misplaced_envelope(self):
msg = self.check_defect(errors.MisplacedEnvelopeHeaderDefect,
'Subject: Dummy subject\r\n'
'From wtf\r\n'
'To: abc\r\n'
'\r\n'
'body\r\n'
)
if msg:
headers = [('Subject', 'Dummy subject'), ('To', 'abc')]
self.assertEqual(msg.items(), headers)
self.assertEqual(msg.get_payload(), 'body\r\n')


class TestCompat32(TestDefectsBase, TestEmailBase):

policy = policy.compat32


class TestDefectDetection(TestDefectsBase, TestEmailBase):
pass

def get_defects(self, obj):
return obj.defects
Expand Down
68 changes: 0 additions & 68 deletions Lib/test/test_email/test_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -2261,50 +2261,6 @@ def test_multipart_no_boundary(self):
self.assertIsInstance(msg.defects[1],
errors.MultipartInvariantViolationDefect)

multipart_msg = textwrap.dedent("""\
Date: Wed, 14 Nov 2007 12:56:23 GMT
From: [email protected]
To: [email protected]
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==--
""")

# test_defect_handling
def test_multipart_invalid_cte(self):
msg = self._str_msg(
self.multipart_msg.format("\nContent-Transfer-Encoding: base64"))
self.assertEqual(len(msg.defects), 1)
self.assertIsInstance(msg.defects[0],
errors.InvalidMultipartContentTransferEncodingDefect)

# test_defect_handling
def test_multipart_no_cte_no_defect(self):
msg = self._str_msg(self.multipart_msg.format(''))
self.assertEqual(len(msg.defects), 0)

# test_defect_handling
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: {}".format(cte)))
self.assertEqual(len(msg.defects), 0)

# test_headerregistry.TestContentTypeHeader invalid_1 and invalid_2.
def test_invalid_content_type(self):
eq = self.assertEqual
Expand Down Expand Up @@ -2381,30 +2337,6 @@ def test_missing_start_boundary(self):
self.assertIsInstance(bad.defects[0],
errors.StartBoundaryNotFoundDefect)

# test_defect_handling
def test_first_line_is_continuation_header(self):
eq = self.assertEqual
m = ' Line 1\nSubject: test\n\nbody'
msg = email.message_from_string(m)
eq(msg.keys(), ['Subject'])
eq(msg.get_payload(), 'body')
eq(len(msg.defects), 1)
self.assertDefectsEqual(msg.defects,
[errors.FirstHeaderLineIsContinuationDefect])
eq(msg.defects[0].line, ' Line 1\n')

# test_defect_handling
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(msg.defects,
[errors.MissingHeaderBodySeparatorDefect])

def test_string_payload_with_extra_space_after_cte(self):
# https://github.com/python/cpython/issues/98188
cte = "base64 "
Expand Down
Loading