diff --git a/Lib/email/utils.py b/Lib/email/utils.py
index c8a6d0af37532c9..682efc18a3fb571 100644
--- a/Lib/email/utils.py
+++ b/Lib/email/utils.py
@@ -101,6 +101,10 @@ def formataddr(pair, charset='utf-8', *, strict=True):
from email.charset import Charset
charset = Charset(charset)
encoded_name = charset.header_encode(name)
+ if specialsre.search(encoded_name):
+ # Not RFC 2047-encoded, so quote it like the ASCII branch
+ # below to keep specials from leaking into the header.
+ encoded_name = '"' + escapesre.sub(r'\\\g<0>', encoded_name) + '"'
return "%s <%s>" % (encoded_name, address)
else:
quotes = ''
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
index e40c82bba9af426..f3143c2859be874 100644
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -3308,6 +3308,32 @@ def test_name_with_dot(self):
# formataddr() quotes the name if there's a dot in it
self.assertEqual(utils.formataddr((a, b)), y)
+ def test_formataddr_non_ascii_name_with_specials(self):
+ # gh-100900: when the charset is configured not to RFC 2047-encode the
+ # display name, formataddr() must still quote a non-ASCII name that
+ # contains specials, the same way its ASCII branch does, so the result
+ # round-trips through getaddresses() instead of splitting on the comma.
+ from email import charset as _charset
+ sentinel = object()
+ previous = _charset.CHARSETS.get('utf-8', sentinel)
+ def restore():
+ if previous is sentinel:
+ _charset.CHARSETS.pop('utf-8', None)
+ else:
+ _charset.CHARSETS['utf-8'] = previous
+ self.addCleanup(restore)
+ _charset.add_charset('utf-8', None) # do not RFC 2047-encode the name
+ formatted = utils.formataddr(('Fôo, Bar', 'a@b.com'))
+ self.assertEqual(formatted, '"Fôo, Bar" ')
+ self.assertEqual(utils.getaddresses([formatted]),
+ [('Fôo, Bar', 'a@b.com')])
+ # A non-ASCII name without specials is still emitted unquoted.
+ self.assertEqual(utils.formataddr(('Fôo Bar', 'a@b.com')),
+ 'Fôo Bar ')
+ # The ASCII branch is unchanged.
+ self.assertEqual(utils.formataddr(('Foo, Bar', 'a@b.com')),
+ '"Foo, Bar" ')
+
def test_parseaddr_preserves_quoted_pairs_in_addresses(self):
# issue 10005. Note that in the third test the second pair of
# backslashes is not actually a quoted pair because it is not inside a
diff --git a/Misc/NEWS.d/next/Library/2026-08-16-02-24-32.gh-issue-100900.y7FWJM.rst b/Misc/NEWS.d/next/Library/2026-08-16-02-24-32.gh-issue-100900.y7FWJM.rst
new file mode 100644
index 000000000000000..d18f1b8d844a898
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-08-16-02-24-32.gh-issue-100900.y7FWJM.rst
@@ -0,0 +1,4 @@
+Fix :func:`email.utils.formataddr` failing to quote a non-ASCII display name
+that contains special characters when the charset is configured not to
+RFC 2047-encode it, which broke round-tripping through
+:func:`~email.utils.getaddresses`. Patch by Nikolaus Schuetz.