Mailfornet

Temp Mail for Developers

Testing a signup flow means testing the email in it. Here is why that is harder than it looks, and the approaches that survive contact with CI.

Every product with a signup has the same untested seam: the user enters an address, a message goes out, and a code comes back. It is the one step nobody wants to break, and it is the step most test suites skip — because testing it properly requires a real mailbox that produces a new address on demand.

Why the usual approaches break

One shared test mailbox

The classic approach: a real account that every test signs up with. It works until two tests run at once and each reads the other's code, or until your application refuses the address because it already exists. Parallel CI turns this from an annoyance into a permanent flake.

Plus addressing

you+test1@gmail.com is clever and free. It also breaks when the application normalises plus tags before checking for duplicates — which many do, precisely to stop people creating multiple accounts. Now your test suite cannot create a second user.

Mocking the mail entirely

Fast, and it tests nothing. A mocked sender passes happily while your SPF record is broken, your template has a dead link, or your provider is rejecting the domain. The bug you most want to catch is the one mocking hides.

A public disposable inbox

Using a public temp mail site from a test means anyone who guesses the address reads the verification code — and it means screen-scraping a web page that is free to change under you.

What a test actually needs

How it looks in practice

The Mailfornet API covers exactly this. A test creates an inbox, signs your application up with that address, then asks for the message — and the request holds open until it arrives rather than returning empty:

const inbox = await mail.inboxes.create({ ttlMinutes: 10 });
await signUp(inbox.address);
const msg = await mail.messages.wait(inbox.id, { subject: 'Verify' });
const code = msg.text.match(/\d{6}/)[0];

That is the whole pattern. It runs the same way in Playwright, Cypress, Jest or Vitest, because it is an HTTP call rather than a browser trick. Webhooks are available too, signed with HMAC, when you would rather be told than ask.

The official client is on npm as mailfornet — zero dependencies, TypeScript types included. The quickstart has a working test in five minutes, and the full reference is at /api.

What it costs

There is a free tier of 100 requests a month, with no card, which is enough to wire the API into a project and watch it work. Paid plans start at $9 a month, and beyond a plan's quota you buy prepaid credits — nothing is ever charged automatically, because an API called from a loop should never be able to surprise you with a bill. See developer pricing.

Where the line is

This API is for testing software you own. It is not for creating accounts in bulk on services you do not, and our Terms of Service apply to it exactly as they do to the rest of Mailfornet. That boundary is not decoration — bulk signup is what gets disposable domains blocklisted, which would make the service worse for the people using it properly.

Common questions

Why not just use plus addressing in tests?

Because many applications strip plus tags before checking whether an address is already registered — often deliberately, to stop duplicate accounts. When yours does, the suite can no longer create a second user, and the failure looks like a bug in your code.

How does a test wait for the email without a sleep loop?

Add a wait parameter to the messages endpoint and the request stays open until mail lands, up to 60 seconds. Or register a webhook and be pushed the message instead. Both beat polling on a timer.

Does it work with Playwright, Cypress or Jest?

Yes. It is an ordinary HTTP API, so it works anywhere you can make a request. The npm client is zero-dependency with TypeScript types, and the quickstart shows a complete test.

Is there a free tier?

Yes — 100 requests a month, no card and no expiry. Enough to integrate the API and see a real signup test pass before deciding anything.

How long do API inboxes last?

You choose, from 1 minute to 24 hours. They expire on their own, so a test run never leaves anything to clean up.