Skip to content

Commit

Permalink
In Python 2.7, encode strings in add_header() as ASCII (#72)
Browse files Browse the repository at this point in the history
* In Python 2, encode other strings in add_header() calls into ASCII so getting this filename does not cause Unicode errors
* Fix test compatibility in Python3
  • Loading branch information
stevenbuccini authored and amcgregor committed Dec 3, 2016
1 parent aa415c3 commit 3995ef9
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
13 changes: 10 additions & 3 deletions marrow/mailer/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,18 @@ def attach(self, name, data=None, maintype=None, subtype=None,
filename=(filename_charset, filename_language, filename)

if inline:
part.add_header('Content-Disposition', 'inline', filename=filename)
part.add_header('Content-ID', '<%s>' % filename)
if sys.version_info < (3, 0):
part.add_header('Content-Disposition'.encode('utf-8'), 'inline'.encode('utf-8'), filename=filename)
part.add_header('Content-ID'.encode('utf-8'), '<%s>'.encode('utf-8') % filename)
else:
part.add_header('Content-Disposition', 'inline', filename=filename)
part.add_header('Content-ID', '<%s>' % filename)
self.embedded.append(part)
else:
part.add_header('Content-Disposition', 'attachment', filename=filename)
if sys.version_info < (3, 0):
part.add_header('Content-Disposition'.encode('utf-8'), 'attachment'.encode('utf-8'), filename=filename)
else:
part.add_header('Content-Disposition', 'attachment', filename=filename)
self.attachments.append(part)

def embed(self, name, data=None):
Expand Down
23 changes: 23 additions & 0 deletions test/test_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,29 @@ def test_mime_embed_failures(self):

with pytest.raises(TypeError):
message.embed('test.gif', object())

def test_that_add_header_and_collapse_header_are_inverses_ascii_filename(self):
message = self.build_message()
message.plain = "Hello world."
message.rich = "Farewell cruel world."
message.attach("wat.txt", b"not a unicode snowman") # calls add_header() under the covers
attachment = message.attachments[0]
filename = attachment.get_filename() # calls email.utils.collapse_rfc2231_value() under the covers
assert filename == "wat.txt"

def test_that_add_header_and_collapse_header_are_inverses_non_ascii_filename(self):
message = self.build_message()
message.plain = "Hello world."
message.rich = "Farewell cruel world."
message.attach("☃.txt", b"unicode snowman", filename_language='en-us')
attachment = message.attachments[0]
filename = attachment.get_param('filename', object(), 'content-disposition') # get_filename() calls this under the covers
assert isinstance(filename, tuple) # Since attachment encoded according to RFC2231, should be represented as a tuple
filename = attachment.get_filename() # Calls email.utils.collapse_rfc2231_value() under the covers, currently fails
if sys.version_info < (3, 0):
assert isinstance(filename, basestring) # Successfully converts tuple to a string
else:
assert isinstance(filename, str)

def test_recipients_collection(self):
message = self.build_message()
Expand Down

0 comments on commit 3995ef9

Please sign in to comment.