From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Mon, 29 Sep 2025 06:25:51 +0000 (+0200) Subject: [3.13] gh-78319: Fix implementation of IMAP APPEND UTF8 (GH-9436) (GH-139407) X-Git-Tag: v3.13.8~30 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d232944638da61d0d4d5eadf2efb74dc0709b928;p=thirdparty%2FPython%2Fcpython.git [3.13] gh-78319: Fix implementation of IMAP APPEND UTF8 (GH-9436) (GH-139407) gh-78319: Fix implementation of IMAP APPEND UTF8 (GH-9436) Make UTF8 support for the IMAP APPEND command RFC 6855 compliant. (cherry picked from commit 408154d64a7b3d43b05f44ea5c4cdf781bdd1352) Co-authored-by: Gordon Messmer --- diff --git a/Lib/imaplib.py b/Lib/imaplib.py index eb440b6fc1ff..141e63989448 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -420,8 +420,6 @@ class IMAP4: else: date_time = None literal = MapCRLF.sub(CRLF, message) - if self.utf8_enabled: - literal = b'UTF8 (' + literal + b')' self.literal = literal return self._simple_command(name, mailbox, flags, date_time) @@ -1011,7 +1009,11 @@ class IMAP4: literator = literal else: literator = None - data = data + bytes(' {%s}' % len(literal), self._encoding) + if self.utf8_enabled: + data = data + bytes(' UTF8 (~{%s}' % len(literal), self._encoding) + literal = literal + b')' + else: + data = data + bytes(' {%s}' % len(literal), self._encoding) if __debug__: if self.debug >= 4: diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index f3ee57d7af3b..9f1f682d02e8 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -325,7 +325,11 @@ class NewIMAPTestsMixin: self._send_tagged(tag, 'OK', 'FAKEAUTH successful') def cmd_APPEND(self, tag, args): self._send_textline('+') - self.server.response = yield + self.server.response = args + literal = yield + self.server.response.append(literal) + literal = yield + self.server.response.append(literal) self._send_tagged(tag, 'OK', 'okay') client, server = self._setup(UTF8AppendServer) self.assertEqual(client._encoding, 'ascii') @@ -336,10 +340,13 @@ class NewIMAPTestsMixin: self.assertEqual(code, 'OK') self.assertEqual(client._encoding, 'utf-8') msg_string = 'Subject: üñí©öðé' - typ, data = client.append(None, None, None, msg_string.encode('utf-8')) + typ, data = client.append( + None, None, None, (msg_string + '\n').encode('utf-8')) self.assertEqual(typ, 'OK') self.assertEqual(server.response, - ('UTF8 (%s)\r\n' % msg_string).encode('utf-8')) + ['INBOX', 'UTF8', + '(~{25}', ('%s\r\n' % msg_string).encode('utf-8'), + b')\r\n' ]) def test_search_disallows_charset_in_utf8_mode(self): class UTF8Server(SimpleIMAPHandler): @@ -764,7 +771,11 @@ class ThreadedNetworkedTests(unittest.TestCase): class UTF8AppendServer(self.UTF8Server): def cmd_APPEND(self, tag, args): self._send_textline('+') - self.server.response = yield + self.server.response = args + literal = yield + self.server.response.append(literal) + literal = yield + self.server.response.append(literal) self._send_tagged(tag, 'OK', 'okay') with self.reaped_pair(UTF8AppendServer) as (server, client): @@ -778,12 +789,12 @@ class ThreadedNetworkedTests(unittest.TestCase): self.assertEqual(client._encoding, 'utf-8') msg_string = 'Subject: üñí©öðé' typ, data = client.append( - None, None, None, msg_string.encode('utf-8')) + None, None, None, (msg_string + '\n').encode('utf-8')) self.assertEqual(typ, 'OK') - self.assertEqual( - server.response, - ('UTF8 (%s)\r\n' % msg_string).encode('utf-8') - ) + self.assertEqual(server.response, + ['INBOX', 'UTF8', + '(~{25}', ('%s\r\n' % msg_string).encode('utf-8'), + b')\r\n' ]) # XXX also need a test that makes sure that the Literal and Untagged_status # regexes uses unicode in UTF8 mode instead of the default ASCII. diff --git a/Misc/NEWS.d/next/Library/2023-02-13-20-34-52.gh-issue-78319.V1zzed.rst b/Misc/NEWS.d/next/Library/2023-02-13-20-34-52.gh-issue-78319.V1zzed.rst new file mode 100644 index 000000000000..cc8a6e739422 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-02-13-20-34-52.gh-issue-78319.V1zzed.rst @@ -0,0 +1 @@ +UTF8 support for the IMAP APPEND command has been made RFC compliant.