Two exports, one Worker
Every Cloudflare Worker tutorial starts with fetch. But
Workers have another entry point that most people never see:
email. Same Worker, same deploy, same bindings. It just
handles a different protocol.
InboxKit is an
email service for agents. It already had fetch for the API:
signup, send, poll, read. But inbound email was missing. When someone
sent a message to handle@juanibiapina.dev, nothing happened.
The email() export
Adding inbound email to an existing Worker takes one new export:
export default {
async fetch(req, env, ctx) { /* HTTP API */ },
async email(message, env) {
try {
await handleInboundEmail(message, env);
} catch {
message.setReject("Mailbox not found");
}
},
};
Cloudflare Email Routing sends the raw MIME message to this handler.
The message object has from, to,
rawSize, and a raw ReadableStream of the full
email. Call setReject() and the sender gets an SMTP bounce.
The handler
The handler is five steps, each one can fail independently:
// 1. Size gate
if (message.rawSize > 1_048_576) throw "too large";
// 2. Extract handle, validate domain
const handle = extractHandle(message.to);
// 3. KV lookup: handle → Durable Object ID
const doId = await env.HANDLES.get(handle);
// 4. Parse raw MIME
const parsed = await new PostalMime().parse(rawBuffer);
// 5. Deliver to inbox
await stub.deliver(from, to, subject, text, html);
Any throw causes the catch in the export to reject the
email. Wrong domain, unknown handle, oversized message, malformed MIME:
all produce a bounce. The happy path is a straight line from raw bytes to
a stored message.
No mail server
The entire setup is: enable Email Routing in the Cloudflare dashboard, set a catch-all rule pointing at your Worker, deploy. Cloudflare handles MX records, TLS, spam filtering, and SMTP. The Worker just gets a parsed envelope and a stream of bytes.
Combined with fetch for the HTTP API and Resend for
outbound, one Worker now handles all three directions of an email
service: send, receive, and read.
PR #7: Inbound email via Email Routing
github.com/juanibiapina/inboxkit