Skip to content

Commit

Permalink
Now python 3 compatible
Browse files Browse the repository at this point in the history
  • Loading branch information
thrawn01 committed Sep 20, 2019
1 parent f87cbfd commit 96fadc8
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 46 deletions.
43 changes: 28 additions & 15 deletions flanker/mime/message/part.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,8 @@ def _encode_charset(preferred_charset, text):
def _encode_transfer_encoding(encoding, body):
if six.PY3:
if encoding == 'quoted-printable':
body = fix_leading_dot(quopri.encodestring(body, quotetabs=False))
body = quopri.encodestring(body, quotetabs=False)
body = fix_leading_dot(body)
return body.decode('utf-8')

if encoding == 'base64':
Expand All @@ -647,7 +648,8 @@ def _encode_transfer_encoding(encoding, body):
return body

if encoding == 'quoted-printable':
return fix_leading_dot(quopri.encodestring(body, quotetabs=False))
body = quopri.encodestring(body, quotetabs=False)
return fix_leading_dot(body)
elif encoding == 'base64':
return _email.encode_base64(body)
else:
Expand All @@ -668,22 +670,27 @@ def fix_leading_dot(s):
We have observed some remote SMTP servers have an intermittent obscure bug
where the leading '.' is removed according to the above spec. Even when the '.'
is obviously within the bounds of a mime part. To combat this we convert any
leading '.' to a '=2E'
is obviously within the bounds of a mime part, and with our sending SMTP
clients dot stuffing the line. To combat this we convert any leading '.'
to a '=2E'.
"""
infp = StringIO(s)
outfp = StringIO()
infp = six.BytesIO(s)
outfp = six.BytesIO()

# TODO(thrawn01): We could scan the entire string looking for leading '.'
# If none found return the original string. This would save memory at the
# expense of some additional processing

dot = b"."
if six.PY3:
dot = ord('.')

while 1:
line = infp.readline()
if not line:
break

if line[0] == '.':
if line[0] == dot:
line = _quote_and_cut(line)

outfp.write(line)
Expand All @@ -697,8 +704,7 @@ def _quote_and_cut(ln):
cut the line in half without dividing any quoted characters and
conforming to the quoted-printable RFC in regards to ending characters.
"""
q = quopri.quote(ln[0])
ln = q + ln[1:]
ln = quopri.quote(ln[0:1]) + ln[1:]

# If the line is under the 76 + '\n' character limit
if len(ln) <= 77:
Expand All @@ -719,25 +725,32 @@ def _quote_and_cut(ln):
if pos > len(ln)/2:
break

if six.PY3:
c = bytes((c,))

# Should be a quoted character
if c == '=':
if c == b'=':
# Peak ahead, do the next 2 chars appear to be a hex values?
if quopri.ishex(ln[pos+1]) and quopri.ishex(ln[pos+2]):
if quopri.ishex(ln[pos+1:pos+3]):
in_quote = 1
continue

new_line = ln[:pos]
next_line = ln[pos:]

# If new line ends with a :space or :tab
if new_line[-1:] in ' \t':
if new_line[-1:] in b' \t':
new_line = new_line[:-1] + quopri.quote(new_line[-1:])

dot = b'.'
if six.PY3:
dot = ord('.')

# If the next line starts with a '.'
if next_line[0] == '.':
next_line = quopri.quote(next_line[0]) + next_line[1:]
if next_line[0] == dot:
next_line = quopri.quote(next_line[0:1]) + next_line[1:]

return new_line + "=\n" + next_line
return new_line + b"=\n" + next_line


def _choose_text_encoding(charset, preferred_encoding, body):
Expand Down
62 changes: 31 additions & 31 deletions tests/mime/message/headers/part_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,133 +5,133 @@

