EMAIL TESTING WITH SMTPBOX

Reliable email checks in CI and Playwright.

Give each test a unique recipient, wait for the captured message and assert its content without guessing how long email takes.

2,500 emails per month free · 5 team members · No card required

Prepare the CI environment

Create an inbox for the test suite. Configure the application under test with that inbox's SMTP credentials. Store SMTPBOX_API_KEY, SMTPBOX_INBOX_ID and TEST_APP_URL in your CI environment; the API key is separate from the SMTP credential.

Use synthetic accounts and a staging application you control. The example below reads an email for an existing test account whose reset request your test has just triggered.

Read and validate the reset link with Playwright

In a Playwright test, use its request fixture and expect import. Set recipient to the unique account address and trigger the reset before this code. Allow at least 60 seconds for the test.

const api = 'https://api.smtpbox.dev/v1';
const headers = {
  Authorization: `Bearer ${process.env.SMTPBOX_API_KEY}`,
};
const inbox = encodeURIComponent(process.env.SMTPBOX_INBOX_ID);
const response = await request.get(`${api}/inboxes/${inbox}/messages/wait`, {
  headers,
  params: { to: recipient, subject: 'Reset', timeout: 20 },
  timeout: 25000,
});
expect(response.ok()).toBeTruthy();
const payload = await response.json();
expect(payload.success).toBe(true);
const uid = encodeURIComponent(payload.data.uid);
let message;
await expect.poll(async () => {
  const result = await request.get(`${api}/messages/${uid}`, { headers });
  expect(result.ok()).toBeTruthy();
  message = (await result.json()).data;
  return Boolean(message.processed_at);
}, { timeout: 20000, intervals: [500, 1000, 2000] }).toBe(true);
const origin = new URL(process.env.TEST_APP_URL).origin;
const resetLink = message.links.map(({ url }) => new URL(url, origin))
  .find(url => url.origin === origin &&
    url.pathname.startsWith('/reset-password/'));
expect(resetLink, 'Expected a reset link on the test app').toBeDefined();
await page.goto(resetLink.href);

Adapt the subject, reset path, account fixture and final form assertions to your application. Do not treat this snippet as an SMTPBox SDK: it uses the real REST API through Playwright. See Playwright's request documentation.

Avoid cross-test matches

Use a random full recipient for every run, not just a common subject. The wait endpoint uses substring matching across the latest 50 messages. Split busy suites across inboxes and limit parallel mail bursts. HTTP 408 means no match arrived during the wait; it should fail the assertion with a useful diagnostic.

Know what to retain

Keep the run identifier, status code and message UID in test output. Avoid logging secrets, complete email bodies or reset links. Use a read/write key if you delete the message afterwards; delete that message rather than clearing the entire shared inbox.

Keep a second layer of application tests

Use fast mail fakes for unit-level behaviour and a smaller set of SMTP integration checks for critical journeys. A sandbox capture confirms the configured non-production mail path, not production inbox placement.

Start with a free inbox

Free includes 2,500 captured emails per month and 7-day retention. Unlimited is £14.99 per month with 30-day retention, subject to fair use.

Create your SMTPBox account Compare plans

Updated