Email on the edge. Sure.

A full-stack email framework for the edge. Inbound, outbound, threading, blob storage, classification, and a native IMAP server — all without a third-party inbox.

No edge SMTP. That would be a nightmare. But edge IMAP on Durable Objects? Absolutely. Bring your own auth, your own storage, your own routing. We ship the protocol layer and the data model.

# one package, drop into any Workers project
$ npm i @rafters/mail
# wire it up
$ npx @rafters/mail init --adapter=d1
# receive your first email
$ wrangler email route <your-worker> *@example.com
bundle 27 kb gzcold start < 12 ms
license MIT
runtime Workers · Node · Bun · Deno
deps 0 required
status alpha
01 / architecture

Edge topology.

Your Worker is the mail exchange. Durable Objects pin IMAP sessions. Adapters connect the core to whatever backends you're already running.

rafters-mail · runtime topology
the internet the edge · your worker byo backends Senders SMTP · inbound Recipients SMTP · outbound IMAP clients Apple · Thunderbird Email Routing cloudflare mx · spf · dkim @rafters/mail your cloudflare worker CORE inbound · outbound · threading parse · classify · webhooks AuthAdapter · InboundAdapter EmailProvider resend · postmark · ses outbound send IMAP DO durable object session state idle · uid · flags rfc 9051 D1 · inbox schema R2 · BlobStorage Workers AI · DeBERTa-v3 smtp in routed send() smtp out imap · tls fetch · uids patch · flags
runs on the edge bring your own external / wire protocol
02 / modules

What's in the box.

One package. Eight composable surfaces. All documented, all adapters, no magic globals.

core / inbound

Inbound

Parse MIME, run through your InboundAdapter, hand off to a handler. Attachments stream to blob storage. Returns a threaded message row.
load 3/10 rfc 5322
core / outbound

Outbound

Compose, reply, forward. Threading headers handled. EmailProvider interface swaps Resend, Postmark, or SES without touching caller code.
providers 3 webhooks yes
core / threading

Threading

Conversation grouping that actually matches what Apple Mail and Gmail do. References, In-Reply-To, Message-ID. No heuristic fuzz.
rfc 5322 §3.6.4
core / storage

Blob storage

Attachments and raw MIME land in BlobStorage. R2 implementation ships; the interface is eight methods. Swap for S3 or whatever.
methods 8 backend R2 · S3
core / classify

Classification

Route incoming mail through Workers AI (DeBERTa-v3). Tag, filter, fan out. Or disable it entirely and write your own rules — the hook is one function.
model deberta-v3 opt-in
core / newsletters

Newsletters

Mailing lists and broadcasts on top of the same schema. Mirrors into platform tables so you can query subscribers with the rest of your app.
mirror yes
imap / server

Native IMAP — on Durable Objects.

The reason this project exists. A full IMAP server that pins session state to a Durable Object per user. Handles LOGIN, SELECT, FETCH, UID, IDLE, APPEND, SEARCH, flags, and the 23 other commands your client actually sends. Apple Mail and Thunderbird connect on TLS:993 without knowing the backend is a Worker.
rfc 9051 commands 31 auth APP-PASS · OAUTH2 tls 1.3
imap / deploy

Where it runs.

Fly, Railway, Fargate, any Docker host, or a bare VPS. The Worker is the source of truth; the IMAP process is a thin port-993 translator.
fly railway docker vps
03 / why edge

Latency, cost, sovereignty.

Email is mostly request/response with bursty fan-out. That is exactly what the edge is good at. Vendor lock-in on your inbox is not fine.

p50 inbound latency
12ms

From SMTP-DATA accepted to row-written. Worker cold starts included. Your users' clients don't round-trip through Virginia.

cost per million msgs
$4.80/mo

Workers + D1 + R2 at published list price. No per-seat surcharge, no inbox retention tier, no "enterprise" line item.

where the data lives
yours

Your D1, your R2, your logs. No vendor reads your customers' email. IMAP auth terminates at your AuthAdapter.

04 / honestly

vs. self-hosted.

Postfix and Dovecot work. They have worked for twenty-five years. But if you haven't babysat a mail server through a PTR-record outage, you will.

Concern Postfix + Dovecot on a VPS @rafters/mail
Inbound MX Run smtpd. Tune greylisting. Apply CVEs. Cloudflare Email Routing handles MX, SPF, DKIM, and spam.
Outbound SMTP Your IP gets on a blocklist by Tuesday. Hand off to Resend / Postmark / SES. Deliverability is their problem.
IMAP server Dovecot on a long-lived VM. State in maildir. Durable Object per user. State is a database row.
Storage Disk fills up. Someone has to rotate it. R2 for blobs, D1 for metadata. Infinite, indexed.
Scaling Resize the VM. Pray the fsync survives. Per-user isolate. Scales to zero when no one's checking mail.
Threading, classification, webhooks You wire up Sieve, SpamAssassin, and a cron job. Built in. One InboundAdapter hook.
Your 2AM pager "disk 97% full on mail-01" Silent.

To be clear: we don't do edge SMTP. That would be a nightmare. Outbound goes through a real transactional provider. What we do is everything after the TCP handshake.

05 / faq

Objections.

The ones that come up in every DM.

Wait, IMAP on a Durable Object? Really?
Really. IMAP is stateful — a client holds a long connection, selects a mailbox, waits for IDLE pushes. A Durable Object is a single-threaded JS instance with addressable state and a WebSocket-ish lifetime. That's the same shape. The DO pins to a user, the Worker handles the auth, and a thin port-993 process (Fly, Railway, Fargate, Docker, VPS) just translates TLS frames into fetch() calls.
So you don't do outbound SMTP?
Correct. Speaking SMTP to Gmail from a Worker IP is a deliverability disaster waiting to happen. Outbound flows through the EmailProvider interface — Resend, Postmark, and SES ship. You can write your own in about forty lines.
What about spam, DKIM, and bounce handling?
Cloudflare Email Routing does MX, SPF, DKIM, and basic spam on the inbound side before your Worker sees a byte. Bounces come back through provider webhooks and land in inbound like any other message, with a type: "bounce" tag.
Do I need Cloudflare?
For the recommended inbound path, yes — Email Routing is the cheapest, best-tuned MX you can get. Everything else is portable. The core runs on Node, Bun, and Deno; the IMAP process runs anywhere Docker runs. D1 is an adapter; swap for Postgres or SQLite and the tests still pass.
Why would an AI agent need an inbox?
Because half of the real world still runs on email threads. Receipts, appointment confirmations, customer replies, calendar invites, magic-link logins. An agent with a first-class inbox — one it owns, not a brittle OAuth scope into someone else's Gmail — can actually participate. That's the whole thesis.
License?
MIT. Use it, fork it, re-skin it, ship it inside your closed-source product. We'd love a star and a bug report.

Open source. MIT.

The whole thing lives at rafters-studio/mail. Issues welcome. RFC nitpicks especially welcome.