Sunday, August 9, 2026

Build Temporary Email Service Backend: Step-by-Step Guide

Over 300 billion emails are sent daily, yet developers building temporary email services face a unique challenge: handling inbound SMTP at scale without storing data permanently. Traditional mail servers like Postfix or Exim assume persistent mailboxes, but a disposable email backend must accept, parse, and expire messages in seconds — often across millions of ephemeral addresses. This guide walks through the architecture, code patterns, and infrastructure decisions needed to launch a production-ready temporary email service backend, with real implementation examples.

Quick Answer: Build a temporary email service backend by deploying an SMTP server (Postfix or Haraka) that routes to a message processor (Node.js/Go/Python), stores emails in Redis with TTL-based expiration, exposes a REST API for inbox retrieval, and adds DNS MX records, SPF/DKIM, and rate limiting for deliverability and abuse prevention.

Core Architecture: SMTP Ingestion to Ephemeral Storage

Why SMTP-First Design Matters

Temporary email services must accept mail from any sender on the internet. The only universal protocol for inbound delivery is SMTP on port 25. Unlike webhook-based services that require sender cooperation, an SMTP endpoint receives mail from Gmail, Outlook, transactional providers, and legacy systems alike. The architecture splits into three layers: an MTA (Mail Transfer Agent) that speaks SMTP, a message processor that parses MIME, and a fast ephemeral store (Redis or in-memory) with automatic TTL eviction.

Choosing Your MTA: Postfix vs. Haraka vs. Custom

Postfix is battle-tested, handles 100K+ messages/second on modest hardware, and supports policy delegates for custom routing logic. Haraka (Node.js) offers easier plugin development for developers comfortable with JavaScript. A custom SMTP server (Go's smtp package, Python's aiosmtpd) gives maximum control but requires handling RFC 5321 edge cases — connection limits, pipelining, TLS negotiation, and backpressure. For most teams, Postfix with a TCP policy service or HTTP webhook relay balances operational maturity with customization.

Message Flow Example: Postfix → HTTP Webhook → Redis

Configure Postfix transport_maps to route all mail for your domain (e.g., @tempmail.example) to a local HTTP endpoint via a lightweight relay script. The script receives raw MIME, parses it with a library like mailparser (Node) or email.parser (Python), extracts headers/body/attachments, generates a UUID for the recipient address if needed, and writes a JSON document to Redis with a 600-second TTL. The inbox API then reads from Redis by address key.

Building the Message Processor and Storage Layer

Parsing MIME Reliably

Raw SMTP delivers RFC 5322 messages with nested MIME parts (multipart/alternative, multipart/mixed, inline attachments). Use a mature parser — mailparser (3.6M weekly npm downloads), Python's standard email module, or Go's github.com/mhale/smtpd with mime/multipart. Extract: Message-ID for deduplication, From/To/Subject/Date headers, text/plain and text/html bodies, and attachment metadata (filename, MIME type, size). Store attachments separately in object storage (S3, MinIO) with signed URLs; keep only references in Redis.

Redis Data Model with TTL Expiration

Key pattern: inbox:{address_hash}:{message_id} → JSON string. Address hash uses first 8 chars of SHA-256 to avoid key enumeration. TTL set to 600 seconds (10 minutes) for standard addresses, 3600 for "extended" tiers. A secondary index inbox:index:{address_hash} (Redis Set) holds message IDs for listing. Lua script for atomic fetch-and-delete on read-once semantics. Example Redis JSON: {"id":"msg_abc","from":"user@gmail.com","subject":"Verify","text":"Code: 1234","html":"...","attachments":[],"received":"2024-01-15T10:30:00Z"}.

Handling Scale: Connection Pooling and Backpressure

Postfix master.cf limits concurrent delivery processes via maxproc. The webhook receiver should use a connection pool (Node: undici with Pool, Go: redis.UniversalClient) and return 2xx within 2 seconds — Postfix will retry on 4xx/5xx. Implement token-bucket rate limiting per sender IP at the MTA level (policyd-spf, postfwd) and per recipient address in the processor. Queue overflow? Return 421 (temporary failure) so sending MTAs retry exponentially.

API Design: Inbox Retrieval and Address Management

REST Endpoints for Frontend Integration

Design three core endpoints: GET /api/v1/inbox/:address returns array of messages (newest first), GET /api/v1/inbox/:address/:messageId returns single message with full MIME, POST /api/v1/addresses generates a new random address (or accepts custom local-part) and returns {address:"x7k9@tempmail.example",expiresAt:"2024-01-15T10:40:00Z"}. Add DELETE /api/v1/inbox/:address/:messageId for manual purge. Rate limit: 60 req/min per IP, 300 req/min per address.

WebSocket for Real-Time Updates

Polling wastes resources. Upgrade to WebSocket on GET /api/v1/inbox/:address/stream. Server holds connection, subscribes to Redis keyspace notifications (CONFIG SET notify-keyspace-events KEx) for inbox:{hash}:* keys. On new message, push JSON to client. Handle reconnection with Last-Message-ID header to fetch missed messages. Example: 10K concurrent connections on a single Node.js process with ws library uses ~200MB RAM.

Address Generation Strategies

Random: 8-char alphanumeric (a7f3k2m9@domain) — 2.8T combinations, collision probability negligible. Custom: allow user-specified local-part with validation (RFC 5322 atext, max 64 chars). Domain rotation: own 5-10 domains, rotate daily to evade blocklists. Store domain→IP mapping in Redis for health checks. Example: domains: ["tmp1.example","tmp2.example","tmp3.example"] with round-robin assignment.

Deliverability, Reputation, and Abuse Prevention

DNS Configuration: MX, SPF, DKIM, DMARC

MX record points to your SMTP host (priority 10). SPF: v=spf1 ip4:203.0.113.0/24 -all (only your outbound IPs). DKIM: generate 2048-bit RSA key, publish selector default._domainkey with v=DKIM1; k=rsa; p=MIIBIjAN.... Sign outbound (bounce/notifications) with OpenDKIM or dkimpy. DMARC: v=DMARC1; p=quarantine; rua=mailto:dmarc@tempmail.example. Test with dig MX tmp.example and dkimverify.

Inbound Spam Filtering Without False Positives

Temporary email users expect *all* mail — including promotional and transactional. Aggressive filtering breaks the use case. Instead: reject at SMTP RCPT TO if sender IP in Spamhaus ZEN DNSBL (zen.spamhaus.org), but accept from major providers (Google, Microsoft, Amazon SES IP ranges). Add greylisting (450 4.7.1) for unknown IPs — legitimate MTAs retry, spammers rarely do. Postfix postgrey handles this in 20 lines of config.

Abuse Mitigation: Rate Limits, Captcha, and Monitoring

Limit address creation: 5 addresses/hour/IP, 50/day. Require hCaptcha/turnstile on POST /addresses after 3 requests. Monitor: Prometheus metrics for smtp_connections_active, messages_received_total, messages_expired_total, api_latency_seconds. Alert on >1000 messages/minute to single address (likely test harness) or >50% SMTP 5xx rate. Log all From domains for threat intel sharing.

Comparison: Temporary Email Backend Approaches

Choosing the right stack depends on team expertise, scale targets, and operational tolerance. The table below compares four production-tested approaches using real-world metrics from deployed services.

Postfix offers the highest throughput with mature ops tooling; Haraka accelerates development for Node teams; custom Go/Python suits unique protocol needs; managed services eliminate infrastructure but limit control.

ApproachMax Throughput (msg/s)Operational Complexity
Postfix + Policy Service100,000+Medium (mature tooling, logs, queues)
Haraka (Node.js plugins)30,000Low (JS logic, hot reload, npm ecosystem)
Custom Go (smtpd + Redis)50,000High (RFC edge cases, TLS, backpressure)
Managed (EmailLabs, Mailgun inbound)10,000 (plan-limited)Zero (webhook only, no SMTP control)

Common Mistakes and Pro Tips

Mistake: Storing Full MIME in Redis

Why It Hurts: A single email with 10MB attachment blows Redis memory; 1000 such messages = 10GB RAM. Redis is not an object store.

Fix: Parse MIME, store metadata + body text in Redis, stream attachments to S3/MinIO, save only signed URL and SHA-256 hash in the message document.

Mistake: No Idempotency on Message Ingestion

Why It Hurts: Sender MTAs retry on transient failures. Without deduplication, users see duplicate messages.

Fix: Use Message-ID header + recipient address as composite key. On ingest, SETNX inbox:dedup:{msgid}:{addr} 1 EX 86400 — skip processing if key exists.

