Skip to content

feat(receiver): port the email parser to mail-parser 1.0.1 (web 0.62.5) - #588

Merged
kroqdotdev merged 4 commits into
mainfrom
dependabot/cargo/apps/receiver-rs/mail-parser-1.0.0
Nov 5, 2026
Merged

kroqdotdev merged 4 commits into
mainfrom
dependabot/cargo/apps/receiver-rs/mail-parser-1.0.0

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Dependabot's bump of mail-parser from 0.11.9 to 1.0 did not build: 1.0 is a rewrite with a read-only view API. This PR ports apps/receiver-rs/src/mail/parse.rs, the only user, to it and moves to 1.0.1, which fixes parameters folded after = (filename, name, boundary). It is rebased on main.

What the stored email document does

The document's shape stays the same. For ordinary mail its content does too:

  • Attachments are 1.0's RFC 8621 list plus every other leaf that is not text shown in a body. RFC 8621 leaves out two kinds of part that 0.11 listed:

    • an image shown inline in both bodies, such as a photo pasted into an Apple Mail message;
    • a text part of an alternative that it discards.

    Both stay listed.

  • Named HTML alternative: a text/html alternative with a name= after the text/plain stays the HTML body. RFC 8621 would make it an attachment, but mail clients show it as the message, and so did 0.11.

  • Attachment bytes: text and HTML attachments are stored converted to UTF-8 from their charset, and a forwarded message is stored as its raw message, both as in 0.11.

  • Sizes: when the bytes are not kept, decoded_len() gives the size without decoding.

  • Blank fields: a blank Subject or Message-ID stays null. 1.0 reads it as "", which would change the forwarded JSON.

Changes 1.0 brings, all fixes

  • A boundary string in the middle of a line no longer ends a part. 0.11 silently cut the text off there.
  • An email that forwards several messages lists each one, not one merged attachment.
  • Header names with a space, a control character or a leading colon (Fr om:, :From:) are no longer read as From or Subject.
  • The last quantum of unpadded base64 is kept, and UTF-7 and UTF-16 text decode correctly.
  • RFC 8621 edge cases: a text/plain marked Content-Disposition: attachment inside an alternative is now an attachment, and a headers-only root part marked attachment is listed as an empty attachment.
  • Malformed input decodes differently: invalid quoted-printable escapes are kept as written, and bytes outside the base64 alphabet are skipped.

How it was checked

  • Corpus diff: the old and new parse.rs ran side by side over mail-parser's corpora (309 messages, plus mbox and maildir samples) and hand-made Apple Mail, Outlook, cid: image, forwarded-message, Latin-1 CSV and UTF-16 messages. Everything not listed above came out identical in document, header map and attachment bytes.
  • Independent review: a fresh review found no bugs. It ran the old and new parsers on 528 generated realistic structures, which came out identical. A 200k-iteration structural fuzz found no panics. The document keys never changed, NUL never appeared, sizes always matched the stored bytes, and the document was the same with and without kept contents. Hostile ~10 MB inputs (20k parts, 20k-deep nesting, 600k addresses, nested base64 messages) parsed in at most about 100 ms each. The one finding was the named-HTML case above, now fixed.
  • Second review (CodeRabbit was rate-limited): a fresh Fable review found no bugs. It found three low-severity items, now fixed: a quadratic part scan when an alternative holds thousands of named HTML parts (now as fast as 0.11); the text of a named-HTML-only alternative (now converted from the HTML); and a changelog line for text parts that are now listed as attachments.
  • Speed: an 11 MB message with three attachments parses in about 11 ms instead of 32 ms.
  • New unit tests pin the decisions above. The two attachment-list tests fail with plain 1.0 attachments().
  • Local runs: cargo test --locked (329 passed), cargo clippy --locked --all-targets -- -D warnings, cargo fmt --check. MSRV 1.98 matches the local toolchain and the rust:1.98 Docker builder.

The web version is 0.62.5 because #616 takes 0.62.4.

🤖 Generated with Claude Code

@dependabot dependabot Bot added dependencies Pull requests that update a dependency file rust Pull requests that update rust code labels Nov 2, 2026
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1812b72d-9cf0-4b5a-9862-98c2fb8e628a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
cargo/encodify 1.0.2 UnknownUnknown
cargo/hashify 0.3.2 UnknownUnknown
cargo/mail-parser 1.0.1 UnknownUnknown

Scanned Files

  • apps/receiver-rs/Cargo.lock

