Test email in CI without parallel jobs colliding
Give every test worker its own inbox, watch mail arrive live instead of guessing with a fixed sleep, and check exactly what your app sent.
Free plan includes 500 emails a month. No credit card.
- 1Checkout and buildStandard CI steps, nothing email-specific yet
- 2Sign up test userUses a dedicated Inceptmail address for this run
- 3Open the inboxCheck what arrived instead of polling an SMTP catcher
- Assert and continueExtract the code or link, then keep testing the flow
Why email is the flaky part of most test suites
Everything else in a test can run in isolation, but email usually means waiting on something outside the test process.
Parallel jobs share an inbox
If every CI run uses the same test address, two jobs running at once can read each other's codes and links.
SMTP sandboxes need an API
Reading mail back out programmatically usually means an SMTP-capture tool's own API, adding a dependency your test suite has to learn.
Flaky waits for delivery
A fixed sleep before checking the inbox is either too short and flaky, or too long and slows every run down.
How to wire email into a test suite in four steps
Set the pattern up once, then reuse it for every flow that sends mail.
- 01
Give each run its own inbox
Use a stable address per test worker, for example ci-{worker}@inceptmail.dev, or one per suite.
- 02
Trigger the email from your test
Sign up, request a reset, or whatever action in your suite sends the email under test.
- 03
Check the inbox in the dashboard
Confirm what arrived, in real time, without waiting on a fixed delay in the test.
- 04
Extract and assert
Pull the code or link from the message you need and continue the test with it.
What a reliable email test setup looks like
Most email-related flakiness in CI traces back to one of these.
One address per parallel worker
Two jobs running at the same time never read from the same inbox.
No arbitrary sleeps
The test waits on the message actually arriving, not a fixed timeout that guesses.
Clean state between runs
An inbox from a previous run does not leak an old message into a new test.
Works with any mail provider
The test does not care whether your app sends through SES, Postmark, or another provider.
Readable failures
When an email never arrives, the failure clearly says so instead of timing out generically.
Retention matches your pipeline
Old test mail ages out automatically, so CI inboxes do not grow indefinitely.
Common email testing failures in CI
Most of these show up as a flaky test long before anyone traces them back to email.
| Failure | What you will notice |
|---|---|
| Cross-run collisions | One job's verification code shows up in a different job's test. |
| Flaky timing | The suite passes locally but times out waiting for mail in CI. |
| Stale message read | A test passes by reading an old email instead of the new one. |
| Hardcoded test address | Every environment and branch shares one address, hiding real bugs. |
| No cleanup | A CI inbox accumulates months of unrelated test mail. |
| Silent provider failure | The email never actually sent, but the test only reports a timeout. |
Test email in CI with Inceptmail
A stable, private address per worker, so parallel test runs never trip over each other.
A stable address per worker
Create as many inboxes as your pipeline needs, each one private and permanent.
Live delivery
Mail appears the instant it is sent, so a test does not need a fixed sleep to be reliable.
Preview and raw HTML
Confirm exactly what your app sent, not just that something arrived.
Shared with your team
Give the whole team visibility into what CI's test mail actually looks like.
The same address pattern also covers local development and staging environments.
Automated email testing FAQ
How do I test email content from Playwright or Cypress?
Put a stable Inceptmail address in your test fixtures, trigger the email-sending action, then check the inbox in the dashboard for the message and extract what you need from it. There is no public API yet, so this step is manual today, a scripted assertion needs to wait for that.
How do I avoid parallel CI jobs reading each other's email?
Give each parallel worker, or each test run, its own inbox address rather than sharing one across the whole pipeline. A private address per project or per worker means one job's mail never ends up in another's way.
Does this replace an SMTP-capture tool in CI?
It solves a different part of the problem. An SMTP sandbox captures your app's own outbound SMTP traffic. Inceptmail is a real receiving address, so it also works for mail sent by any service, direct or third-party, without reconfiguring SMTP for the CI environment.
How fast does mail arrive in CI?
Delivery is live, the message appears in the dashboard as soon as your provider sends it, similar to the delay you would see checking a local mail-catcher.
Can I clean up test inboxes automatically?
Messages age out on their own, 7 days on Free and 90 on Pro, so CI test mail does not accumulate indefinitely even without manual cleanup.
Is Inceptmail free for CI usage?
Yes. The Free plan includes 500 emails a month, 3 inboxes per project, and 7 days of message history, with no credit card needed.
Give your test email a proper home.
Create your first inbox in under a minute. The Free plan covers a whole project.
Get started free