TempMaily.co
Developers

Automate Email Verification Testing with a Temp Mail API

TempMaily Team9 min read

A temp mail API for testing lets your automated tests do what a human tester used to do by hand: create a fresh inbox, trigger a signup against it, wait for the verification email, pull the code out, and finish the flow — all in code, with no mailbox open in a browser. If your product sends a confirmation email during signup, that email is a wall your end-to-end (E2E) tests slam into. A disposable-mail REST API is how you get through it reliably, in CI, on every run.

This post covers why programmatic inboxes are the right primitive, the exact shape of an automated verification test, and a realistic Node example that polls for a message and extracts a code with a regex. The code here is illustrative — treat the API reference as the source of truth for request and response shapes.

Quick answer

Use a temp mail API in tests when your product requires email verification, password reset, invite acceptance, or any other email-dependent step. The best pattern is to create a unique inbox per test run, trigger the user flow with that address, poll for the expected message with a timeout, extract the code or link from the full message body, then delete or abandon the inbox. This avoids shared-mailbox race conditions, stale test accounts, and manual CI steps.

For CI and E2E tests, polling is usually simpler and more deterministic than webhooks. Use webhooks when the mail should trigger a background system instead of unblocking a test runner.

Why E2E tests need programmatic inboxes

Any signup worth testing has an email step, and that step is where naive test setups break down. The problems are specific:

A disposable-mail API solves all four by giving every test run its own unique, throwaway inbox that your code fully controls. Each address is isolated, so parallel runs never cross wires; each is fresh, so there is no stale state; and each is discarded after the assertion, so nothing accumulates. This is the same disposability that makes temp mail useful for signups generally — here it is just driven by a test runner instead of a person.

The automated verification flow

Every email-verification test, regardless of framework, follows the same five beats:

  1. Create an inbox. Call the API to mint a new disposable address. Hold onto both the address and its inbox ID.
  2. Trigger the signup. Drive your app — through Playwright, Cypress, an HTTP client, whatever — using that address as the user's email.
  3. Receive the message. Wait for the verification email to land. Either poll the messages endpoint on an interval, or let a webhook push the message to you.
  4. Extract the code or link. Fetch the full message body and run a regular expression to pull out the numeric code or the confirmation URL.
  5. Assert and finish. Submit the code (or visit the link), then assert the account reaches a verified state.

The only real decision is beat three: poll or push.

Polling vs. webhooks

Both are first-class; pick by context.

For a test suite, polling is almost always the pragmatic choice. For a long-running service that reacts to mail, reach for the webhook.

The API shape at a glance

TempMaily's API is a small, predictable REST surface under /v1, authenticated with a Bearer API key in the Authorization header. The three endpoints you need for a verification test map exactly onto the flow above:

Plus webhooks for push delivery when you want messages to come to you instead. Exact paths, parameters, pagination, and response fields are documented at /docs/api — always reconcile your client against that, since the snippet below is intentionally simplified to show the shape, not to be copy-pasted verbatim.

API access is a Premium feature ($9.90/mo), which also gets you the dedicated and custom domains worth using in tests so your own app does not reject the address as disposable.

A realistic Node example

Here is the poll-and-extract pattern in plain Node. It creates an inbox, then polls until the verification email arrives, then pulls a six-digit code out of the body. Swap the endpoint details to match the reference.

const API = "https://tempmaily.co/v1";
const KEY = process.env.TEMPMAILY_API_KEY; // Premium API key

const headers = {
  Authorization: `Bearer ${KEY}`,
  "Content-Type": "application/json",
};

// 1. Create a fresh disposable inbox for this test run.
async function createInbox() {
  const res = await fetch(`${API}/inboxes`, { method: "POST", headers });
  if (!res.ok) throw new Error(`createInbox failed: ${res.status}`);
  return res.json(); // -> { id, address }  e.g. "[email protected]"
}

