Local SMTP capture for automated tests

Test the emails
your users actually receive.

Trigger your app’s real email flow and assert the exact link or code from your test. Everything is captured on localhost — not one message leaves your machine.

$ npx inboxtap

GET /api/emails/latest?to=signup%40local.test

{
  "email": {
    "subject": "Verify your account",
    "codes": ["482910"],
    "links": ["https://app.test/verification?…"]
  }
}

The problem

Where do your test emails go?

Sent to made-up addresses like test@example.com, they bounce or vanish unseen. Worse: with production SMTP in dev, one bad seed emails real people.

The catch

InboxTap catches everything on localhost

Point your app at localhost:1025. Every recipient is accepted and every message is stored on your machine — nothing crosses the network boundary.

The payoff

Your test reads the real email

Await the exact verification link or OTP your user would receive, and assert the whole flow — signup to verified.

The problem

Where do your test emails go?

Sent to made-up addresses like test@example.com, they bounce or vanish unseen. Worse: with production SMTP in dev, one bad seed emails real people.

The catch

InboxTap catches everything on localhost

Point your app at localhost:1025. Every recipient is accepted and every message is stored on your machine — nothing crosses the network boundary.

The payoff

Your test reads the real email

Await the exact verification link or OTP your user would receive, and assert the whole flow — signup to verified.

Built for deterministic test suites

Local by default

SMTP and HTTP bind to localhost. InboxTap never relays mail.

Parallel-safe inboxes

Unique client-generated addresses isolate concurrent test workers.

REST API

List, retrieve, wait for, and clear captured messages over local HTTP.

Automatic extraction

Discover HTTP(S) links and unique 4–8 digit codes from parsed mail.

Test SDK

Await messages, links, codes, and regex matches from Bun or Node tests.

Bounded resources

Storage, message size, and long-poll waits all have predictable limits.

From browser action to inbox assertion

The whole flow, in one test.

Create an isolated address, submit it through your app, then wait for the expected value. InboxTap works with Playwright, Vitest, Jest, and other Bun or Node runners.

signup.spec.ts
import { InboxTapClient } from "inboxtap/client";

const inboxTap = new InboxTapClient();
const inbox = await inboxTap.createInbox({ alias: "signup" });

await page.getByLabel("Email").fill(inbox.address);
await page.getByRole("button", { name: "Create account" }).click();

const verificationUrl = await inbox.waitForLink({
  subject: /verify your email/i,
  contains: "/verification",
});

await page.goto(verificationUrl);

Node 20+ · Bun or npm

$ npx inboxtap

SMTP on localhost:1025. API on localhost:8025. Ready.

Read installation guide →

Practical email-testing resources

Integrations, guides, and honest comparisons.

Connect InboxTap to your test stack, prove complete authentication flows, and choose the local email tool that fits your team.

Free · Open source · MIT licensed

Keep test email local and observable.

Use it, inspect the source, or help shape the next release.