Skip to content

gh-62222: Fix and extend quoted-printable decoding#152679

Open
serhiy-storchaka wants to merge 2 commits into
python:mainfrom
serhiy-storchaka:gh-62222-qp-malformed-escape
Open

gh-62222: Fix and extend quoted-printable decoding#152679
serhiy-storchaka wants to merge 2 commits into
python:mainfrom
serhiy-storchaka:gh-62222-qp-malformed-escape

Conversation

@serhiy-storchaka

Copy link
Copy Markdown
Member

binascii.a2b_qp() and quopri now leave an invalid = escape (one not followed by two hexadecimal digits or a soft line break) in place and rescan the following character instead of consuming it, like email.quoprimime and other quoted-printable decoders. For example b'==41' now decodes to b'=A' instead of b'=41'.

A new opt-in strip_ws parameter is added to binascii.a2b_qp(), quopri.decode(), quopri.decodestring() and email.quoprimime.decode(). When true, whitespace at the end of each line is stripped while decoding, as required by RFC 2045 for a quoted-printable body, while encoded whitespace (=20/=09) is preserved. It is false by default everywhere except email.quoprimime.decode(), so every existing default is preserved.

The documentation for email.message.Message.get_payload(decode=True) now notes that it does not strip trailing whitespace from a quoted-printable body, contrary to RFC 2045 — this matches the behavior of common mail clients.

binascii.a2b_qp() and quopri now leave an invalid "=" escape in place and
rescan the following character instead of consuming it, like email.quoprimime
and other decoders (b'==41' now decodes to b'=A').

Add an opt-in strip_ws parameter to binascii.a2b_qp(), quopri.decode(),
quopri.decodestring() and email.quoprimime.decode() to strip trailing
whitespace per RFC 2045.  It is false by default everywhere except
email.quoprimime.decode(), preserving every existing default.

Also document that email's get_payload(decode=True) does not strip trailing
whitespace, contrary to RFC 2045.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@read-the-docs-community

read-the-docs-community Bot commented Jun 30, 2026

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33373283 | 📁 Comparing df866a9 against main (ecdef17)

  🔍 Preview build  

5 files changed · ± 5 modified

± Modified

Register the new "strip_ws" argument name in the global objects tables
(make regen-global-objects), needed by static builds where binascii is
compiled into the core, and replace an unresolved :func: reference to the
undocumented email.quoprimime.decode with a literal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant