Skip to content

Commit f7431eb

Browse files
serhiy-storchakaharjothkharaclaude
authored
[3.13] gh-49680: Test imaplib.IMAP4.append line-ending normalization (GH-152879)
(cherry picked from commit 6759fd8) Co-authored-by: harjoth <harjoth.khara@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 7258a9e commit f7431eb

1 file changed

Lines changed: 28 additions & 6 deletions

File tree

Lib/test/test_imaplib.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import calendar
1010
import threading
1111
import re
12+
import select
1213
import socket
1314

1415
from test.support import verbose, run_with_tz, run_with_locale, cpython_only, requires_resource
@@ -90,6 +91,18 @@ class Handler(SimpleIMAPHandler):
9091
return Handler
9192

9293

94+
def _read_literal(handler, marker):
95+
# Read one literal, a raw octet sequence, by its count from the marker
96+
# ('{N}', or '(~{N}' in UTF8 mode).
97+
size = int(re.search(r'\{(\d+)\}', marker).group(1))
98+
# The client must wait for the continuation, so nothing should be readable.
99+
if select.select([handler.connection], [], [], 0)[0]:
100+
raise AssertionError('client sent the literal before the '
101+
'continuation request')
102+
handler._send_textline('+')
103+
return handler.rfile.read(size)
104+
105+
93106
class TestImaplib(unittest.TestCase):
94107

95108
def test_Internaldate2tuple(self):
@@ -425,10 +438,8 @@ def cmd_AUTHENTICATE(self, tag, args):
425438
self.server.response = yield
426439
self._send_tagged(tag, 'OK', 'FAKEAUTH successful')
427440
def cmd_APPEND(self, tag, args):
428-
self._send_textline('+')
429441
self.server.response = args
430-
literal = yield
431-
self.server.response.append(literal)
442+
self.server.response.append(_read_literal(self, args[-1]))
432443
literal = yield
433444
self.server.response.append(literal)
434445
self._send_tagged(tag, 'OK', 'okay')
@@ -626,6 +637,19 @@ def test_login(self):
626637
self.assertEqual(data[0], b'LOGIN completed')
627638
self.assertEqual(client.state, 'AUTH')
628639

640+
def test_append_line_endings(self):
641+
# append() normalizes bare CR and LF in the message to CRLF.
642+
class AppendHandler(SimpleIMAPHandler):
643+
def cmd_APPEND(self, tag, args):
644+
self.server.response = _read_literal(self, args[-1])
645+
yield # read the trailer line
646+
self._send_tagged(tag, 'OK', 'APPEND completed')
647+
client, server = self._setup(AppendHandler)
648+
client.login('user', 'pass')
649+
message = b'a\rb\nc\r\nd'
650+
client.append('INBOX', None, None, message)
651+
self.assertEqual(server.response, b'a\r\nb\r\nc\r\nd')
652+
629653
def test_logout(self):
630654
client, _ = self._setup(SimpleIMAPHandler)
631655
typ, data = client.login('user', 'pass')
@@ -1461,10 +1485,8 @@ def test_enable_UTF8_True_append(self):
14611485

14621486
class UTF8AppendServer(self.UTF8Server):
14631487
def cmd_APPEND(self, tag, args):
1464-
self._send_textline('+')
14651488
self.server.response = args
1466-
literal = yield
1467-
self.server.response.append(literal)
1489+
self.server.response.append(_read_literal(self, args[-1]))
14681490
literal = yield
14691491
self.server.response.append(literal)
14701492
self._send_tagged(tag, 'OK', 'okay')

0 commit comments

Comments
 (0)