Skip to main content

philiprehberger-email-validate

Tests PyPI version Last updated

philiprehberger-email-validate

Email validation with syntax checking and normalization.

Installation

pip install philiprehberger-email-validate

Usage

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"

Quick Syntax Check

from philiprehberger_email_validate import is_valid

is_valid("user@example.com")   # True
is_valid("not-an-email")       # False

Normalization

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"

MX Lookup

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"

Disposable Email Detection

from philiprehberger_email_validate import validate_email

result = validate_email("user@mailinator.com")
print(result.is_disposable)  # True

Custom Disposable Domains

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"})

Role-Based Email Detection

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

Free Provider Detection

Flag consumer/free mailboxes (useful for filtering B2B signups that should use a company address):

from philiprehberger_email_validate import validate_email, is_free_email

result = validate_email("user@gmail.com")
print(result.is_free)  # True

is_free_email("user@gmail.com")        # True
is_free_email("user@acme-corp.com")    # False

Email Domain Suggestions

from philiprehberger_email_validate import validate_email, suggest_domain, suggest_email

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)

# Correct the whole address (local part and any +tag are preserved)
suggest_email("first.last+promo@hotmial.com")  # "first.last+promo@hotmail.com"
suggest_email("user@gmail.com")                # "" (no suggestion needed)

RFC 5321 Strict Mode

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)"

Bulk Validation

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)

Extract Emails from Text

from philiprehberger_email_validate import extract_emails

emails = extract_emails("Contact hello@example.com or support@test.org")
# ["hello@example.com", "support@test.org"]

Email Parts

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"

Mask Email

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"

Disposable check

from philiprehberger_email_validate import is_disposable

is_disposable("user@mailinator.com")   # True
is_disposable("user@gmail.com")        # False
is_disposable("not-an-email")          # False

Comparing emails

from philiprehberger_email_validate import compare_emails

compare_emails("Foo@Gmail.com", "foo@gmail.com")              # True
compare_emails("foo.bar+tag@gmail.com", "foobar@gmail.com")   # True
compare_emails("foo@a.com", "bar@a.com")                      # False

Deduplicating emails

Remove duplicates by normalized form, keeping the first original spelling and input order:

from philiprehberger_email_validate import dedupe_emails

dedupe_emails(["Foo@Gmail.com", "f.oo+news@gmail.com", "bar@example.com"])
# ["Foo@Gmail.com", "bar@example.com"]

Grouping by domain

Invalid addresses are collected under the None key:

from philiprehberger_email_validate import group_by_domain

group_by_domain(["a@Example.com", "b@test.org", "c@example.com", "oops"])
# {"example.com": ["a@Example.com", "c@example.com"], "test.org": ["b@test.org"], None: ["oops"]}

Serializing results

import json
from philiprehberger_email_validate import validate_email

json.dumps(validate_email("user@example.com").to_dict())

API

Function / Class Description
EmailResult Dataclass with valid, normalized, domain, error, is_disposable, is_role_based, is_free, 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.)
is_disposable(email) Check if an email's domain is in the disposable-domains set
is_free_email(email) Check if an email's domain is a known free/public provider (gmail, yahoo, etc.)
compare_emails(a, b) Check if two emails are equivalent after normalization
suggest_domain(domain) Suggest a corrected domain for common typos
suggest_email(email) Suggest a corrected full email address for a domain typo
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
FREE_EMAIL_DOMAINS Frozen set of known free/public email provider domains
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
dedupe_emails(emails) Remove duplicates by normalized form, keeping the first original spelling and input order
group_by_domain(emails) Group addresses by normalized domain; invalid addresses go under the None key
EmailResult.to_dict() Return the result fields as a plain dictionary

Development

pip install -e .
python -m pytest tests/ -v

Support

If you find this project useful:

⭐ Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT

Metadata

Release files for philiprehberger-email-validate 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for philiprehberger-email-validate 0.8.0
File Size Uploaded Provenance Actions
philiprehberger_email_validate-0.8.0.tar.gz 190.3 kB Without provenance Details for philiprehberger_email_validate-0.8.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for philiprehberger-email-validate 0.8.0
File Interpreter ABI Platform Actions
philiprehberger_email_validate-0.8.0-py3-none-any.whl Python 3 none any Details for philiprehberger_email_validate-0.8.0-py3-none-any.whl

Total release size: 201.5 kB

Release files / philiprehberger_email_validate-0.8.0.tar.gz

Download URL philiprehberger_email_validate-0.8.0.tar.gz
Size 190.3 kB
Tags Source
SHA-256 checksum
How to use checksums
dd2ec100ce9927940119b59f42de3d1689770dfc9bb3e2e524cfb9f3c9abef1d
BLAKE2b-256 checksum
How to use checksums
eae95c9e70a6b06070c4b26006777f2873ce4949c096d65331c5e1d7a2b5ba3d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release files / philiprehberger_email_validate-0.8.0-py3-none-any.whl

Download URL philiprehberger_email_validate-0.8.0-py3-none-any.whl
Size 11.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7e250e17bda189468ebc3f24573a72c7c63e010509f269520774b85bd371e5d4
BLAKE2b-256 checksum
How to use checksums
3cd74d92859d4ef9976fa19e75a98a80354ccef31121e82940bfa3d6bff3e44d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Security for philiprehberger-email-validate 0.8.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page