Email validation with syntax checking and normalization.
pip install philiprehberger-email-validateEmail validation with syntax checking and normalization.
pip install philiprehberger-email-validate
from philiprehberger_email_validate import validate_email
result = validate_email("user@example.com")
print(result.valid) # True
print(result.normalized) # "user@example.com"
print(result.domain) # "example.com"
from philiprehberger_email_validate import is_valid
is_valid("user@example.com") # True
is_valid("not-an-email") # False
from philiprehberger_email_validate import normalize
normalize(" User@Example.COM ") # "user@example.com"
normalize("first.last+tag@gmail.com") # "firstlast@gmail.com"
normalize("user+promo@example.com") # "user@example.com"
from philiprehberger_email_validate import validate_email
result = validate_email("user@example.com", check_mx=True)
if not result.valid:
print(result.error) # "MX lookup failed for domain: example.com"
from philiprehberger_email_validate import validate_email
result = validate_email("user@mailinator.com")
print(result.is_disposable) # True
from philiprehberger_email_validate import validate_email, set_disposable_domains
# Per-call extra domains
result = validate_email("user@tempmail.xyz", extra_disposable=["tempmail.xyz"])
print(result.is_disposable) # True
# Global merge with built-in list
set_disposable_domains({"tempmail.xyz", "fakeemail.org"})
from philiprehberger_email_validate import validate_email, is_role_based
result = validate_email("info@example.com")
print(result.is_role_based) # True
is_role_based("admin@example.com") # True
is_role_based("john@example.com") # False
from philiprehberger_email_validate import validate_email, suggest_domain
result = validate_email("user@gmial.com")
print(result.suggested_domain) # "gmail.com"
suggest_domain("hotmial.com") # "hotmail.com"
suggest_domain("gmail.com") # "" (no suggestion needed)
from philiprehberger_email_validate import validate_email
result = validate_email("user@example.com", strict=True)
print(result.valid) # True
result = validate_email(".user@example.com", strict=True)
print(result.valid) # False
print(result.error) # "Local part starts or ends with a dot (RFC 5321)"
from philiprehberger_email_validate import validate_many
results = validate_many(["user@example.com", "bad@@email", "test@gmail.com"])
for r in results:
print(r.normalized, r.valid)
# With concurrent MX lookups and strict mode
results = validate_many(emails, check_mx=True, concurrent=True, strict=True)
from philiprehberger_email_validate import extract_emails
emails = extract_emails("Contact hello@example.com or support@test.org")
# ["hello@example.com", "support@test.org"]
from philiprehberger_email_validate import email_parts
parts = email_parts("user@example.com")
print(parts.local) # "user"
print(parts.domain) # "example.com"
print(parts.tld) # "com"
from philiprehberger_email_validate import mask_email
mask_email("john@example.com") # "j***n@example.com"
mask_email("alice@example.com") # "a***e@example.com"
| Function / Class | Description |
|---|---|
EmailResult | Dataclass with valid, normalized, domain, error, is_disposable, is_role_based, and suggested_domain fields |
normalize(email) | Normalize an email: lowercase, strip whitespace, Gmail dot-insensitivity, plus-addressing cleanup |
is_valid(email) | Quick boolean syntax check |
validate_email(email, check_mx, extra_disposable, strict) | Full validation returning an EmailResult |
validate_many(emails, check_mx, concurrent, extra_disposable, strict) | Validate multiple emails with optional parallel MX lookups |
is_role_based(email) | Check if an email uses a role-based local part (info@, admin@, etc.) |
suggest_domain(domain) | Suggest a corrected domain for common typos |
set_disposable_domains(domains) | Merge additional domains into the global disposable domains set |
DISPOSABLE_DOMAINS | Mutable set of known disposable email domains |
ROLE_PREFIXES | Frozen set of known role-based email prefixes |
COMMON_DOMAINS | Frozen set of common email provider domains used for suggestions |
extract_emails(text) | Extract all valid email addresses from text, deduplicated |
email_parts(email) | Split email into structured parts (local, domain, tld, normalized) |
EmailParts | Dataclass with local, domain, tld, normalized fields |
mask_email(email, mask_char, visible) | Mask the local part for privacy display |
pip install -e .
python -m pytest tests/ -v
If you find this project useful: