Skip to main content

daaki_message/
lib.rs

1//! RFC 5322 email message parser and builder.
2//!
3//! Provides three main operations:
4//! - [`parse_email`]: Parse raw RFC 5322 message bytes into a structured [`ParsedEmail`]
5//! - [`build_message`]: Construct RFC 5322 message bytes from an [`OutgoingEmail`]
6//! - [`parse_address_list`]: Liberally parse a comma-separated address list
7//!   (e.g., a user-typed recipient string or a decoded header value) into
8//!   [`Address`] records, without enforcing strict outgoing-mail validation
9//!
10//! # References
11//! - RFC 5322 (Internet Message Format)
12//! - RFC 2045 (MIME Part One — body format, Content-Transfer-Encoding)
13//! - RFC 2046 (MIME Part Two — media types, multipart boundaries)
14//! - RFC 2047 (MIME Part Three — encoded words in headers)
15//! - RFC 2183 (Content-Disposition)
16//! - RFC 2231 (MIME parameter encoding)
17//! - RFC 6532 (Internationalized email headers)
18
19// `fuzzing` cfg is set by cargo-fuzz (nightly) — not known to check-cfg.
20#![cfg_attr(not(fuzzing), allow(unexpected_cfgs))]
21
22pub mod error;
23pub mod types;
24
25mod builder;
26mod parser;
27
28pub use builder::build_message;
29pub use error::Error;
30pub use parser::{parse_address_list, parse_email, parse_headers_only};
31pub use types::{
32    Address, BuiltMessage, DateTime, HeaderName, MessageId, OutgoingAttachment, OutgoingEmail,
33    ParsedAttachment, ParsedEmail, TlsMode, ValidationError,
34};
35
36/// Crate-level `Result` alias using [`Error`].
37pub type Result<T> = std::result::Result<T, Error>;
38
39/// Fuzz-only entry points. Not part of the public API.
40///
41/// Exposed behind `#[cfg(fuzzing)]` (set automatically by `cargo-fuzz`) so
42/// that out-of-crate fuzz harnesses can reach `pub(crate)` parser helpers.
43#[allow(unexpected_cfgs)]
44#[cfg(fuzzing)]
45#[doc(hidden)]
46pub mod fuzz {
47    /// Thin wrapper around [`crate::parser::decode_encoded_words`].
48    ///
49    /// Decodes RFC 2047 encoded words in a header value.
50    pub fn decode_encoded_words(input: &str) -> String {
51        crate::parser::decode_encoded_words(input)
52    }
53
54    /// Thin wrapper around [`crate::parser::parse_rfc5322_date`].
55    ///
56    /// Parses an RFC 5322 date-time string (RFC 5322 Section 3.3).
57    pub fn parse_rfc5322_date(input: &str) -> Option<crate::types::DateTime> {
58        crate::parser::parse_rfc5322_date(input)
59    }
60
61    /// Thin wrapper around [`crate::builder::encode_rfc2047_if_needed`].
62    ///
63    /// Encodes a string using RFC 2047 encoded words if it contains non-ASCII
64    /// characters (RFC 2047 Section 5).
65    pub fn encode_rfc2047_if_needed(text: &str) -> String {
66        crate::builder::encode_rfc2047_if_needed(text)
67    }
68}
69
70/// Consumer-facing README examples must compile against the current public API.
71///
72/// This turns the README into executable doctests so stale field names or
73/// helper signatures are caught during `cargo test --doc`.
74#[cfg(doctest)]
75#[doc = include_str!("../README.md")]
76mod readme_doctests {}