Skip to content

Commit

Permalink
#1693546: don't add quotes around RFC 2231 encoded values.
Browse files Browse the repository at this point in the history
The RFC is bit hard to understand on this point, but the examples
clearly show that parameter values that are encoded according
to its charset/language rules don't have surrounding quotes, and
the ABNF does not allow for quotes.  So when we produce such
encoded values, we no longer add quotes.
  • Loading branch information
bitdancer committed Dec 24, 2010
1 parent ddf5370 commit dfd7eb0
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 5 deletions.
4 changes: 3 additions & 1 deletion Lib/email/message.py
Expand Up @@ -66,17 +66,19 @@ def _formatparam(param, value=None, quote=True):
if value is not None and len(value) > 0:
# A tuple is used for RFC 2231 encoded parameter values where items
# are (charset, language, value). charset is a string, not a Charset
# instance.
# instance. RFC 2231 encoded values are never quoted, per RFC.
if isinstance(value, tuple):
# Encode as per RFC 2231
param += '*'
value = utils.encode_rfc2231(value[2], value[0], value[1])
return '%s=%s' % (param, value)
else:
try:
value.encode('ascii')
except UnicodeEncodeError:
param += '*'
value = utils.encode_rfc2231(value, 'utf-8', '')
return '%s=%s' % (param, value)
# BAW: Please check this. I think that if quote is set it should
# force quoting even if not necessary.
if quote or tspecials.search(value):
Expand Down
50 changes: 46 additions & 4 deletions Lib/email/test/test_email.py
Expand Up @@ -534,15 +534,31 @@ def test_noascii_add_header(self):
msg.add_header('Content-Disposition', 'attachment',
filename="Fußballer.ppt")
self.assertEqual(
'attachment; filename*="utf-8\'\'Fu%C3%9Fballer.ppt"',
'attachment; filename*=utf-8\'\'Fu%C3%9Fballer.ppt',
msg['Content-Disposition'])

def test_nonascii_add_header_via_triple(self):
msg = Message()
msg.add_header('Content-Disposition', 'attachment',
filename=('iso-8859-1', '', 'Fußballer.ppt'))
self.assertEqual(
'attachment; filename*="iso-8859-1\'\'Fu%DFballer.ppt"',
'attachment; filename*=iso-8859-1\'\'Fu%DFballer.ppt',
msg['Content-Disposition'])

def test_ascii_add_header_with_tspecial(self):
msg = Message()
msg.add_header('Content-Disposition', 'attachment',
filename="windows [filename].ppt")
self.assertEqual(
'attachment; filename="windows [filename].ppt"',
msg['Content-Disposition'])

def test_nonascii_add_header_with_tspecial(self):
msg = Message()
msg.add_header('Content-Disposition', 'attachment',
filename="Fußballer [filename].ppt")
self.assertEqual(
"attachment; filename*=utf-8''Fu%C3%9Fballer%20%5Bfilename%5D.ppt",
msg['Content-Disposition'])


Expand Down Expand Up @@ -3643,7 +3659,7 @@ def test_set_param(self):
Subject: This is a test message
Date: Fri, 4 May 2001 14:05:44 -0400
Content-Type: text/plain; charset=us-ascii;
title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21"
title*=us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21
Hi,
Expand Down Expand Up @@ -3673,7 +3689,7 @@ def test_del_param(self):
Subject: This is a test message
Date: Fri, 4 May 2001 14:05:44 -0400
Content-Type: text/plain; charset="us-ascii";
title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21"
title*=us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21
Hi,
Expand All @@ -3688,6 +3704,32 @@ def test_rfc2231_get_content_charset(self):
msg = self._msgobj('msg_32.txt')
eq(msg.get_content_charset(), 'us-ascii')

def test_rfc2231_parse_rfc_quoting(self):
m = textwrap.dedent('''\
Content-Disposition: inline;
\tfilename*0*=''This%20is%20even%20more%20;
\tfilename*1*=%2A%2A%2Afun%2A%2A%2A%20;
\tfilename*2="is it not.pdf"
''')
msg = email.message_from_string(m)
self.assertEqual(msg.get_filename(),
'This is even more ***fun*** is it not.pdf')
self.assertEqual(m, msg.as_string())

def test_rfc2231_parse_extra_quoting(self):
m = textwrap.dedent('''\
Content-Disposition: inline;
\tfilename*0*="''This%20is%20even%20more%20";
\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20";
\tfilename*2="is it not.pdf"
''')
msg = email.message_from_string(m)
self.assertEqual(msg.get_filename(),
'This is even more ***fun*** is it not.pdf')
self.assertEqual(m, msg.as_string())

def test_rfc2231_no_language_or_charset(self):
m = '''\
Content-Transfer-Encoding: 8bit
Expand Down
3 changes: 3 additions & 0 deletions Misc/NEWS
Expand Up @@ -11,6 +11,9 @@ Core and Builtins
Library
-------

- Issue #1693546: fix email.message RFC 2231 parameter encoding to be in better
compliance (no "s around encoded values).

- Improved the diff message in the unittest module's assertCountEqual().

- Issue #1155362: email.utils.parsedate_tz now handles a missing space before
Expand Down

0 comments on commit dfd7eb0

Please sign in to comment.