STRINGS = (
# Some normal strings
('', ''),
('hello', 'hello'),
('''hello
(b'', ''),
(b'hello', 'hello'),
(b'''hello
there
world''', '''hello
there
world'''),
('''hello
(b'''hello
there
world
''', '''hello
there
world
'''),
('\201\202\203', '=81=82=83'),
(b'\201\202\203', '=81=82=83'),
# Add some trailing MUST QUOTE strings
('hello ', 'hello=20'),
('hello\t', 'hello=09'),
(b'hello ', 'hello=20'),
(b'hello\t', 'hello=09'),

# Some long lines. First, a single line of 108 characters
('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\xd8\xd9\xda\xdb\xdc\xdd\xde\xdfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
(b'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\xd8\xd9\xda\xdb\xdc\xdd\xde\xdfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'''xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=D8=D9=DA=DB=DC=DD=DE=DFx=
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'''),

# A line of exactly 76 characters, no soft line break should be needed
('yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy',
(b'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy',
'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'),

# A line of 77 characters, forcing a soft line break at position 75,
# and a second line of exactly 2 characters (because the soft line
# break `=' sign counts against the line length limit).
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
'''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=
zz'''),

# A line of 151 characters, forcing a soft line break at position 75,
# with a second line of exactly 76 characters and no trailing =
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
'''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'''),

# A string containing a hard line break, but which the first line is
# 151 characters and the second line is exactly 76 characters. This
# should leave us with three lines, the first which has a soft line
# break, and which the second and third do not.
('''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
(b'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz''',
'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'''),

# Lines that end with space or tab should be quoted
('yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy ',
(b'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy ',
'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=
=20'''),

# Lines that end with a partial quoted character
('yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=y',
(b'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=y',
'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=
=3Dy'''),

# Lines that lead with a dot '.' should have the dot quoted
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.z',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.z',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n' +
'=2Ez'),

# Lines that end with a dot '.' are not quoted
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.zz',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.zz',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.=\n' +
'zz'),

# Lines that lead with a dot '.' should have the dot quoted and cut
# if the quoted line is longer than 76 characters.
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n' +
'=2Ezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\nzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n' +
'zz'),

# Respect quoted characters when considering leading '.'
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
'.\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
b'.\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n' +
'=2E=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=7F=\n' +
'=7F=7F=7F'),

# Should cut somewhere near the middle of the line
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
'.quick brown fox, quick brown cat, quick hot dog, quick read dog, quick white bird',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
b'.quick brown fox, quick brown cat, quick hot dog, quick read dog, quick white bird',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n'
'=2Equick brown fox, quick brown cat, qui=\n' +
'ck hot dog, quick read dog, quick whi=\n'
+ 'te bird'),

# Respect quoted character when considering where to cut
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
'.quick brown fox, quick brown cat\x7f\x7f\x7f\x7f\x7f, quick read dog, quick white bird',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
b'.quick brown fox, quick brown cat\x7f\x7f\x7f\x7f\x7f, quick read dog, quick white bird',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n' +
'=2Equick brown fox, quick brown cat=7F=7F=\n' +
'=7F=7F=7F, quick read dog, quick whi=\n' +
'te bird'),

# Avoid considering non quoted characters when cutting
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
'.quick brown fox, quick brown cat=20=================, quick read dog, quick white bird',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
b'.quick brown fox, quick brown cat=20=================, quick read dog, quick white bird',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n' +
'=2Equick brown fox, quick brown cat=3D20=\n' +
'=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\n' +
'=3D=3D=3D=3D=3D, quick read dog, quick white bird'),

# Should quote leading '.' if the cut results in a '.' on the next line
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
'.quick brown fox, quick brown cat..................... quick read dog, quick white bird',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
b'.quick brown fox, quick brown cat..................... quick read dog, quick white bird',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n' +
'=2Equick brown fox, quick brown cat.....=\n' +
'=2E............... quick read dog, quic=\n' +
'k white bird'),

# Should quote :space if the cut results in a :space at the end of the next line
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
'.quick brown fox, quick brown cat quick read dog, quick white bird',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
b'.quick brown fox, quick brown cat quick read dog, quick white bird',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n' +
'=2Equick brown fox, quick brown cat =20=\n' +
' quick read dog, quic=\n' +
'k white bird'),
# Should quote :tab if the cut results in a :tab at the end of the next line
('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
'.quick brown fox, quick brown cat \t quick read dog, quick white bird',
(b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
b'.quick brown fox, quick brown cat \t quick read dog, quick white bird',
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=\n' +
'=2Equick brown fox, quick brown cat =09=\n' +
' quick read dog, quic=\n' +
Expand Down

0 comments on commit 96fadc8

Please sign in to comment.