email_message_wire/lib.rs
1//! RFC822/MIME wire parsing and rendering for `email-message`.
2//!
3//! This crate focuses on wire format concerns and keeps `email-message` focused on
4//! outbound message representation.
5//!
6//! ```rust
7//! use email_message_wire::{parse_rfc822, render_rfc822};
8//!
9//! let raw = b"From: from@example.com\r\nTo: to@example.com\r\n\r\nHello";
10//! let message = parse_rfc822(raw).unwrap();
11//! let _bytes = render_rfc822(&message).unwrap();
12//! ```
13//!
14//! Current rendering support:
15//! - Structured body rendering for text, html, text+html, and MIME trees.
16//! - `Message::attachments` rendered as MIME parts with multipart nesting, base64 transfer
17//! encoding, Content-Disposition, and optional Content-ID.
18//! - RFC2231 `filename*=` parameter emitted for non-ASCII attachment filenames.
19//! - Attachment references are model-level values and must be resolved to bytes before
20//! rendering.
21//!
22//! # Feature interaction with `email-message`
23//!
24//! Depending on `email-message-wire` enables `email-message`'s `mime`
25//! feature for the calling crate as a side effect, `MimePart` becomes
26//! visible in `email_message`. The wire crate genuinely needs `mime`
27//! for full MIME-tree rendering, so this is unavoidable; downstream
28//! crates that want `MimePart` access have an alternative path through
29//! the wire dependency.
30//!
31//! # Parser semantics
32//!
33//! See [`parse_rfc822`] for the full decoding contract. Highlights:
34//! - Body charsets outside `utf-8`/`us-ascii`/`iso-8859-1`/`latin1` are
35//! decoded with `String::from_utf8_lossy`, invalid bytes become
36//! `U+FFFD` rather than producing an error.
37//! - Encoded words in unsupported charsets pass through as the raw
38//! `=?…?=` literal.
39//! - Duplicate `To:`/`Cc:`/`Bcc:`/`Reply-To:` lines are merged.
40//! - RFC 6532 (SMTPUTF8) inbound is not supported; non-ASCII header
41//! lines fail.
42//! - The returned `Message` has not been validated for outbound
43//! delivery, wrap via `OutboundMessage::new` if you intend to send
44//! it through a `Transport`.
45
46mod rfc822;
47
48pub use rfc822::{
49 MAX_INPUT_BYTES, MAX_MULTIPART_DEPTH, MAX_MULTIPART_PARTS, MessageParseError,
50 MessageRenderError, RenderOptions, decode_rfc2047_phrase, parse_rfc822, render_rfc822,
51 render_rfc822_with,
52};