structured-email-address
RFC 5321/5322/6531 conformant email address parser, validator, and normalizer for Rust.
What makes this different?
Every Rust email crate stops at RFC validation. This one goes further:
| Feature | email_address |
email-address-parser |
This crate |
|---|---|---|---|
| RFC 5322 grammar | Partial | Full | Full |
| RFC 6531 (UTF-8) | Yes | Yes | Yes |
| Subaddress/+tag extraction | - | - | Yes |
| Provider-aware dot-stripping | - | - | Yes |
| Configurable case folding | - | - | Yes |
| PSL domain validation | - | - | Yes |
| Anti-homoglyph detection | - | - | Yes |
| IDN domain Unicode accessor | - | - | Yes |
| Display name parsing | Yes | - | Yes |
| Configurable strictness | Partial | Partial | Full |
| Serde support | Yes | - | Yes |
| Zero dependencies* | Yes | nom | idna + 3 |
* Dependencies: idna, unicode-normalization, unicode-security. Optional: psl, serde.
Quick Start
use ;
// Parse with defaults (RFC 5322 Standard mode)
let email: EmailAddress = "user+tag@example.com".parse?;
assert_eq!;
assert_eq!;
assert_eq!;
// International domains: IDNA roundtrip
let email: EmailAddress = "user@münchen.de".parse?;
assert_eq!;
assert_eq!;
Configured Parsing
use ;
let config = builder
.strip_subaddress // user+tag → user
.dots_gmail_only // a.l.i.c.e@gmail.com → alice@gmail.com
.lowercase_all // USER → user
.check_confusables // detect Cyrillic lookalikes
.domain_check_psl // verify domain in Public Suffix List
.build;
let email = parse_with?;
assert_eq!;
assert_eq!;
assert!;
Display Names
use ;
let config = builder.allow_display_name.build;
let email = parse_with?;
assert_eq!;
Batch Parsing
Parse thousands of addresses in one call. Config is shared, results preserve input order:
use ;
let config = builder.strip_subaddress.lowercase_all.build;
let results = parse_batch;
assert!;
assert!;
assert!;
For large lists (10K+), enable the rayon feature for parallel parsing:
= { = "0.0.1", = ["rayon"] }
let results = parse_batch_par;
Batch Benchmarks (baseline)
100K emails (mix of valid + invalid), strip_subaddress + dots_gmail_only + lowercase_all config.
Apple M1 Pro, Rust 1.85, cargo bench --all-features.
| Variant | Time | Throughput |
|---|---|---|
parse_batch (sequential) |
49.1 ms | ~2.0M emails/sec |
parse_batch_par (rayon) |
9.6 ms | ~10.4M emails/sec |
Rayon gives ~5x speedup on this workload.
Strictness Levels
| Level | Grammar | Use case |
|---|---|---|
Strict |
RFC 5321 (envelope) | SMTP validation, reject exotic addresses |
Standard |
RFC 5322 (header) | Default — full grammar, no obsolete forms |
Lax |
RFC 5322 + obs-* | Legacy system interop |
Features
| Feature | Default | Description |
|---|---|---|
serde |
Yes | Serialize/deserialize as canonical string |
psl |
Yes | Domain validation against Public Suffix List |
rayon |
No | Parallel batch parsing via parse_batch_par() |
# Minimal (no serde, no PSL)
= { = "0.0.1", = false }
Anti-Homoglyph Protection
Detects visually confusable email addresses using Unicode skeleton mapping:
use confusable_skeleton;
// Cyrillic 'а' (U+0430) vs Latin 'a' (U+0061)
assert_eq!;
Support the Project
USDT (TRC-20): TFDsezHa1cBkoeZT5q2T49Wp66K8t2DmdA
License
Apache License 2.0