Skip to content
2 changes: 1 addition & 1 deletion Doc/library/email.utils.rst
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ of the new API.
:rfc:`2231` header is not known by Python; it defaults to ``'us-ascii'``.

For convenience, if the *value* passed to :func:`collapse_rfc2231_value` is not
a tuple, it should be a string and it is returned unquoted.
a 3-tuple, it should be a string and it is returned unquoted.


.. function:: decode_params(params)
Expand Down
4 changes: 4 additions & 0 deletions Lib/email/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,10 @@ def decode_params(params):
def collapse_rfc2231_value(value, errors='replace',
fallback_charset='us-ascii'):
if not isinstance(value, tuple) or len(value) != 3:
if not isinstance(value, str):
raise TypeError(
f"expected str or 3-tuple, got {type(value).__name__}"
)
return unquote(value)
# While value comes to us as a unicode string, we need it to be a bytes
# object. We do not want bytes() normal utf-8 decoder, we want a straight
Expand Down
14 changes: 14 additions & 0 deletions Lib/test/test_email/test_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -5789,6 +5789,20 @@ def test_should_not_hang_on_invalid_ew_messages(self):
with self.subTest(m=m):
msg = email.message_from_string(m)

def test_collapse_rfc2231_value_non_3_tuple(self):
# collapse_rfc2231_value raises TypeError on values that are
# neither a string nor a 3-tuple.
from email.utils import collapse_rfc2231_value
for val in [(), ('a',), ('a', 'b'), ('a', 'b', 'c', 'd'), 42, None]:
with self.subTest(val=val):
with self.assertRaises(TypeError):
collapse_rfc2231_value(val)
# A proper 3-tuple decodes correctly.
result = collapse_rfc2231_value(('us-ascii', 'en', 'hello'))
self.assertEqual(result, 'hello')
# A plain string passes through unquote.
self.assertEqual(collapse_rfc2231_value('"hello"'), 'hello')


# Tests to ensure that signed parts of an email are completely preserved, as
# required by RFC1847 section 2.1. Note that these are incomplete, because the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:func:`email.utils.collapse_rfc2231_value` now raises :exc:`TypeError`
instead of :exc:`AttributeError` when called with a value that is neither a
string nor a 3-tuple.
Loading