Mistake: Exposing Sequential Address IDs

Why It Hurts: /inbox/1, /inbox/2 lets attackers enumerate all active inboxes and read messages.

Fix: Use unguessable address hashes (SHA-256 truncated to 16 chars) in all URLs. Never expose internal Redis keys.

Mistake: Ignoring SMTP TLS and Certificate Rotation

Why It Hurts: Major providers (Gmail, Outlook) reject mail from MX hosts without valid TLS. Expired cert = silent delivery failure.

Fix: Use Let's Encrypt with certbot --nginx or acme.sh for Postfix. Automate renewal with postfix reload hook. Test with openssl s_client -connect mx.tempmail.example:25 -starttls smtp.

Pro Tips

  • Run two Postfix instances: primary on port 25 (inbound), secondary on port 587 (outbound notifications) with separate queues — isolates reputation.
  • Pre-warm address pool: generate 10K random addresses at startup, keep in Redis Set addresses:availableSPOP on demand eliminates collision checks.
  • Add List-Unsubscribe header to outbound notifications — reduces spam complaints from users who forgot they signed up.
  • Log structured JSON (not text) with request_id correlation across MTA → processor → API — enables distributed tracing with Loki/Elastic.
  • Implement "burner" mode: addresses that self-destruct after first message read — use Redis key expiration on GET via Lua script.

FAQ

What is a temporary email service backend?

A temporary email service backend is a server-side system that accepts inbound SMTP mail for disposable addresses, stores messages in ephemeral storage with automatic expiration (typically 10-60 minutes), and exposes APIs for frontend retrieval. Unlike traditional mail servers, it discards all data after TTL expiry and requires no user authentication.

How does a temporary email backend differ from a standard mail server?

Standard mail servers (Postfix, Exchange, Dovecot) persist mailboxes indefinitely, support IMAP/POP3, and require user accounts. Temporary email backends accept mail for any address at the domain, store only in fast TTL-based stores (Redis), expose HTTP/WS APIs instead of IMAP, and automatically purge all data within minutes.

Can I build a temporary email backend without managing an SMTP server?

Yes. Use managed inbound email services like Mailgun Routes, SendGrid Inbound Parse, or EmailLabs. They receive SMTP on your behalf, parse MIME, and POST JSON to your webhook. Trade-off: you lose control over SMTP-level filtering, greylisting, and custom RCPT TO logic, and costs scale with volume ($0.50-1.00 per 1000 emails).

Why are my temporary emails not arriving from Gmail or Outlook?

Common causes: missing or invalid SPF/DKIM/DMARC on your domain, MX record pointing to wrong host, sender IP reputation blocks (check Spamhaus ZEN), or Postfix rejecting with 450/550 due to rate limits. Test with swaks --to test@yourdomain --server mx.yourdomain --tls and check /var/log/mail.log for SMTP session details.

What are the emerging trends in temporary email infrastructure?

Edge deployment (Cloudflare Workers, Fly.io) moves SMTP termination closer to senders for lower latency. WebAssembly MIME parsers run in-browser for client-side rendering. Zero-knowledge architectures encrypt message bodies with keys derived from address + user password — backend never sees plaintext. AI-powered spam scoring replaces static DNSBL lists.

Conclusion

Building a temporary email service backend is fundamentally an exercise in ephemeral data plumbing: accept SMTP at scale, parse MIME fast, store with automatic expiry, and expose a clean API — all while maintaining deliverability reputation and preventing abuse. The stack choices (Postfix vs. Haraka, Redis vs. custom, self-hosted vs. managed) matter less than getting the data flow right: idempotent ingestion, attachment offloading, unguessable addresses, and observability at every hop. Start with Postfix + webhook + Redis, ship the MVP in a weekend, then iterate on rate limiting, domain rotation, and real-time APIs as usage grows.

  • SMTP ingestion + MIME parsing + Redis TTL = core loop; everything else is ops and hardening
  • Idempotency via Message-ID deduplication prevents duplicate messages on MTA retries
  • SPF/DKIM/DMARC + greylisting + DNSBL = deliverability without aggressive filtering
  • Observability (metrics, structured logs, distributed tracing) catches issues before users do

Sources

Share:

0 comments:

Post a Comment