kroqdotdev added a commit that referenced this pull request Nov 3, 2026
…on guard (#610)

Folds Dependabot #592, #590, #587, #585, #586 and #589 (Python SDK dev deps, uuid 1.29, statoss 0.1.1, futures-util 0.3.34, unicode-width 0.2.3, setup-uv 10.3.3). Scoped override moves typescript-eslint's minimatch 10 to 11 (GHSA-g3hv-75wg-m249). The SDK's agent credentials writer refuses prototype-named issuers and unknown slot names and reads entries as own properties (CodeQL js/prototype-polluting-assignment). mail-parser 1.0 (#588) is left for a separate change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dependabot
dependabot Bot force-pushed the dependabot/cargo/apps/receiver-rs/mail-parser-1.0.0 branch from df1d877 to 035caf7 Compare November 3, 2026 14:49
@kroqdotdev
kroqdotdev force-pushed the dependabot/cargo/apps/receiver-rs/mail-parser-1.0.0 branch from 035caf7 to 1f4ceac Compare November 5, 2026 11:32
@kroqdotdev kroqdotdev changed the title feat(deps): bump mail-parser from 0.11.9 to 1.0.0 in /apps/receiver-rs feat(receiver): port the email parser to mail-parser 1.0.1 (web 0.62.5) Nov 5, 2026
@kroqdotdev

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Action not completed

Review skipped.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

dependabot Bot and others added 3 commits November 5, 2026 12:45
Bumps [mail-parser](https://github.com/stalwartlabs/mail-parser) from 0.11.9 to 1.0.0.
- [Release notes](https://github.com/stalwartlabs/mail-parser/releases)
- [Changelog](https://github.com/stalwartlabs/mail-parser/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stalwartlabs/mail-parser/commits)

---
updated-dependencies:
- dependency-name: mail-parser
  dependency-version: 1.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
mail-parser 1.0 is a rewrite with a read-only view API. Port
apps/receiver-rs/src/mail/parse.rs to it and move to 1.0.1, which fixes
parameters folded after "=" (filename, name, boundary).

The stored document keeps its shape and, for ordinary mail, its content:

- Attachments are 1.0's RFC 8621 list plus every other leaf that is not
  text shown in a body. RFC 8621 leaves out an image shown inline in both
  bodies (Apple Mail's pasted photo) and a text part of an alternative it
  discards; 0.11 listed both, so they stay listed.
- Text and HTML attachments are stored converted to UTF-8 from their
  charset and a forwarded message as its raw message, as 0.11 stored
  them. Sizes come from decoded_len() when the bytes are not kept.
- A blank Subject or Message-ID stays null (1.0 reads it as "").

Changes that come from 1.0 itself, all fixes: a boundary inside a line
no longer ends a part (0.11 cut the text off there); a message that
forwards several messages lists each; header names with a space, a
control character or a leading colon are no longer read as From or
Subject; the last quantum of unpadded base64 is kept; UTF-7 and UTF-16
decode correctly. RFC 8621 edge cases also move: a named text/html
alternative after text/plain is an attachment, and a text/plain with
Content-Disposition: attachment inside an alternative is too.

Checked by running the old and new parser side by side over mail-parser's
corpora (309 messages plus mbox and maildir samples) and hand-made
Apple Mail, Outlook and attachment messages: everything not listed above
is identical, and an 11 MB message parses in about a third of the time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RFC 8621, which mail-parser 1.0 follows, makes a text/html version of a
multipart/alternative an attachment when it carries a file name and
follows the text/plain one. Mail clients still show it as the message
and 0.11 read it as the HTML body, so read it as the HTML body (and do
not list it as an attachment) when the HTML body has no HTML otherwise.
Content-Disposition: attachment still makes it an attachment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kroqdotdev
kroqdotdev force-pushed the dependabot/cargo/apps/receiver-rs/mail-parser-1.0.0 branch from 87be17b to 08c0ee7 Compare November 5, 2026 11:46
@kroqdotdev

Copy link
Copy Markdown
Owner

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Action not completed

Review skipped.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 23 minutes.

- Keep the named HTML parts as parts, not ids: the HTML body no longer
  searches every part once per id, and the attachment filter is a binary
  search. An alternative of 9,990 named HTML parts took 113 ms; it now
  parses as fast as on 0.11.
- When the text body yields no text, convert the named HTML, as for
  HTML-only mail, so such a message has text and text_from_html.
- Changelog: text and HTML parts marked as attachments, or text parts
  with a file name, are listed as attachments now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kroqdotdev
kroqdotdev merged commit b01b0f5 into main Nov 5, 2026
28 checks passed
@kroqdotdev
kroqdotdev deleted the dependabot/cargo/apps/receiver-rs/mail-parser-1.0.0 branch November 5, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant