email-normalize
A Python 3.11+ library for normalizing email addresses by stripping
mailbox-provider-specific behaviors such as plus addressing
(foo+bar@gmail.com) and period ignoring (f.o.o@gmail.com).
Installation
pip install email-normalize
Usage
Synchronous
import email_normalize
result = email_normalize.normalize('f.o.o+bar@gmail.com')
print(result.normalized_address) # foo@gmail.com
print(result.mailbox_provider) # Google
print(result.mx_records) # [(5, 'gmail-smtp-in.l.google.com'), ...]
Async
For use within an asyncio application, use the Normalizer class directly:
import asyncio
import email_normalize
async def main():
normalizer = email_normalize.Normalizer()
result = await normalizer.normalize('f.o.o+bar@gmail.com')
print(result.normalized_address)
asyncio.run(main())
The Normalizer maintains a LFRU cache of MX lookups, making it efficient
for batch processing.
Without DNS Lookups
Use skip_dns=True to normalize against well-known domains without
performing MX record lookups:
result = email_normalize.normalize('user+tag@gmail.com', skip_dns=True)
This mode uses a static domain map and will not detect providers for custom domains.
Normalization Rules
| Provider | Plus Addressing | Strip Periods | Local Part as Hostname | Domain Folding |
|---|---|---|---|---|
| Apple | x | x† | ||
| Fastmail | x | x | ||
| x | x* | x† | ||
| Microsoft | x | |||
| ProtonMail | x | |||
| Rackspace | x | |||
| Yahoo | ||||
| Yandex | x | |||
| Zoho | x |
- Plus Addressing: Strips everything after
+in the local part - Strip Periods: Removes
.from the local part - Local Part as Hostname: Extracts the subdomain as the local part (Fastmail custom domains)
- Domain Folding: Rewrites provider alias domains to a single canonical domain
* Google strips periods only for consumer Gmail addresses (gmail.com and
googlemail.com). Google Workspace custom domains route through the same MX
servers but treat periods as significant, so periods are preserved for them
(plus addressing is still stripped).
† Some providers deliver one mailbox under several domain names. These alias
domains are folded to a single canonical form so the same mailbox always
normalizes to the same address: Google's googlemail.com → gmail.com, and
Apple's me.com and mac.com → icloud.com. Domains that share a provider
but are separate mailboxes (e.g. Microsoft's outlook.com/hotmail.com, or
Yahoo's yahoo.com/aol.com) are intentionally left unchanged.
Documentation
Full documentation is available at gmr.github.io/email-normalize.
Release files for email-normalize 3.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| email_normalize-3.2.0.tar.gz | 42.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| email_normalize-3.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 50.5 kB
Release files / email_normalize-3.2.0.tar.gz
| Download URL | email_normalize-3.2.0.tar.gz |
|---|---|
| Size | 42.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f83c0e96a9a6c0aa84e746a9f4c4772b85d1bd7a9833a52065b0b73510945f06
|
|
BLAKE2b-256 checksum How to use checksums |
188740b9778e0004358c237410ad95b76627c9eae8e7171c2b163faa25df3c03
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.
Transparency logRelease files / email_normalize-3.2.0-py3-none-any.whl
| Download URL | email_normalize-3.2.0-py3-none-any.whl |
|---|---|
| Size | 8.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3497f57c2f010f6e4aa9c7473d225fda37da0ed37adfbbd2d2a7146dee041920
|
|
BLAKE2b-256 checksum How to use checksums |
f9663cd3fa4d43eca27b482bc8be0481b3d2b6f313ff77134a1445cc81f9d9f9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.
Transparency log