VerifyEmail
All articles

How to Block Disposable Email Addresses at Signup (3 Approaches)

How to block disposable email addresses at signup: regex vs maintained blocklist vs API, MX-based detection, and the privacy relays you must never block.

Ryan Sullivan · Email Deliverability & Operations ·
disposable email signup validation email verification api fraud prevention developer guide

How to Block Disposable Email Addresses at Signup (3 Approaches)

Every free trial eventually meets the same user: fourteen accounts, fourteen Mailinator addresses, zero intention of paying. Here’s how to block disposable email addresses without turning away the real people who happen to use a privacy alias. You have three options: a regex or static blocklist you maintain yourself, a maintained list you refresh on a schedule, or a real-time API that checks each address as it’s typed. For most products the answer is a maintained list on the server, an explicit allowlist for privacy relays, and an API for the signups that actually cost you money. The most common answer, and the wrong one, is a hard block against a list nobody has touched since it was pasted in.

Vendor claims below come from their own docs and the raw list files, checked on 2026-09-17.

How to Block Disposable Email Addresses at Signup (3 Approaches)

What counts as a disposable email address, and what doesn’t?

A disposable address is one nobody expects to read a second email at: a public inbox anyone can open, or an inbox that expires in minutes or hours. Privacy relays are not disposable. They forward to a real inbox, persist, and support replies. Conflating the two is where most blocklist projects go wrong, so separate them first.

Mailinator describes its free tier as “a 100% free, public temporary or disposable email address,” where “you can use any address @mailinator.com and check those public inboxes” (Mailinator, checked 2026-09-17). That’s the target: no password, no owner, no second message. Compare Apple, which says Hide My Email “generates unique, random email addresses that automatically forward to your personal email inbox” (Apple Support, checked 2026-09-17). Same shape from the outside, opposite intent. A random-looking domain is not evidence of anything. Only its behavior is.

Why block disposable emails at signup at all?

Because a disposable signup can’t be reached again, skews activation and trial-conversion numbers, and is the default tool for trial and credit abuse. The tradeoff is real: every filter rejects some legitimate people. Whether that’s worth it depends on what a fake account costs you, and for most free-trial products it is.

PyPI is the reference case. In a 2024 post about a malware campaign, the PyPI admin wrote that “one of the most impactful mechanisms we currently have is prohibiting known ‘throw-away’ email domains from creating accounts on the index” (PyPI blog, 2024-06-16). The same post notes that a 160-project campaign then registered through outlook.com and hotmail.com. Read both halves. Blocking throwaways removed the cheap path, and it didn’t stop a motivated attacker, because nothing on the email layer does. There’s a smaller deliverability angle too: confirmation mail to expired inboxes bounces, and bounces feed the reputation ledger I covered in the bounce-rate post.

Approach 1: Can a regex or a static blocklist do the job?

A regex can’t, and a static list can for about a week. A regex validates the shape of an address, and x9k2@mailinator.com has a perfectly fine shape. A static list catches the well-known providers on the day you copy it, then decays as throwaway services rotate domains. You’ll never notice, because rejected signups don’t file bug reports.

The standard starting point is the disposable-email-domains repo: CC0 licensed, one domain per line, 8,883 lines when I pulled the raw file on 2026-09-17, with a commit that same morning. The maintainers are candid: “we cannot guarantee all of these can still be considered disposable but we do basic checking so chances are they were disposable at one point in time.” That describes every static list, and it cuts both ways. Domains get dropped by throwaway services and picked up by real businesses, so false-positive risk grows with the list’s age too.

One implementation detail people get wrong: the list stores registrable domains only, so user@foo.yopmail.com must match yopmail.com, and under a public suffix like .co.uk you match the third level. Splitting on @ and doing a plain set lookup misses every subdomain. Match on the registrable domain using the public suffix list.

Approach 2: What does a maintained list add?

A maintained list buys you freshness and, if you pick the right one, a documented method. The cost is that the big lists disagree by an order of magnitude, and bigger isn’t automatically better. Every extra domain is a chance to reject someone real.

Sizes on 2026-09-17: disposable-email-domains at 8,883, wesbos/burner-email-providers at 27,277, and eramitgupta/disposable-email, which aggregates other lists nightly and claims “110,880+” domains in its README. The gap isn’t 100,000 providers one project missed. It’s how much each is willing to sweep in, expired and parked domains and dynamic-DNS hostnames included.

The one I’d read first is 7c/fakefilter, because its method is different: rather than waiting for submissions, it says it will “actively monitor all known providers and get their domains almost realtime and distribute daily.” A throwaway service’s domain list is a live feed, and a list that polls the feed beats one that waits for a pull request. The tradeoff is a dependency on one volunteer project’s uptime, which its README tells you to plan for. Whichever list you pick, schedule the refresh. A list that was current when the feature shipped is a static list with extra steps.

Approach 3: When is a real-time API worth paying for?

When a bad signup costs more than a check, or when you need signals a list can’t carry: whether the domain has mail servers at all, whether the mailbox exists, whether the domain is a catch-all. The cost is latency on the signup path, a per-check price, and a dependency that can time out.

Most verification APIs return a disposable flag alongside the mailbox verdict, which matters because “not disposable” and “deliverable” are separate questions. VerifyEmail’s verification API runs the disposable check in the same pass as the live SMTP mailbox check, with disposable, role, and free addresses returned as separate flags so you decide which states are allowed. One credit per address, and duplicates and failures on our side are never charged. The honest downside: a network call on a form is always slower than a hash lookup, so set a short timeout and fail open.

Not sure it’s worth it at your volume? Run a few suspicious signups through the free disposable email checker and see what a list lookup alone would have missed.

How does MX-based detection catch domains that aren’t on any list?

Throwaway providers rotate domains faster than lists can follow, but they rarely rotate mail servers. Resolve the MX records for a signup domain and you get two signals: no MX at all means nothing can receive mail there, and an MX host you’ve already seen behind known throwaway domains means this new domain is probably the same operator.

I spot-checked this on 2026-09-17 by taking every 220th line of the disposable-email-domains file (40 domains) and resolving each one’s primary MX. Sixteen had no MX record at all. Of the remaining 24, three resolved to generator.email, three to vietxf.com, two to email.chatgpt.org.uk, and two to mail.wabblywabble.com: ten live domains on four mail hosts. A brand-new domain pointing at generator.email isn’t on any list yet, and it doesn’t need to be.

The tradeoff is shared infrastructure. One sampled domain resolved to ImprovMX and another to Cloudflare’s email routing, both of which forward mail for plenty of legitimate small domains. “No MX” is a safe block. “Known throwaway MX” is a strong flag. “Shared forwarding MX” is nothing on its own. Keep those three separate; the MX lookup tool shows a domain’s hosts and priorities if you want to eyeball one.

Which addresses look disposable but aren’t?

Privacy relays. They use unfamiliar domains and random local parts, and they’re often generated at the exact moment someone signs up for your product, which is precisely what a throwaway looks like. They belong to real people who chose privacy over convenience, and blocking them is a false positive with a paying customer attached.

The three you’ll see most, from their own docs:

  • Apple Hide My Email uses @privaterelay.appleid.com. Addresses forward to the verified Apple Account inbox, and users can “read and respond directly” (Apple Support, checked 2026-09-17). One catch for you as the sender: Apple’s developer docs say “if you don’t register all the source domains or emails that you use, email sent to the private relay service will result in a bounce message,” and registered domains must pass SPF (Apple Developer, checked 2026-09-17). If your Apple signups bounce, that’s your config, not a disposable address.
  • Firefox Relay uses @mozmail.com, including Premium subdomains like mask@yourname.mozmail.com. Masks “forward messages to your true email address,” and Premium users can reply within three months. Mozilla’s FAQ records the problem from the other side: “some sites may not accept an email address that includes a subdomain” (Firefox Relay FAQ, checked 2026-09-17).
  • DuckDuckGo Email Protection uses @duck.com, with generated addresses like amaze-gem-spider@duck.com. Private addresses “do not expire,” forward as long as the account is active, and “replies just work” (DuckDuckGo Help, checked 2026-09-17).

None of the three appear in the disposable-email-domains list as of 2026-09-17, which is correct. I wouldn’t trust any list to stay correct on this point, so pin an allowlist in your own code. If relay users generate more abuse than you can tolerate, that’s a rate-limit or challenge problem, not a blocklist problem.

The three approaches compared

Regex or static listMaintained list, scheduled refreshReal-time API
CatchesKnown providers on copy dayKnown providers plus recent rotationsListed domains, plus MX, pattern, and mailbox signals
MissesEverything registered after you copiedDomains newer than the refresh intervalWhatever the vendor’s model misses
False-positive riskGrows with age; recycled domainsGrows with list size; check relay handlingLowest, if the vendor allowlists relays
MaintenanceYou, foreverA cron job and a diffNone beyond the integration
LatencyMicrosecondsMicrosecondsOne network round trip
CostYour timeYour time, less of itPer check; link pricing
Best forPrototypes, internal toolsMost productsTrials, credits, anything with a payout

Should you block, flag, or challenge?

Flag by default, block only where a fake account has a direct cost, and always decide on the server. A client-side check is a courtesy that lets you suggest a work email while the user is still on the form. The server-side check is the only one that exists, because anyone can post directly to your endpoint.

The pattern I’d ship for a free trial:

  • Check server-side on the signup request; the client check is a UX layer only.
  • Match on the registrable domain, not the raw host.
  • Consult the allowlist first: privaterelay.appleid.com, mozmail.com, duck.com, and anything you’ve verified by hand.
  • “No MX” is a hard reject with a clear message.
  • “On the blocklist” is a soft flag for trials: create the account, withhold trial credits until a non-disposable address is confirmed.
  • Fail open on timeout. Log it, let the signup through, review the log. A vendor outage should never be your outage.
  • Rate-limit per IP and device regardless, because PyPI’s attackers didn’t need throwaways.

A minimal server-side check