// 3. Poll the messages endpoint until a matching email lands (or we time out).
async function waitForMessage(inboxId, { timeoutMs = 30000, intervalMs = 2000 } = {}) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const res = await fetch(`${API}/inboxes/${inboxId}/messages`, { headers });
    const { messages = [] } = await res.json();
    const hit = messages.find((m) => /verify/i.test(m.subject));
    if (hit) {
      // 4. Fetch the full message so we have the complete body to parse.
      const full = await fetch(`${API}/messages/${hit.id}`, { headers });
      return full.json(); // -> { subject, text, html, ... }
    }
    await new Promise((r) => setTimeout(r, intervalMs));
  }
  throw new Error("Verification email never arrived within timeout");
}

// 4. Pull the code out of the body with a tightly scoped regex.
function extractCode(message) {
  const body = message.text || message.html || "";
  const codeMatch = body.match(/\b(\d{6})\b/);
  if (codeMatch) return codeMatch[1];

  // Or extract a confirmation link instead of a numeric code:
  const linkMatch = body.match(/https?:\/\/[^\s"']*\/verify[^\s"']*/i);
  if (linkMatch) return linkMatch[0];

  throw new Error("No verification code or link found in message");
}

// The full flow, as it would sit inside a test.
async function runVerification(triggerSignup) {
  const inbox = await createInbox();          // 1
  await triggerSignup(inbox.address);          // 2  (drive your app here)
  const message = await waitForMessage(inbox.id); // 3
  const code = extractCode(message);           // 4
  return code;                                 // 5  -> submit + assert
}

Wired into a runner, triggerSignup is where Playwright or Cypress fills your signup form with inbox.address, and the returned code is what you type into the verification field before asserting the account is confirmed. The webhook variant replaces waitForMessage entirely: your endpoint receives the message payload and resolves a promise your test is awaiting.

What to watch for

A few things separate a test that passes once from one that stays green in CI.

The bottom line

A temp mail API for testing turns the email-verification step from the flakiest part of your E2E suite into just another assertion. Create an isolated inbox per run, drive the signup, poll (or receive a webhook) for the message, extract the code with a scoped regex, and finish the flow — no human, no shared mailbox, no race conditions. It is the difference between "we skip the email step in CI" and "our signup is tested end to end on every commit."

Programmatic access is part of TempMaily Premium. Start with the full API reference for exact endpoints and payloads, and if you are new to disposable inboxes in general, what is a temporary email covers the fundamentals the API is built on.

Frequently asked questions

What is a temp mail API for testing?

It is a REST API that lets your test code create disposable inboxes and read the mail they receive, programmatically. Instead of a human opening a mailbox to copy a verification code, your test creates an inbox, points a signup at it, then fetches the message and extracts the code automatically. It makes email-dependent flows testable in CI.

Why can't I just use a shared mailbox for E2E tests?

Shared mailboxes create race conditions: parallel test runs collide on the same messages, and you cannot reliably tell which email belongs to which run. Programmatic disposable inboxes give each test its own unique address, so verification emails never cross wires, and the inbox is discarded afterward.

Should I poll for the email or use a webhook?

Poll in test runners and CI, where the test is already blocking and waiting for a result. Use a webhook for push-based automation — background jobs or services that should react to an inbound email without holding a loop open. TempMaily supports both; webhooks POST the message to your endpoint as it arrives.

How do I extract a verification code from the email body?

Fetch the full message, then run a regular expression over the text or HTML body. For a numeric code, a pattern like a six-digit match works; for a confirmation link, match the href to your verification route. Always scope the regex tightly so you match the code and not an unrelated number in the footer.

Is the TempMaily API a premium feature?

Yes. Programmatic API access, including inbox creation, message reading, and webhooks, is part of TempMaily Premium at $9.90/mo. Authentication uses a Bearer API key. The full endpoint reference lives at /docs/api, which is the source of truth for request and response shapes.

Will disposable domains get rejected by the app I'm testing?

Sometimes, if your own product blocklists known disposable domains. For testing, use a Premium dedicated or custom domain that your app treats as legitimate, so the verification flow behaves exactly as it would for a real user.

Guides

How Long Does a Temporary Email Last?

How long does a temporary email last? It varies by service — minutes to days. TempMaily free lasts 24 hours; Premium lets you keep an address with no expiry.

5 min read

Get a free disposable inbox

A live throwaway address, no signup, real-time delivery. Upgrade to Premium for custom domains, forwarding, and no expiry.