How to Test Email Verification Without Using a Real Email
Verification email is the gate in front of every signup flow — and the step QA most often leaves untested. Not because it is hard, but because the usual tool, a personal inbox, is a terrible test fixture. Here is the setup that makes it an ordinary assertion.
Why a real inbox fails as a test fixture
- It is shared state. Filters, tabs of unread mail and a colleague's replies make every read non-deterministic.
- It is slow. Provider-level greylisting and spam scanning add minutes of delivery variance your test cannot control.
- It leaks. Pointing staging signups at a personal address puts real addresses into test databases and log files.
- It is not parallel. Two CI jobs using one inbox will eat each other's mail.
A disposable inbox from Tempx fixes all four: any name at tempx.uk becomes a working mailbox the moment mail is sent to it, readable over a free JSON API — no account, no setup, no cleanup.
The recipe
- Pick a fresh address for the run. Derive it from something unique —
verify-8f3a1@test.tempx.uk-style names never collide between parallel runs. - Do the signup with that address in your browser, script or E2E test, exactly as a user would.
- Poll the inbox API until the message appears:
GET https://tempx.uk/api/inbox?address=…returns the message list as JSON (240 reads/minute is plenty for a 2-second poll). - Assert on the message — sender, subject, and the code or link. Every message carries a 140-character text preview, which comfortably contains verification codes.
- Finish the flow — enter the code or open the link, and assert the account is actually activated.
# watch a verification mail arrive, then show it
ADDR="verify-8f3a1@tempx.uk"
for i in $(seq 1 30); do
MSG=$(curl -s "https://tempx.uk/api/inbox?address=$ADDR" | jq -r ".messages[0].preview // empty")
[ -n "$MSG" ] && echo "$MSG" && break
sleep 2
done
What to assert (and what not to)
| Assert on | Why |
|---|---|
| Sender address | Catches misconfigured From headers that tank deliverability |
| Subject line | The template regression users actually see in notifications |
| The code / link | Proves the flow is completable, not just that mail moved |
| Arrival time | Your verification SLA is part of the user experience |
| Exact HTML | Don't — templates change; assert structure or text, not pixels |
Failure modes worth a test each
- The resend button. Request the mail again and confirm a second message arrives — and that the first code is invalidated if your design says so.
- The expired link. If links expire after 30 minutes, test that an old link shows a helpful error, not a 500.
- The wrong-template check. A signup mail that renders the password-reset template passes every "did mail arrive" check and still fails the user.
For frameworks, the same recipe has ready-made shapes: Playwright, Cypress and Selenium each ship a complete working spec.
Create a temporary email address
Free, instant, no sign-up — messages auto-delete.
Go to your inbox