You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
imaplib: must not replace LF or CR by CRLF in literals #49680
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=Nonecreated_at=<Date2009-03-06.07:51:15.737>labels= ['easy', 'type-bug', '3.8', 'expert-email', '3.10', 'library', '3.9']
title='imaplib: must not replace LF or CR by CRLF in literals'updated_at=<Date2020-11-07.01:52:35.851>user='https://bugs.python.org/memeplex'
For example, after that "normalization", quoted printable encoded
headers (as described at rfc 2047) longer than 76 characters are
splitted in two different ill-formed headers because the soft LF line
break becomes a "hard" CRLF one. This is clearly wrong.
rfc 2060 specifically allows CR and LF inside literals:
"""
A literal is a sequence of zero or more octets (including CR and LF),
prefix-quoted with an octet count in the form of an open brace ("{"),
the number of octets, close brace ("}"), and CRLF.
"""
It looks like the IMAP4.append method is responsible for the CRLF
substitution (trunk/Lib/imaplib.py).
# defined near top of module:MapCRLF=re.compile(r'\r\n|\r|\n')
# in append method:self.literal=MapCRLF.sub(CRLF, message)
I'll work on a test for it this evening.
-Ron
rduplain commented on Apr 26, 2009
rduplainmannequin
Mannequin
More actions
Module imaplib has pretty sparse test code. There is only 1 test case,
for imaplib.Time2Internaldate.
trunk/Lib/test/test_imaplib.py
The attached patch tests for LF, CR preservation with regard to the
IMAP4.append method, but more testing is necessary to make sure LF, CR
are preserved in IMAP literals throughout imaplib and that the
respective fix doesn't break anything. Mock IMAP interaction may be the
way to go for better test cases. Is anyone working on expanding imaplib
test coverage?
-Ron
rajeshsr commented on Oct 27, 2009
rajeshsrmannequin
Mannequin
More actions
Am quite new here; just searching hard to contribute, would like to
patch this, if I can go ahead.
Don't we need to patch the original imaplib code also?
just remove the line:
self.literal = MapCRLF.sub(CRLF, message)
and have:
self.literal = message
Or am I missing something completely?
I'm not sure if this is a 2.6/2.7 only issue because the code mentioned in msg86572 still exists, although with a change for bpo-21800 (RFC 6855/UTF-8) applied.
For reference, bpo-25591 expanded the test coverage for the imaplib. However, I don't see any tests related to CR or LF in literals.
I traced this on current main. IMAP4.append() still normalizes the APPEND message literal with MapCRLF.sub(CRLF, message) before assigning self.literal, so caller-provided bytes containing bare CR or LF are sent as different bytes.
I also looked at the old PR #10901 and the concern about the older bpo-723962 change that introduced this canonicalization. The distinction that seems important is command framing vs literal payload: _command() already sends the literal length, waits for continuation, sends the literal bytes, and then sends the protocol CRLF after the literal. So it seems like append() should preserve the message literal exactly, while the protocol framing remains handled outside the literal.
Would a narrowly scoped PR be welcome that:
preserves the APPEND message bytes exactly for the literal payload,
updates the existing APPEND tests that currently expect normalization,
adds a regression test with CR, LF, and CRLF in the message body to assert the fake server receives the exact payload?
I have not opened a PR yet; I wanted to check that this framing/payload distinction is the right way to resolve the bpo-723962 concern.
Fixed in #152775: append() now accepts translate_line_endings=False to send the message literal as exact octets, without rewriting bare CR or LF to CRLF. The useful test additions from @harjothkhara's original PR (#151557) were also backported to 3.13, 3.14 and 3.15.
Activity
memeplex commentedon Mar 6, 2009
For example, after that "normalization", quoted printable encoded
headers (as described at rfc 2047) longer than 76 characters are
splitted in two different ill-formed headers because the soft LF line
break becomes a "hard" CRLF one. This is clearly wrong.
rfc 2060 specifically allows CR and LF inside literals:
"""
A literal is a sequence of zero or more octets (including CR and LF),
prefix-quoted with an octet count in the form of an open brace ("{"),
the number of octets, close brace ("}"), and CRLF.
"""
[-]Must not replace LF or CR by CRLF in literals[/-][+]imaplib: must not replace LF or CR by CRLF in literals[/+]rduplain commentedon Apr 25, 2009
It looks like the IMAP4.append method is responsible for the CRLF
substitution (trunk/Lib/imaplib.py).
I'll work on a test for it this evening.
-Ron
rduplain commentedon Apr 26, 2009
Module imaplib has pretty sparse test code. There is only 1 test case,
for imaplib.Time2Internaldate.
trunk/Lib/test/test_imaplib.py
The attached patch tests for LF, CR preservation with regard to the
IMAP4.append method, but more testing is necessary to make sure LF, CR
are preserved in IMAP literals throughout imaplib and that the
respective fix doesn't break anything. Mock IMAP interaction may be the
way to go for better test cases. Is anyone working on expanding imaplib
test coverage?
-Ron
rajeshsr commentedon Oct 27, 2009
Am quite new here; just searching hard to contribute, would like to
patch this, if I can go ahead.
Don't we need to patch the original imaplib code also?
just remove the line:
self.literal = MapCRLF.sub(CRLF, message)
and have:
self.literal = message
Or am I missing something completely?
mcepl commentedon Apr 21, 2018
On that note: would anybody be willing to express in form of (simplified) test case, what's the problem reported here? I am not sure, I follow.
mcepl commentedon Apr 21, 2018
Oh, this is 2.6 bug. This should be closed.
csabella commentedon May 4, 2018
I'm not sure if this is a 2.6/2.7 only issue because the code mentioned in msg86572 still exists, although with a change for bpo-21800 (RFC 6855/UTF-8) applied.
For reference, bpo-25591 expanded the test coverage for the imaplib. However, I don't see any tests related to CR or LF in literals.
JulienPalard commentedon Sep 13, 2019
It looks like a revert of 47404ff
Which is the fix for https://bugs.python.org/issue723962 which I'm currently reading.
mcepl commentedon Dec 6, 2024
Yes, because that commit was too hard hitting, and it made some messages non-conforming to RFCs (e.g., by corrupting headers).
savagemechanic commentedon May 18, 2026
I traced this on current main.
IMAP4.append()still normalizes the APPEND message literal withMapCRLF.sub(CRLF, message)before assigningself.literal, so caller-provided bytes containing bare CR or LF are sent as different bytes.I also looked at the old PR #10901 and the concern about the older bpo-723962 change that introduced this canonicalization. The distinction that seems important is command framing vs literal payload:
_command()already sends the literal length, waits for continuation, sends the literal bytes, and then sends the protocol CRLF after the literal. So it seems likeappend()should preserve the message literal exactly, while the protocol framing remains handled outside the literal.Would a narrowly scoped PR be welcome that:
messagebytes exactly for the literal payload,I have not opened a PR yet; I wanted to check that this framing/payload distinction is the right way to resolve the bpo-723962 concern.
pythongh-49680: Add Harjoth Khara to ACKS
pythongh-49680: Don't rewrite CR/LF in imaplib APPEND literals
pythongh-49680: Add Harjoth Khara to ACKS
pythongh-49680: Test exact APPEND and email message round-trip
gh-49680: Add translate_line_endings parameter to imaplib.IMAP4.append (
[3.15] gh-49680: Test imaplib.IMAP4.append line-ending normalization (G…
[3.14] gh-49680: Test imaplib.IMAP4.append line-ending normalization (G…
[3.13] gh-49680: Test imaplib.IMAP4.append line-ending normalization (G…
serhiy-storchaka commentedon Jul 2, 2026
Fixed in #152775:
append()now acceptstranslate_line_endings=Falseto send the message literal as exact octets, without rewriting bare CR or LF to CRLF. The useful test additions from @harjothkhara's original PR (#151557) were also backported to 3.13, 3.14 and 3.15.