“Disposable email detected.”
Now what?
Your E2E suite was green for months. Then your own signup form — or the identity vendor behind it — started rejecting your test addresses as disposable email, and every run went red without a line of code changing. Here's what actually happened, which fixes are dead ends, and the one that's permanent.
What actually happened
Signup fraud is fought with domain blocklists: public and commercial lists of domains known to hand out free, anonymous inboxes. Validation services check MX records, score domain age and reputation, and match against those lists. It works, and it's everywhere — baked into identity vendors, bot-protection layers, and thousands of hand-rolled isDisposable() checks.
The awkward part: to a blocklist, a shared email-testing domain is indistinguishable from temp mail. Anyone can get an address on it, mail flows in programmatically, nobody replies. Every shared inbox domain — every tool's, including ours — eventually gets listed. This isn't a bug in your test suite or a failure of your vendor; it's the fraud-prevention ecosystem working exactly as designed on a domain that matches the pattern.
The fixes that don't fix it
- Plus-addressing a real mailbox (
qa+run42@gmail.com): back to shared mutable state — parallel runs collide, old messages match new assertions, and providers rate-limit or flag the pattern. You traded one flake for three. - Hopping to a fresh temp domain: the lists update faster than you do. Blocklist maintainers watch domain registrations feeding mail-receiving infrastructure; a new domain with no reputation trips domain-age heuristics all by itself. This race has a house, and you're not it.
- Allow-listing test domains in production code: now your fraud check has a documented hole shipped to production, and its name is in your repo. Security review will find it; so might someone else.
The fix that's permanent: receive on a domain you own
Blocklists list other people's domains — shared infrastructure any stranger can use. A subdomain of your own company domain is categorically different: it inherits your root domain's age and reputation, no stranger can get an address on it, and no blocklist has a reason to touch it. Fraud checks that verify MX records find a real mail exchanger and pass.
Two DNS records point a subdomain's mail at MailFixture — one to prove you own it, one to route the mail:
; route the subdomain's mail to us tests.acme.dev. MX 10 mx.mxsink.sh. ; one-time ownership proof (token from the dashboard) _mfx.tests.acme.dev. TXT "mfx-verify=k7f2…"
Verification is automatic once the records propagate; from then on anything@tests.acme.dev is a programmatic inbox your suite can mint on demand — createInbox({ domain: 'tests.acme.dev' }) — with the same long-poll and OTP extraction as before. Your root domain's mail (MX for acme.dev itself) is untouched; only the subdomain routes to us.
This is also why the fix is sticky: the reputation your test domain accumulates is yours, attached to a domain you control, not to a vendor's shared namespace. Custom domains are on every paid plan, from $15/mo.
One boundary worth stating
Everything above assumes you're testing your own product's signup flow — that's what MailFixture is for, and our terms draw exactly that line: registering accounts on services you don't control is prohibited; testing flows you own is the point. If what you actually need is to mass-register accounts somewhere you don't operate, no email-testing tool is the right answer, including this one.