Mailtrap alternative โ€” when you don't need an SMTP trap, just a mock email API

Credit first: Mailtrap's Email Sandbox is genuinely good at what it's for. It catches real SMTP traffic before it reaches anyone, previews your HTML across clients, scores spam likelihood, and gives QA a shared inbox to eyeball. If your question is "does this email look right and would it deliver?" โ€” keep Mailtrap, or self-host Mailpit (open source, excellent, unlimited). Nothing on this page replaces an SMTP trap.

The wall you hit is quota. Per Mailtrap's official pricing (August 2026), the Sandbox free tier is 50 test emails per month, one sandbox, 10 stored emails per sandbox, one user. A single CI run of a signup + password-reset + notification suite can burn a week's worth; a month of PR builds is hopeless. The next step is $17/month for 500. And here's the thing most teams discover at that moment: the majority of their "email tests" never needed SMTP capture at all.

1. Two different questions

QuestionRight tool
"Does the email render correctly? Would it hit spam? What does QA see?"SMTP trap โ€” Mailtrap Sandbox or self-hosted Mailpit
"Does my code call the provider correctly โ€” right payload, right recipient? Does it survive a 401, a 429, a timeout? Does the retry fire?"API-level mock โ€” this guide

Modern apps rarely speak SMTP themselves; they POST JSON to SendGrid, Mailgun, Postmark, Resend โ€” or Mailtrap's own sending API. That means the code path you're testing in CI is an HTTP call, and the failure modes that page you at 3am are HTTP failure modes. An SMTP trap can't stage any of them. A mock API can, on cue, for free.

2. A Mailtrap-shaped mock in one paste

Mailtrap's sending API answers POST /api/send with {"success":true,"message_ids":[โ€ฆ]} (and errors as {"success":false,"errors":[โ€ฆ]} โ€” we verified that error body against the live API before publishing). Recreate the dialect:

BASE=https://mockbird.mockbird.workers.dev
P=$(curl -s -X POST $BASE/api/projects -H 'content-type: application/json' \
     -d '{"name":"mailtrap-mock","blank":true}')
PID=$(echo $P | sed 's/.*"id": *"\([^"]*\)".*/\1/')
KEY=$(echo $P | sed 's/.*"adminKey": *"\([^"]*\)".*/\1/')

# Mailtrap-send-shaped: POST /api/send โ†’ success + a fresh message id
curl -s -X POST $BASE/api/projects/$PID/routes -H "x-admin-key: $KEY" \
  -H 'content-type: application/json' -d '{
  "method":"POST","path":"/api/send","status":200,
  "body":"{\"success\":true,\"message_ids\":[\"{{uuid}}\"]}"}'

Point your HTTP client at https://mockbird.mockbird.workers.dev/m/<PID> instead of send.api.mailtrap.io and send normally:

curl -s -X POST https://mockbird.mockbird.workers.dev/m/<PID>/api/send \
  -H 'content-type: application/json' -H 'Authorization: Bearer anything' -d '{
  "from":{"email":"app@example.com"},"to":[{"email":"user@example.com"}],
  "subject":"Reset your password","text":"..."}'
# {"success":true,"message_ids":["bc393c41-838e-4605-93b8-a04a0530f887"]}

The request inspector records what your code actually sent โ€” payload, headers, auth scheme (token value redacted) โ€” so the assertion becomes "we emailed the right person with the right subject", not "the function didn't throw". Same pattern works for Postmark and Resend and SendGrid and Mailgun, all in the same project.

3. Failure drills no trap can stage

Every command below was run against the project above before publishing:

# Their real 401 dialect (body verified live): re-POST the route to flip it
curl -s -X POST $BASE/api/projects/$PID/routes -H "x-admin-key: $KEY" \
  -H 'content-type: application/json' -d '{
  "method":"POST","path":"/api/send","status":401,
  "body":"{\"success\":false,\"errors\":[\"Unauthorized\"]}"}'
# โ†’ HTTP 401 {"success":false,"errors":["Unauthorized"]}  (re-POST the 200 version to flip back)

# Deterministic fail-then-recover for retry logic:
POST /m/$PID/api/send?mock_seq=500,200        # โ†’ 500, then 200, 200, โ€ฆ

# Rate-limit burst (three rapid sends):
POST /m/$PID/api/send?mock_ratelimit=2        # โ†’ 200 200 429
# the 429 carries retry-after + x-ratelimit-limit/remaining/reset headers

# Slow provider / timeout drill:
POST /m/$PID/api/send?mock_delay=2000         # measured 2.10s round-trip

All simulation params compose with custom routes. One honest note: mock_ratelimit windows are clock-aligned 60-second buckets, so a burst can straddle a boundary โ€” when a test needs exact determinism, prefer mock_seq=429,200.

4. A queryable outbox (the part traps do with clicking)

Mailtrap's answer to "did we send it?" is a dashboard. For CI you want it API-queryable. Add an emails resource to the same project and have your test double write records:

curl -s -X POST $BASE/api/projects/$PID/resources -H "x-admin-key: $KEY" \
  -H 'content-type: application/json' -d '{
  "name":"emails","seed":0,
  "fields":[{"name":"to","type":"email"},{"name":"subject","type":"sentence"},
            {"name":"status","type":"oneOf","values":["queued","delivered","bounced"]}]}'

# your app-under-test (or a webhook) records the send:
curl -s -X POST $BASE/m/$PID/emails -H 'content-type: application/json' \
  -d '{"to":"user@example.com","subject":"Reset your password","status":"queued"}'

# your test asserts:
curl -s "$BASE/m/$PID/emails?status=queued&to=user@example.com"

Full recipe โ€” filters, X-Total-Count, PATCH-to-bounced flows, HMAC-signed delivery webhooks, snapshot fixtures for parallel workers โ€” in the mock email API guide.

Honest comparison

Mailtrap SandboxMailpit (self-host, OSS)Mockbird
Catches real SMTPโœ” its whole pointโœ”โœ— HTTP APIs only
HTML render preview / spam scoreโœ” polishedโœ” preview (no spam score by default)โœ—
Free quota50 test emails/mo, 1 sandbox, 10 stored, 1 userunlimited (your hardware)10k requests/project/day
Signup / setupaccount requiredrun a binary/containernone โ€” one curl
Fail on cue (401/429/500/sequences/latency)โœ—โœ— (can chaos SMTP responses, not your provider's API)โœ” query params
Assert payloads from CI, API-queryablepartial (API access on all plans, within quota)โœ” REST APIโœ” inspector + outbox
Provider API dialects (Mailtrap/Postmark/Resend/SendGrid shapes)n/an/aโœ” custom routes
Team dashboards, shared QA inboxโœ” (paid tiers scale)DIY hostingโœ— dashboard is per-project

Straight answer: if you send over SMTP or need rendering/spam checks, Mailtrap is worth its price โ€” or Mailpit free if you'll host it. If your CI is burning sandbox quota on tests that only assert payloads and exercise failure handling, move those tests to an API-level mock and let the trap do the one job only it can do. Most teams end up with both: five rendering tests through a trap, fifty behavior tests through a mock.

Notes & limits

Create yours

The paste block in section 2 is the entire setup โ€” or open the dashboard and click the route together. The same project also gives you a GraphQL endpoint, OpenAPI + TypeScript exports, and snapshotted fixtures.