email_address
An RFC 5322-compliant EmailAddress newtype for parsing and validating email addresses in Rust.
Repository Health
Technical Analysis
email_address provides a strongly-typed EmailAddress wrapper around String, built specifically for validating and working with email addresses per the relevant IETF specifications (RFC 1123, 3629, 3696, 4291, 5234, 5321, 5322, 5890, 6531, 6532). Addresses are constructed exclusively through FromStr::from_str or parse_with_options, which run the full local-part and domain grammar checks and return a typed Error enum on failure rather than a boolean or panic.
Beyond ASCII, the crate supports UTF-8 local parts and domains (internationalized addresses), quoted local parts, domain literals (IPv4/IPv6 in brackets), and optional display-name parsing ("Name <user@example.com>"). An Options struct exposes chainable builder methods for relaxing or tightening RFC edge cases, such as requiring a minimum number of domain segments or disallowing domain literals, so consumers can match their own validation policy without forking the parser.
What You Get
- A typed
EmailAddressnewtype that can only be constructed from a string that has already passed RFC-grammar validation. - Static
is_valid,is_valid_local_part, andis_valid_domainhelpers for pre-construction checks without allocating. - A configurable
Optionsbuilder for relaxing/tightening RFC edge cases: minimum sub-domains, domain literals, and display-name support. - Accessors for the parsed components —
local_part(),domain(),email(),display_part()— plusto_uri()formailto:links andto_display()forName <user@example.com>formatting. - Optional
serdesupport (on by default via theserde_supportfeature) for serializing/deserializingEmailAddressas a plain string.
Common Use Cases
- Validating email addresses submitted through a web form or API before persisting them.
- Parsing addresses from
mailto:links or email headers into their component parts. - Enforcing stricter-than-default rules (e.g. requiring a TLD) on user-submitted addresses via
Options. - Deserializing untrusted JSON/config input into a guaranteed-valid
EmailAddresstype via serde.
Under The Hood
Architecture
The crate is implemented as a single src/lib.rs file (~1,900 lines including its extensive test suite) following a newtype-wrapper pattern: EmailAddress(String) can only be built through FromStr::from_str or parse_with_options, both of which funnel into parse_address → split_parts → parse_local_part/parse_domain → character-class predicate functions (is_atext, is_qtext_char, is_dtext_char). There is no internal module layering beyond public API surface, parsing internals, and character predicates — a deliberate flat structure for a narrowly scoped grammar validator, where the Options struct and predicate functions are the load-bearing abstraction and any RFC-rule change touches them directly.
Tech Stack
Pure Rust (edition 2018) with zero required runtime dependencies. The only dependency is optional serde ~1.0, gated behind the default-on serde_support feature for Serialize/Deserialize. Dev-dependencies (claims 0.8, serde_assert 0.8) support test assertions and serde round-trip testing. Build tooling is plain cargo; the crate publishes to crates.io with docs.rs configured for a single target (x86_64-unknown-linux-gnu). No web framework, database, or external service integration — this is a leaf utility crate.
Code Quality
The test module contains dozens of table-driven test cases covering Wikipedia’s canonical valid/invalid email examples, multi-script Unicode local parts (Chinese, Hindi, Ukrainian, Greek, German, Russian), Options-driven parsing variants, and case-sensitivity/equality semantics, plus a separate serde_tests module for serialization round-trips. Error handling is fully typed through a dedicated Error enum implementing std::error::Error, Display, Clone, and PartialEq — the public API never panics or swallows a validation failure. The crate opts into strict lint groups (#![warn(missing_docs, unreachable_pub, rust_2018_idioms, ...)]) and denies unsafe code and several deprecated patterns. CI runs both a build workflow and a dedicated security-audit workflow.
API Design
The public surface is intentionally minimal: construct via the standard FromStr trait, or use is_valid/is_valid_local_part/is_valid_domain for pre-construction checks. The Options type uses chainable, const fn builder methods (with_minimum_sub_domains, without_domain_literal, with_display_text, etc.) so callers can express a validation policy declaratively. Component accessors (local_part, domain, email, display_part) avoid extra allocation by borrowing from the original string, and nearly every public method carries a runnable doctest, keeping the crate’s documentation and its guarantees in sync.