DEV Community

heocoi
heocoi

Posted on

Building MailSink: a temp email API with MCP server on Cloudflare Workers

The problem

Testing email flows in CI has been painful for years. MailSlurp is $79/mo, Mailtrap's API isn't built for AI agents, and most alternatives want you to run your own SMTP server.

I wanted something different: a REST API callable from tests, with an MCP server so AI agents could run email-verified signup flows natively.

So I built it.

What it does

MailSink gives you programmatic temporary email inboxes via a simple REST API:

# Spin up a disposable inbox
curl -X POST api.mailsink.dev/v1/inboxes
# → signup-k8m2@codenotify.net

# Your app or agent signs up with that address...

# Wait for the verification mail, extract the OTP code
curl api.mailsink.dev/v1/inboxes/inb_rae1z/wait-for-code
# → { "code": "847291", "from": "stripe.com" }
Enter fullscreen mode Exit fullscreen mode

That's the whole API surface for the common case.

The MCP angle

An MCP server ships in the @mailsink/mcp npm package. Claude Code, Cursor, Windsurf, any MCP client can call these tools natively during autonomous workflows:

create_inbox({ ttl: 3600 })
// → signup-k8m2@codenotify.net

get_verification_code({ inbox_id, timeout: 30 })
// → { code: "847291" }
Enter fullscreen mode Exit fullscreen mode

Your agent can actually sign up for Stripe, GitHub, Clerk, Supabase. Not a browser automation wrapper. Native.

The architecture

Everything runs on Cloudflare's edge:

  • workers/api - Hono on Cloudflare Workers. Routes: inboxes, messages, domains, keys, auth (GitHub OAuth), billing (Stripe), internal. KV-based rate limiting.
  • workers/email - Cloudflare Email Routing handler. Parses incoming mail with postal-mime, writes metadata to D1, raw body to R2, triggers OTP extraction.
  • packages/shared - OTP + magic-link extractors for Stripe, GitHub, Google, Clerk, Supabase, Auth0, Resend, AWS. Raw MIME always available if the extractor misses.
  • mcp - @mailsink/mcp npm package. 7 tools exposed to MCP clients.

Why Cloudflare:

  • Sub-20ms p50 latency via 320+ edge locations
  • Email Routing handles SMTP receipt for free on shared domains
  • D1 for metadata, R2 for bodies, zero infra to manage
  • One deploy target, one config

What I learned

  1. Email parsing is harder than it looks. postal-mime handles MIME well, but OTP patterns across senders are wildly inconsistent. I built per-sender extractors for the top 8 services and fall back to generic regex patterns for everything else.

  2. MCP turned a dev tool into an agent tool. Same REST API, new audience. Zero additional code to maintain, major differentiator in the pitch.

  3. Cloudflare Email Routing + shared domains lets you skip running Haraka or Postfix for shared-domain inboxes. You only need your own SMTP receiver when you support Bring Your Own Domain.

  4. Pricing anchors matter. MailSlurp at $79/mo signals "enterprise." I priced Pro at $15/mo because the real differentiator is agent-friendliness, not feature parity.

Pricing

  • Free: 3 inboxes, 100 msgs/mo
  • Pro: $15/mo unlimited
  • BYOD on Pro+ (bring your own domain, waitlist)

Try it

Live at https://mailsink.dev. GitHub OAuth, you're in in 10 seconds.

Feedback welcome, especially on API shape and pricing positioning.

First open stable release. Still learning what breaks.

Top comments (0)