Illustrative only, against a placeholder host. Swap in whichever list or API you chose above.

const RELAY_ALLOWLIST = new Set([
  "privaterelay.appleid.com",
  "mozmail.com",
  "duck.com",
]);

// `disposableDomains` is the registrable-domain set you refresh nightly.
export async function classifySignupEmail(
  email: string,
  disposableDomains: Set<string>,
): Promise<"ok" | "flag" | "reject"> {
  const domain = registrableDomain(email.split("@")[1].toLowerCase());
  if (RELAY_ALLOWLIST.has(domain)) return "ok";
  if (disposableDomains.has(domain)) return "flag";

  try {
    const res = await fetch(
      `https://verification-api.example/v1/verify?email=${encodeURIComponent(email)}`,
      { headers: { Authorization: `Bearer ${process.env.VERIFY_KEY}` },
        signal: AbortSignal.timeout(3000) },
    );
    const r = await res.json();
    if (r.mx === false) return "reject";
    if (r.disposable) return "flag";
    return "ok";
  } catch {
    return "ok"; // fail open; log and review
  }
}

Note what it doesn’t do: it never rejects on the list alone, and never rejects on a failed request. Those two lines are the difference between a filter and a support-ticket generator.

Where I’d land

Ship the maintained list with a nightly refresh and the relay allowlist today; that’s an afternoon and it removes the cheapest abuse path. Add the real-time check where a fake account has a price tag: trial credits, referral payouts, anything that touches a card. And accept the tradeoff out loud. You’ll still let some throwaways through, because the alternative is rejecting people who used Apple’s own privacy feature to sign up for your product.

If you’d rather not run the list yourself, VerifyEmail’s bulk verifier and API do the disposable, MX, and mailbox checks in one pass from one credit wallet. Get Started Free. Includes 100 free credits, no credit card required.

Frequently asked questions

Is a regex enough to block disposable email addresses? No. A regex only checks the shape of an address, and a throwaway address from Mailinator or Guerrilla Mail is perfectly well-formed. Disposable detection is a domain-reputation question, not a syntax question, so you need a domain list or a live check behind the regex.

Should I block Apple Hide My Email, Firefox Relay, or DuckDuckGo addresses? No. Addresses at privaterelay.appleid.com, mozmail.com, and duck.com are forwarding aliases that land in a real person’s inbox, don’t expire, and support replies. Apple, Mozilla, and DuckDuckGo all document this. Put those domains on an explicit allowlist so a stale blocklist can’t reject a paying user.

How often do disposable email domain lists go stale? Constantly. Throwaway providers rotate domains, so a list is missing entries the day you vendor it. The disposable-email-domains repo on GitHub had a commit on the day I checked and holds under 9,000 domains, while aggregated lists claim over 110,000. Either refresh the list on a schedule or use a service that does it for you.

Should the disposable check run on the client or the server? Both, but only the server counts. A client-side check gives instant feedback and a chance to suggest a work email. The server-side check is the one that actually prevents the account, because anyone can skip your JavaScript with a curl command.

Does blocking disposable emails hurt signup conversion? Hard blocks cost you some real people, mostly privacy-conscious users and anyone your list misclassifies. The lower-risk pattern for trials is to soft-flag: let the signup through, hold trial credits or the paid path until a work or personal address is confirmed, and fail open when the check itself times out.

Written by

Ryan Sullivan , Email Deliverability & Operations

Ryan has spent over a decade cleaning lists and protecting sender reputation for outbound teams and ESP marketers, and writes about the parts of email deliverability you usually learn the hard way.

Frequently asked questions

Is a regex enough to block disposable email addresses?
No. A regex only checks the shape of an address, and a throwaway address from Mailinator or Guerrilla Mail is perfectly well-formed. Disposable detection is a domain-reputation question, not a syntax question, so you need a domain list or a live check behind the regex.
Should I block Apple Hide My Email, Firefox Relay, or DuckDuckGo addresses?
No. Addresses at privaterelay.appleid.com, mozmail.com, and duck.com are forwarding aliases that land in a real person's inbox, don't expire, and support replies. Apple, Mozilla, and DuckDuckGo all document this. Put those domains on an explicit allowlist so a stale blocklist can't reject a paying user.
How often do disposable email domain lists go stale?
Constantly. Throwaway providers rotate domains, so a list is missing entries the day you vendor it. The disposable-email-domains repo on GitHub had a commit on the day I checked and holds under 9,000 domains, while aggregated lists claim over 110,000. Either refresh the list on a schedule or use a service that does it for you.
Should the disposable check run on the client or the server?
Both, but only the server counts. A client-side check gives instant feedback and a chance to suggest a work email. The server-side check is the one that actually prevents the account, because anyone can skip your JavaScript with a curl command.
Does blocking disposable emails hurt signup conversion?
Hard blocks cost you some real people, mostly privacy-conscious users and anyone your list misclassifies. The lower-risk pattern for trials is to soft-flag: let the signup through, hold trial credits or the paid path until a work or personal address is confirmed, and fail open when the check itself times out.