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 {}