A free, real email inbox for automated tests. One API call gives you a fresh @receivemail.dev address; you point your app's signup or password-reset flow at it, then read what arrives. No account, no API key.
Install playwright-receivemail. Each test gets its own fresh inbox as a mailbox fixture:
npm i -D playwright-receivemail
import { test, expect } from "playwright-receivemail";
test("a new user can verify their email", async ({ page, mailbox }) => {
await page.goto("/signup");
await page.getByLabel("Email").fill(mailbox.address);
await page.getByRole("button", { name: "Create account" }).click();
const link = await mailbox.waitForMatch(/https:\/\/[^\s"]+\/verify[^\s"]*/, {
subjectContains: "verify",
timeout: 30_000,
});
await page.goto(link);
await expect(page.getByText("Email verified")).toBeVisible();
});
Install cypress-receivemail and register its commands in your support file:
npm i -D cypress-receivemail
import { addReceivemailCommands } from "cypress-receivemail";
addReceivemailCommands();
cy.createMailbox().then((mb) => {
cy.visit("/signup");
cy.get("input[name=email]").type(mb.address);
cy.contains("button", "Create account").click();
cy.getEmailMatch(/\b\d{6}\b/).then((code) => cy.get("input[name=code]").type(code));
});
Two HTTP calls. Create a mailbox:
curl -X POST https://receivemail.dev/mailboxes \
-H 'content-type: application/json' -d '{"ttlMinutes": 15}'
# => {"address":"a1b2c3d4e5f6@receivemail.dev","expiresAt":"...","secret":"..."}
Send your app's email to address, then read it with the secret:
curl https://receivemail.dev/mailboxes/a1b2c3d4e5f6@receivemail.dev/messages \
-H 'authorization: Bearer <secret>'
# => {"address":"...","messages":[{"from_address":"...","subject":"...","body_text":"...","received_at":"2026-09-26T04:54:46Z"}]}
Poll every few seconds until the message you expect shows up, or call GET /mailboxes/:address/wait?timeout=25 with the same header: it holds the request open and returns as soon as a message arrives ({"timed_out":true} if none does). Messages are newest first; received_at is ISO 8601 in UTC.
Match against body_text (or subject). Typical patterns:
const code = body_text.match(/\b\d{6}\b/)?.[0];
const link = body_text.match(/https:\/\/[^\s"]+\/verify[^\s"]*/)?.[0];
The Playwright and Cypress helpers do this for you: pass the regex to waitForMatch / getEmailMatch.
You choose the address lifetime with ttlMinutes: 1 to 60 minutes, 15 by default. Received mail is deleted after about 24 hours. Use a new address per test run rather than reusing one.
Reading a mailbox needs the secret returned when it was created, and addresses are random. Mail sent to an address nobody reserved can't be read through the API. Still, treat these inboxes as throwaway test infrastructure: don't send real users' personal data to them.
Yes. The agent-identity-mcp MCP server gives an agent (Claude, Cursor and others) a disposable receivemail.dev inbox for free, plus a real UK phone number for SMS codes through sms-florin (paid). There is also an n8n node.
Yes, within the limits above. If you need HTML bodies, attachments, custom domains or long-lived inboxes, a paid service such as Mailosaur or MailSlurp fits better; see our comparisons with Mailosaur, MailSlurp and Mailinator.