From f9d2d7b4ebdb0c7047e60323b396eb0e8c68a360 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 10 Jul 2026 09:09:42 +0300 Subject: [PATCH] gh-49555: Clarify imaplib modified UTF-7 docs and comments Co-Authored-By: Claude Opus 4.8 --- Doc/whatsnew/3.16.rst | 5 +++-- Lib/imaplib.py | 6 +++++- .../2026-07-09-12-00-00.gh-issue-49555.Ka9Lm2.rst | 9 ++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index c3653523647170..2312ae89fcb448 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -263,8 +263,9 @@ imaplib (Contributed by Przemysław Buczkowski and Serhiy Storchaka in :gh:`89869`.) * Non-ASCII mailbox names are now automatically encoded as modified UTF-7 - (:rfc:`3501`, section 5.1.3), so international mailbox names can be passed - as ordinary :class:`str`. + (:rfc:`3501`, section 5.1.3) in the default mode, so international mailbox + names can be passed as ordinary :class:`str` without enabling ``UTF8=ACCEPT`` + (under which they are sent as UTF-8). (Contributed by Serhiy Storchaka in :gh:`49555`.) diff --git a/Lib/imaplib.py b/Lib/imaplib.py index d8acf085e7a128..eca00675174098 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1552,7 +1552,7 @@ def _encode_mailbox(self, arg, safe): # UTF-7 token -- one that needs no quoting, or an explicitly quoted # string -- is passed through unchanged, so that a name obtained as raw # bytes from LIST (and decoded as ASCII) round-trips without being - # encoded again. Pass bytes to bypass encoding entirely. + # encoded again. self._encoding is only ever 'ascii' or 'utf-8'. if self._encoding != 'ascii': return bytes(arg, self._encoding) try: @@ -1568,11 +1568,15 @@ def _encode_mailbox(self, arg, safe): return arg.encode('utf-7-imap') def _mailbox(self, arg): + # A str name is encoded for the wire; pass bytes to send the name + # verbatim, bypassing encoding entirely. if isinstance(arg, str): arg = self._encode_mailbox(arg, _non_astring_char) return self._astring(arg) def _list_mailbox(self, arg): + # As _mailbox(), but for a LIST/LSUB pattern; pass bytes to bypass + # encoding. if isinstance(arg, str): arg = self._encode_mailbox(arg, _non_list_char) if _quoted.fullmatch(arg): diff --git a/Misc/NEWS.d/next/Library/2026-07-09-12-00-00.gh-issue-49555.Ka9Lm2.rst b/Misc/NEWS.d/next/Library/2026-07-09-12-00-00.gh-issue-49555.Ka9Lm2.rst index 87236e98a07901..56860e53db8862 100644 --- a/Misc/NEWS.d/next/Library/2026-07-09-12-00-00.gh-issue-49555.Ka9Lm2.rst +++ b/Misc/NEWS.d/next/Library/2026-07-09-12-00-00.gh-issue-49555.Ka9Lm2.rst @@ -1,4 +1,7 @@ :mod:`imaplib` now encodes non-ASCII mailbox names as modified UTF-7 -(:rfc:`3501`, section 5.1.3), so international mailbox names can be passed as -ordinary :class:`str`. A ``str`` that is already valid modified UTF-7, or a -:class:`bytes` object, is sent unchanged. +(:rfc:`3501`, section 5.1.3) in the default mode, so international mailbox +names can be passed as ordinary :class:`str`; under ``UTF8=ACCEPT`` they are +sent as UTF-8 instead. A name that is not valid modified UTF-7, such as one +with a bare ``&``, is now encoded correctly instead of being sent as is. +A ``str`` that is already valid modified UTF-7, or a :class:`bytes` object, +is sent unchanged.