Skip to content

Commit 0d7e298

Browse files
gh-49680: Add translate_line_endings parameter to imaplib append
Pass False to send the message as an exact sequence of octets, without rewriting bare CR or LF to CRLF. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 564c58c commit 0d7e298

4 files changed

Lines changed: 41 additions & 4 deletions

File tree

Doc/library/imaplib.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ upper bound (``'3:*'``).
195195
An :class:`IMAP4` instance has the following methods:
196196

197197

198-
.. method:: IMAP4.append(mailbox, flags, date_time, message)
198+
.. method:: IMAP4.append(mailbox, flags, date_time, message, *, translate_line_endings=True)
199199

200200
Append *message* to named mailbox.
201201

@@ -204,6 +204,14 @@ An :class:`IMAP4` instance has the following methods:
204204
If *flags* is not already enclosed in parentheses, parentheses are
205205
added automatically.
206206

207+
If *translate_line_endings* is true (the default),
208+
line endings in *message* are translated to CRLF.
209+
Pass ``False`` to send the message literal exactly as given,
210+
which is required to preserve messages that contain bare CR or LF.
211+
212+
.. versionchanged:: next
213+
Added the *translate_line_endings* parameter.
214+
207215

208216
.. method:: IMAP4.authenticate(mechanism, authobject)
209217

Lib/imaplib.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,12 +483,17 @@ def response(self, code):
483483
# IMAP4 commands
484484

485485

486-
def append(self, mailbox, flags, date_time, message):
486+
def append(self, mailbox, flags, date_time, message, *,
487+
translate_line_endings=True):
487488
"""Append message to named mailbox.
488489
489490
(typ, [data]) = <instance>.append(mailbox, flags, date_time, message)
490491
491492
All args except 'message' can be None.
493+
494+
If 'translate_line_endings' is true (the default), line endings in
495+
'message' are translated to CRLF. Pass false to send the message
496+
literal exactly as given.
492497
"""
493498
name = 'APPEND'
494499
if not mailbox:
@@ -502,8 +507,9 @@ def append(self, mailbox, flags, date_time, message):
502507
date_time = Time2Internaldate(date_time)
503508
else:
504509
date_time = None
505-
literal = MapCRLF.sub(CRLF, message)
506-
self.literal = literal
510+
if translate_line_endings:
511+
message = MapCRLF.sub(CRLF, message)
512+
self.literal = message
507513
return self._simple_command(name, mailbox, flags, date_time)
508514

509515

Lib/test/test_imaplib.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,25 @@ def test_login(self):
634634
self.assertEqual(data[0], b'LOGIN completed')
635635
self.assertEqual(client.state, 'AUTH')
636636

637+
def test_append_translate_line_endings(self):
638+
# By default line endings in the message are normalized to CRLF;
639+
# translate_line_endings=False sends the literal exactly (gh-49680).
640+
class AppendHandler(SimpleIMAPHandler):
641+
def cmd_APPEND(self, tag, args):
642+
size = int(args[-1].strip('{}'))
643+
self._send_textline('+')
644+
self.server.response = self.rfile.read(size)
645+
self.rfile.readline() # trailing CRLF after the literal
646+
self._send_tagged(tag, 'OK', 'APPEND completed')
647+
message = b'a\rb\nc\r\nd'
648+
client, server = self._setup(AppendHandler)
649+
client.login('user', 'pass')
650+
client.append('INBOX', None, None, message)
651+
self.assertEqual(server.response, b'a\r\nb\r\nc\r\nd')
652+
client.append('INBOX', None, None, message,
653+
translate_line_endings=False)
654+
self.assertEqual(server.response, message)
655+
637656
def test_logout(self):
638657
client, _ = self._setup(SimpleIMAPHandler)
639658
typ, data = client.login('user', 'pass')
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Add the *translate_line_endings* parameter to :meth:`imaplib.IMAP4.append`.
2+
By default line endings in the message are translated to CRLF, as before;
3+
passing ``False`` sends the message literal exactly as given, preserving
4+
bare CR or LF octets.

0 commit comments

Comments
 (0)