From 0d7306ad552dd5518635f52b147e6d4eeead89a9 Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Sun, 28 Sep 2025 23:03:06 -0700 Subject: [PATCH] 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 --- Lib/imaplib.py | 8 +++-- Lib/test/test_imaplib.py | 29 +++++++++++++------ ...3-02-13-20-34-52.gh-issue-78319.V1zzed.rst | 1 + 3 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-02-13-20-34-52.gh-issue-78319.V1zzed.rst diff --git a/Lib/imaplib.py b/Lib/imaplib.py index eb440b6fc1ffbd..141e6398944873 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -420,8 +420,6 @@ def append(self, mailbox, flags, date_time, message): 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 @@ def _command(self, name, *args): 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 f3ee57d7af3b16..9f1f682d02e8ef 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -325,7 +325,11 @@ def cmd_AUTHENTICATE(self, tag, args): 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 @@ def cmd_APPEND(self, tag, args): 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 @@ def test_enable_UTF8_True_append(self): 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 @@ def cmd_APPEND(self, tag, args): 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 00000000000000..cc8a6e73942203 --- /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.