Skip to content

fix: decode quoted-printable attachments to their bytes - #287

Open
hobleyd wants to merge 1 commit into
Enough-Software:mainfrom
hobleyd:fix/qp-attachment-decode
Open

hobleyd wants to merge 1 commit into
Enough-Software:mainfrom
hobleyd:fix/qp-attachment-decode

Conversation

@hobleyd

@hobleyd hobleyd commented Sep 22, 2026

Copy link
Copy Markdown

Problem

QuotedPrintableMailCodec.decodeData returned the undecoded source (part.codeUnits), so any attachment with Content-Transfer-Encoding: quoted-printable came out as its own source text: a PDF began =25PDF=2D1=2E7 where the caller asked for %PDF-1.7.

MailCodec.decodeBinary also had no entry for quoted-printable/q (or 7bit) in _binaryDecodersByName, so it fell through to the undecoded source and only printed a message. The corruption was silent to the caller.

Fix

  • decodeData now decodes =XY hex escapes to bytes and drops soft line breaks (=\r\n, =\n). It applies no charset: an attachment's bytes are the payload, not text. An invalid escape such as =ZZ is passed through rather than dropped, and a trailing = with no hex digits is kept.
  • _binaryDecodersByName gains q, quoted-printable and 7bit, so every encoding _textDecodersByName knows has a binary counterpart.

Tests

Eight new tests in quoted_printable_mail_codec_test.dart covering hex escapes, bytes above 0x7F, soft line breaks, literal pass-through, invalid and trailing escapes, and the decodeBinary routing for quoted-printable, Q and 7bit.

QuotedPrintableMailCodec.decodeData returned the undecoded source, so a
quoted-printable attachment came out as `=25PDF=2D1=2E7` where the caller
asked for `%PDF-1.7`. MailCodec.decodeBinary also had no entry for
`quoted-printable`/`q` or `7bit` at all: it fell through to the
undecoded source and only printed, so the corruption was silent.

decodeData now decodes hex escapes to bytes and drops soft line breaks,
applying no charset (an attachment's bytes are the payload, not text).
Invalid escapes are passed through rather than dropped.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants