diff --git a/Lib/email/utils.py b/Lib/email/utils.py index 7eab74dc0db9df..c70f496a55f776 100644 --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -40,7 +40,9 @@ CRLF = '\r\n' TICK = "'" -specialsre = re.compile(r'[][\\()<>@,:;".]') +# These are used by formataddr() to understand what characters require a name +# field to be quoted and what characters within that must be \escaped. +specialsre = re.compile(r'[][\\()<>@,:;". ]') escapesre = re.compile(r'[\\"]') diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index 2deb35721576b8..3e0f1e9c17b974 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3227,7 +3227,7 @@ def test_parseaddr_multiple_domains(self): def test_noquote_dump(self): self.assertEqual( utils.formataddr(('A Silly Person', 'person@dom.ain')), - 'A Silly Person ') + '"A Silly Person" ') def test_escape_dump(self): self.assertEqual( @@ -3248,6 +3248,12 @@ def test_escape_backslashes(self): b = 'person@dom.ain' self.assertEqual(utils.parseaddr(utils.formataddr((a, b))), (a, b)) + def test_parseaddr_formataddr_inverse(self): + # gh-91400 + identity = '"foo bar" ' + single = utils.formataddr(utils.parseaddr(identity)) + self.assertEqual(identity, single) + def test_quotes_unicode_names(self): # issue 1690608. email.utils.formataddr() should be rfc2047 aware. name = "H\u00e4ns W\u00fcrst" diff --git a/Misc/NEWS.d/next/Library/2022-05-10-21-46-28.gh-issue-91400.usUzm_.rst b/Misc/NEWS.d/next/Library/2022-05-10-21-46-28.gh-issue-91400.usUzm_.rst new file mode 100644 index 00000000000000..e74020fdb19c80 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-05-10-21-46-28.gh-issue-91400.usUzm_.rst @@ -0,0 +1,2 @@ +Make :func:`email.utils.formataddr` "quote" the name portion of an email address if +it contains spaces.