If you ship software that sends email — password resets, magic-link logins, signup verifications, invoices, weekly digests — you have a testing problem most teams never properly solve. The naive approach is to send the test emails to your own mailbox. That works for a week, until you forget the test scripts are running and your real inbox is thirty deep in "Confirm your account at acme-staging.test". Worse, you stop noticing the test mail enough to spot when something legitimate breaks.
This guide is about a different approach: use a disposable inbox like tenmin.app as the recipient. The address is real, mail genuinely flows through the same path it will in production, and the inbox is gone in ten minutes regardless of whether your test cleaned up after itself. We'll walk through three workflows — interactive QA, automated end-to-end tests, and template review — and the trade-offs of each.
Why a disposable inbox beats the obvious alternatives
The two most common alternatives to a real recipient address are capturing the email before it leaves your system, and mocking the sender library. Both have their place, but both also have a gap a disposable inbox covers nicely.
SMTP-capture services like Mailpit, MailHog, and Mailtrap intercept outbound mail and show it in a web UI. They are excellent for development. They are also not the same path as production. The mail never leaves your network, never traverses your real sending provider's infrastructure, never gets scored by a spam filter, and never renders in a real mail client. If your bug is "the link in the email has a broken Mailgun click-tracking wrapper," a capture service won't show it; the wrapping happens at the provider, after you've handed the message off.
Mocking the sender library — patching nodemailer.sendMail or django.core.mail.send_mail to write to memory instead of going out — has the same problem squared. You're now not testing the integration at all, just your own wrappers around it. Mocking is fine for unit tests of business logic ("did we attempt to send a welcome email?"), but it's the wrong tool when you need to verify the end-to-end behaviour of "when a user signs up, they actually receive a functional verification link."
A disposable inbox sits between the two: real network path, real provider, real rendering — but a recipient that you don't care about and that disappears on its own. You get the full integration test without the inbox-pollution cost.
Workflow 1: interactive QA
You're testing a new signup flow. Click "register," see what arrives, click the link, see what happens. Run the flow with a fresh inbox each time.
- Open tenmin.app in a separate tab. Copy the address it generated.
- Paste it into your app's signup form. Submit.
- Switch back to the tenmin.app tab. The mail arrives in seconds — the page polls every three seconds.
- Click into the message, follow the link, finish the flow. If you need to go through it again, hit "Refresh" on the inbox card to generate a brand-new address.
Two things to be aware of. First, the link in the email almost certainly contains a verification token tied to that specific recipient address. If your app rejects the token because the URL is being clicked from a different browser session than the one that signed up, that's a real bug worth catching — but it's not specific to using a disposable inbox. Second, the tenmin.app HTML renderer strips scripts and renders inside a sandboxed iframe, so any tracking or analytics in the email body won't fire. That's a feature for the recipient, but if you're specifically testing whether the click-tracking pixel works, you'll need to view the raw HTML and verify the image URL manually.
Workflow 2: automated end-to-end tests
You want to wire the signup-receives-mail loop into Playwright or Cypress so it runs in CI. The challenge is that a disposable inbox needs a real recipient address and a way for the test to fetch the mail. tenmin.app's read endpoint is the same one the web UI polls, so it works fine for this — though you should be a polite citizen about how often you hit it from CI.
The shape of the test is:
- Generate a random local part in the test (six hex characters, same format as the web UI). Build the address
[email protected]. - Drive the signup flow with that address.
- Poll
https://api.tenmin.app/api/inbox/<localpart>until a message arrives or a timeout fires (thirty seconds is usually plenty; sixty if your sending provider has a cold-start delay). - Extract the verification URL from the message body — usually with a regex — and have the test navigate to it.
- Continue the test with the user now in a verified state.
Some hygiene to apply here. Poll every two to three seconds, not every two hundred milliseconds; you'll get rate-limited and you're being wasteful. Cap the wait — if a message hasn't arrived in sixty seconds, the test should fail loudly rather than hang the CI run. And tag the local part with something that identifies your project (e.g., myapp-3f9c2a) so that if we ever see an unusual amount of traffic to a prefix, we can correlate it to a real user.
Don't overload us
tenmin.app is on Cloudflare's free tier. We don't currently rate-limit aggressively because we don't need to — most usage is humans clicking through one signup. If your CI starts hitting us with thousands of requests per hour, we'll have to start throttling, and your tests will start flaking. A rough budget: a few hundred requests an hour from a single project is invisible to us; a few thousand starts to be visible.
If you're doing genuinely high-volume testing, run your own disposable receiver. The entire architecture is documented in our behind-the-scenes guide, and you can clone the shape — Cloudflare Email Routing, a Worker, KV storage with TTL — onto your own domain in an afternoon. The code is small, the dependencies are single-digit, and the free tier easily handles tens of thousands of test messages a month.
Workflow 3: template review
The reason this category of testing matters is template rendering. Gmail strips <style> blocks but keeps inline styles; Outlook on Windows uses the Word rendering engine and breaks anything that depends on flexbox; Apple Mail respects dark-mode media queries but Yahoo Mail does not; some clients block remote images by default and some don't. Your local capture tool's "preview" tab will show none of this correctly. A real email client will.
For template review, the disposable-inbox workflow is:
- Pick three or four target clients you actually care about — typically Gmail web, Outlook desktop, Apple Mail on iOS, and one webmail client like Yahoo or ProtonMail.
- Set up forwarding from a tenmin.app address into each of those clients for the duration of your review session. (Most clients accept "forward all from X to Y" rules; some let you set this up as a one-line filter.)
- Send a copy of the template from your staging environment to the tenmin.app address.
- Open each client and compare rendering.
A cheaper version, if you don't have accounts set up across multiple clients: pay ten dollars a month for a service like Litmus or Email on Acid that renders templates against eighty clients automatically. For a one-time check, the manual route is fine; for ongoing QA on a frequently-updated template, the paid service is worth it.
Things to test that are easy to forget
A short checklist of things that benefit from end-to-end testing and that are awkward to catch with capture tools:
- Long signup tokens get URL-wrapped. Outlook's "safe links" rewrites links above a certain length in ways that can break tokens. If your tokens are over a hundred characters, this hits you in production but not in dev.
- From-address consistency. When you send from
[email protected], some clients fold messages from that sender together. If your password-reset and welcome email use slightly different From addresses, users may not find the one they're looking for in their inbox. - Unsubscribe header presence. Gmail surfaces a one-click unsubscribe button only if you set the
List-Unsubscribeheader correctly. Test that your transactional sender adds it for the categories you'd expect, and crucially doesn't add it for the categories you wouldn't (e.g., security alerts). - Reply behaviour. What happens when a user replies to your no-reply address? If the reply bounces, do they see a useful bounce? If it doesn't, where does it go?
What disposable inbox testing can't do
Two specific limitations worth being honest about. First, you can't reliably test deliverability through a disposable receiver. Cloudflare Email Routing accepts mail permissively for our domain because we ask it to; a Gmail recipient would be much stricter. If you're debugging a "Gmail is sending us to spam" problem, you need to test against a real Gmail account, not a tenmin.app inbox.
Second, anything that depends on the recipient interacting with the message in a real mail client — opening on a phone, swiping to mark as spam, marking as not-spam, adding to contacts — can't be reproduced via the tenmin.app web view, which renders the message in a sandboxed iframe with no client-side mail-app behaviour. For those flows, either forward into a real client (as in the template review section above) or set up a dedicated test inbox at a real provider.
Further reading
- How tenmin.app works under the hood — and why it costs $30/year to run is the right place to start if you want to build your own disposable receiver instead of depending on ours.
- Disposable email vs. email aliasing covers when you'd want a stable alias instead of a throwaway, including for testing flows that span more than ten minutes.