diff --git a/Lib/email/utils.py b/Lib/email/utils.py index 6889c5591bf030..001b1dd4081edf 100644 --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -399,8 +399,14 @@ def encode_rfc2231(s, charset=None, language=None): return "%s'%s'%s" % (charset, language, s) -rfc2231_continuation = re.compile(r'^(?P\w+)\*((?P[0-9]+)\*?)?$', +rfc2231_continuation = re.compile(r'^(?P[\w-]+)\*((?P[0-9]+)\*?)?$', re.ASCII) +# `\w` is ASCII-only here (re.ASCII), so it matches exactly [A-Za-z0-9_], +# all of which are valid RFC 2045 `token` characters. Adding `-` lets the +# regex recognize hyphenated continuation parameter names (e.g. `file-name*0*`). +# This is intentionally stricter than the full RFC 2045 `token` set (which +# also permits e.g. `.`, `!`, `#`); none of those appear in practice for +# RFC 2231 parameter names, and broadening the class is out of scope here. def decode_params(params): """Decode parameters list according to RFC 2231. diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index e40c82bba9af42..6d66238b885946 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -400,6 +400,18 @@ def test_continuation_sorting_part_order(self): filename = msg.get_filename() self.assertEqual(filename, 'foo bar.txt') + def test_continuation_with_hyphenated_name(self): + # gh-130110: parameter names containing hyphens were not recognized + # as RFC 2231 continuations and were left undecoded. + msg = email.message_from_string( + "Content-Disposition: attachment; " + "file-name*0*=\"utf-8''start\"; " + "file-name*1*=\"-middle-\"; " + "file-name*2*=\"end\"\n" + ) + value = msg.get_param('file-name', header='content-disposition') + self.assertEqual(value, ('utf-8', '', 'start-middle-end')) + def test_sorting_no_continuations(self): msg = email.message_from_string( "Content-Disposition: attachment; " diff --git a/Misc/NEWS.d/next/Library/2026-07-10-23-32-52.gh-issue-130110.R7xQz2.rst b/Misc/NEWS.d/next/Library/2026-07-10-23-32-52.gh-issue-130110.R7xQz2.rst new file mode 100644 index 00000000000000..f80f0bdf8b3893 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-10-23-32-52.gh-issue-130110.R7xQz2.rst @@ -0,0 +1,3 @@ +:meth:`email.utils.decode_params` (and the parameter parsing it backs) now +correctly decodes :rfc:`2231` continuation parameter names that contain +hyphens, such as ``file-name*0*``.