DEV Community

Jay Thorat
Jay Thorat

Posted on

I Built a Disposable Email Service Because Every Existing One Had Terrible UX

I needed a temporary email address. Simple enough, right?

I opened the top results — Guerrilla Mail, Temp Mail, 10MinuteMail — and every single one felt like stepping into a website from 2008. Ads covering half the screen, pop-ups, slow loading, confusing layouts. These are supposed to be privacy tools, yet they're stuffed with third-party trackers.

I closed all the tabs and thought: I'll just build one myself.

What I Built

MeowMail — a disposable email service at meowmail.in

  • One click, you get an inbox. No signup, no account, no cookies.
  • Emails arrive in real-time.
  • Everything auto-expires. Nothing is stored forever.
  • Zero ads. Zero tracking.

That's it. Nothing clever. Just a temp inbox that works and doesn't fight you.

The Tech Stack

This is where it got interesting.

Backend: Elixir + Phoenix

I didn't want to depend on a third-party email relay like Mailgun or SendGrid to receive emails. I wanted to own the entire pipeline. So I built a custom SMTP server in Elixir using gen_smtp.

The flow:

Incoming Email → SMTP Server → Email Parser → PostgreSQL → WebSocket broadcast
Enter fullscreen mode Exit fullscreen mode

Elixir was a perfect fit here. The BEAM VM handles thousands of concurrent SMTP connections without breaking a sweat, and Phoenix Channels gave me real-time delivery to the browser out of the box.

Key backend components:

  • SMTP Server — Accepts inbound email directly, validates sender/recipient, enforces size limits
  • Email Processor — Parses MIME, extracts headers/body/attachments, sanitizes HTML
  • Rate Limiter — Hammer-based rate limiting to prevent abuse
  • Cleanup Worker — Background process that purges expired emails (TTL-based)
  • REST API — Phoenix controllers serving inbox and email data to the frontend

Frontend: React + Vite + Tailwind CSS

Minimal, fast, dark-themed UI. No component library — just clean custom components.

  • Real-time updates via Phoenix WebSocket channels — new emails appear instantly without polling
  • Split-pane inbox — email list on the left, detail view on the right
  • Sandboxed HTML rendering — emails with HTML are rendered in a sandboxed iframe to prevent XSS
  • Attachment support — view and download attachments inline
  • Fully responsive — works on mobile

Infrastructure

  • PostgreSQL for email storage
  • Redis for rate limiting
  • EC2 for hosting
  • Cloudflare for DNS + Web Analytics (no Google Analytics — that would defeat the purpose)

Design Decisions I'm Happy About

1. No third-party email relay

Owning the SMTP layer means no vendor lock-in, no per-email costs, and full control over what gets accepted or rejected. The tradeoff is more complexity, but Elixir made it manageable.

2. TTL-based expiry, not user-triggered deletion

Emails expire automatically. Users can delete manually too, but the system doesn't rely on them to clean up. This keeps storage bounded and predictable.

3. No accounts for MVP

The simplest version of a temp mail service doesn't need auth. You visit, you get an inbox, you use it, you leave. Adding accounts later is a layered addition, not a rewrite.

4. WebSocket-first, not polling

Polling an API every few seconds is wasteful and gives a sluggish feel. Phoenix Channels made real-time delivery trivially easy — when an email hits the SMTP server, it's in your browser within a second.

What I'd Do Differently

  • Prerendering for SEO — It's a React SPA, so Google has to execute JavaScript to see content. SSR or prerendering would help with crawlability. On the list for later.
  • Email threading — Right now each email is standalone. Grouping by conversation would be a nice UX improvement.

What's Next

  • Email forwarding (like Firefox Relay)
  • Custom domain support (bring your own domain)

Try It

meowmail.in — takes one click, no signup.

If you've ever been frustrated by a bloated temp mail service, I built this for people like us. Would love to hear your feedback.

Top comments (0)