How to block disposable email addresses at signup
Three ways to catch temporary e-mail addresses on your signup form, from a static blocklist to an API, with code, and the mistakes that block real users.
What counts as a disposable e-mail address
A disposable (or temporary, throwaway, burner) address comes from a service that hands out inboxes without registration, usually for minutes or hours. Mailinator, Guerrilla Mail, 10 Minute Mail and thousands of lesser-known domains work this way. They are useful to people who want to avoid newsletters, and equally useful to anyone creating many accounts.
Three neighbouring categories are often confused with them and need different treatment:
- Privacy relays like Sign in with Apple's
privaterelay.appleid.com, DuckDuckGo'sduck.comor Firefox Relay forward to a real, long-lived inbox. Blocking them hurts privacy-minded customers. Treat them as a small risk signal at most. - Free providers like Gmail, Outlook.com or Yahoo are not disposable. Their abuse pattern is different: aliases of one inbox, covered in our Gmail alias guide.
- Domains that cannot receive mail at all — typos like
gmial.comor invented domains. These are worth catching too, because nobody can confirm an account there.
Option 1: a static blocklist in your code
Open-source lists of disposable domains are maintained on GitHub and contain tens of thousands of entries. The simplest approach is to load one into a set and check the domain at signup:
# Python DISPOSABLE = set(open("disposable_domains.txt").read().split()) def is_disposable(email: str) -> bool: domain = email.rsplit("@", 1)[-1].strip().lower().rstrip(".") parts = domain.split(".") # match subdomains too: mail.tempdomain.com -> tempdomain.com return any(".".join(parts[i:]) in DISPOSABLE for i in range(len(parts) - 1))
It costs nothing and adds no latency. The downsides:
- It goes stale. New disposable domains appear all the time, and many services rotate domains specifically to get around blocklists. A list you copied six months ago misses the newest ones, which are exactly the ones abusers use.
- Lists disagree. Different lists include different domains, and some contain mistakes. Merging several gives better coverage but more maintenance.
- You need a refresh job and a deploy (or a reload) every time it changes.
Option 2: check the mail server (MX)
A DNS lookup for the domain's MX records tells you whether it can receive mail at all. It catches typos and invented domains that no blocklist contains:
# Python, with dnspython import dns.resolver def can_receive_mail(domain: str) -> bool: try: return len(dns.resolver.resolve(domain, "MX", lifetime=2)) > 0 except dns.resolver.NXDOMAIN: return False except Exception: return True # DNS trouble is not the user's fault: fail open
Cache the result per domain, keep the timeout short, and never reject a signup because your DNS resolver had a bad moment. Note that an MX check does not catch disposable services — they receive mail perfectly well, that is their job.
Option 3: an API that does both and keeps itself current
An API moves the list maintenance and the MX lookups out of your code. Attrelix merges several public lists, refreshes them daily, records when each domain was first seen, checks the mail server, and normalizes Gmail aliases in the same call — and also scores the network and device, so you get one decision per signup rather than an e-mail verdict alone. You can try the domain lookup for free on the disposable e-mail checker.
curl https://attrelix.com/v1/check \ -H "Authorization: Bearer $ATTRELIX_SECRET" \ -H "Content-Type: application/json" \ -d '{"email":"someone@mailinator.com","ip":"203.0.113.9"}'
The response includes email.disposable, email.relay, email.mx and the normalized address, along with the overall decision and the reasons behind it.
Mistakes that block real users
- Blocking relays. Apple's private relay is used by many iPhone users signing in with Apple. Blocking it blocks them.
- Blocking on DNS errors. A timeout is not proof that a domain is fake.
- Over-broad lists. Some community lists include small legitimate providers or company domains. If a customer complains, allowlist the domain instead of arguing.
- A dead-end error message. “Invalid e-mail” confuses a real person who typed a real address. Say that temporary inboxes aren't accepted and ask for another address.
What a disposable check won't catch
Blocking throwaway domains raises the cost of abuse a little: the abuser switches to Gmail. From there, the abuse shows up as many accounts behind one inbox or one device. That is where detecting multiple accounts takes over.
Summary
- Separate disposable domains, privacy relays, free providers and dead domains.
- A static list is a fine start but goes stale; refresh it or use an API.
- Use MX checks for dead domains, and fail open on DNS trouble.
- Expect abusers to move to Gmail aliases next, and normalize addresses.