DNS MX verification — cached per domain, singleflight-deduplicated
emailMod.VerifyDomain(ctx, addr)
Soft-fail handling — ErrDomainUnresolvable means "DNS is down", not "email is bad"
errors.Is(err, email.ErrDomainUnresolvable)
Expected output (abridged)
=== ValidateAndNormalize ===
accepted " USER@EXAMPLE.COM " → "user@example.com"
accepted "user.name+tag@sub.example.co.uk" → "user.name+tag@sub.example.co.uk"
rejected "" → must not be empty
rejected "notanemail" → invalid format
rejected "user@localhost" → domain must contain at least one dot
rejected "user@example..com" → invalid format
=== VerifyDomain ===
domain OK : user@gmail.com
=== Error handling ===
ErrInvalidEmail: email: invalid address: invalid format
reason only : invalid format
Golden rule
Always normalize before storing and before querying the database. User@EXAMPLE.COM and user@example.com are the same address — store only the canonical form.
Command email demonstrates the auth/email module: validating, normalizing,
and optionally verifying that an email domain can receive messages via DNS MX lookup.