Skip to main content

Crate mailrs_mime

Crate mailrs_mime 

Source
Expand description

§mailrs-mime

Crates.io docs.rs License

RFC 2045 / 2046 MIME body parser. Walks the multipart tree, decodes Content-Transfer-Encoding (base64, quoted-printable, 7bit, 8bit, binary), exposes text / HTML extraction + find-by-content-type + attachment iteration.

Layered: built on top of mailrs-rfc5322 (headers), mailrs-rfc2231 (params), and mailrs-rfc2047 is available for downstream callers who need encoded-word header decode.

Replaces residual mail-parser usage in inbound code paths where only the MIME tree shape matters (find calendar invite part, extract attachments, get the text body for indexing).

§Quickstart

use mailrs_mime::parse;

let raw = b"Content-Type: multipart/alternative; boundary=\"x\"\r\n\
\r\n\
--x\r\n\
Content-Type: text/plain\r\n\
\r\n\
plain version\r\n\
--x\r\n\
Content-Type: text/html\r\n\
\r\n\
<p>html version</p>\r\n\
--x--\r\n";

let root = parse(raw);
assert!(root.content_type.is_multipart());

// Find the HTML alternative:
let html = root.find_by_content_type("text/html").unwrap();
assert_eq!(html.body_text().as_deref(), Some("<p>html version</p>"));

// Iterate all parts depth-first:
for part in root.walk() {
    println!("{}", part.content_type.mime_type());
}

§What this crate does

  • parse(raw)Part — top-level entry. Returns a tree matching the message’s multipart structure.
  • Part::walk() — depth-first iterator over self + descendants
  • Part::find_by_content_type("text/calendar") — exact-match lookup, useful for iTIP / iMIP invite extraction
  • Part::body_text() — for text/* leaves, decodes per the part’s charset= (via encoding_rs)
  • Part::attachments() + Part::attachment_filename() — finds parts marked attachment (by Content-Disposition or filename parameter)
  • Content-Transfer-Encoding decoders: base64, quoted-printable, identity (7bit/8bit/binary), unknown (passes through)
  • RFC 2231 parameter decoding built in — filename*=UTF-8''… forms surface as plain UTF-8 via Part::attachment_filename()

§What this crate does not

  • No RFC 2047 encoded-word decode in headers — that’s mailrs-rfc2047. Use it on From / Subject / display names after extracting via mailrs-rfc5322.
  • No body autodetection beyond charset — if the message lies about its charset, we trust the lie. (Real parsers occasionally apply heuristics for mojibake recovery; out of v1.0 scope.)
  • No DKIM / SPF / DMARC — separate stones (mailrs-dkim, mailrs-spf, mailrs-dmarc).
  • No address-list structured parseFrom: returns raw bytes via mailrs-rfc5322; building (name, addr) from it is downstream.
  • No outbound MIME builder — this crate is read-only. Use a builder crate for composing outbound mail.

§Layering

mailrs-mime                       ← this crate (MIME body tree)
   ├── mailrs-rfc5322             ← header lookup, lazy
   ├── mailrs-rfc2231             ← parameter encode/decode
   └── encoding_rs + base64       ← foundational

Each layer is independently published; downstream callers can pull whichever subset they need without the rest.

§Performance

Measured (criterion, M-series Mac, release):

OperationMedian
parse simple text/plain173 ns
parse multipart/alternative (2 parts)831 ns
find_by_content_type("text/calendar") (full parse + walk)1.39 µs

Compared to mail-parser 0.11 on the same inputs:

Pathmailrs-mimemail-parserratio
simple body_text207 ns194 ns~1.1×
invite-shape, first part lookup1.38 µs630 ns~2.2× (mail-parser faster)

The simple case is close to a wash; the multipart walk path is where mail-parser’s optimized internals still win. Future polish rounds may close that gap. v1.0 ships at shape parity — the data extracted is the same; perf is acceptable for inbound where parse cost is dwarfed by DNS / disk / DB calls.

Reproduce: cargo bench -p mailrs-mime --bench mime.

§License

Apache-2.0 OR MIT. Module layout:

  • content_type — parse Content-Type: header (type / subtype / params)
  • decoder — Content-Transfer-Encoding decoders (base64, qp, 7bit, 8bit)
  • partPart struct + multipart tree walker

Re-exports§

pub use content_type::ContentType;
pub use content_type::Disposition;
pub use decoder::TransferEncoding;
pub use part::parse;
pub use part::Part;

Modules§

content_type
Content-Type + Content-Disposition header value parsing.
decoder
Content-Transfer-Encoding decoders (RFC 2045 §6).
part
MIME tree parser: splits a message into a recursive Part structure with parsed Content-Type, Content-Transfer-Encoding, and decoded body bytes.