This site is not affiliated with or endorsed by Cloudflare, Inc. It simply showcases experiments built using Cloudflare services.
Cloudflare Experiments

Email Worker Inbox

Receive inbound emails with Email Workers, store them in KV, and inspect over HTTP

Process inbound mail with the Cloudflare Email Workers email handler, parse MIME with postal-mime, store message summaries in Workers KV, and inspect them over HTTP.

Features

  • Inbound email handler with reject/store policy
  • Parses subject/body with postal-mime
  • GET /inbox and GET /inbox/:id for inspection
  • Stores up to 50 recent messages with a 7-day KV TTL
  • Local simulation via Wrangler’s /cdn-cgi/handler/email endpoint

API Reference

Email handler

Configured in the Cloudflare dashboard under Email Routing → route an address to this Worker.

The demo policy rejects:

  • senders from spam.example or @spam.
  • subjects containing [spam] or starting with spam:

Rejected messages are still stored in KV with rejected: true so you can inspect them.

GET /inbox

Lists recent stored messages (newest first, max 50).

Example Request

curl "https://your-worker.workers.dev/inbox"

Success Response

count number

Number of stored messages returned

messages array

Message summaries with id, from, to, subject, receivedAt, optional text / html, and rejection fields

{
  "count": 1,
  "messages": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "from": "sender@example.com",
      "to": "inbox@example.com",
      "subject": "Hello from Email Workers",
      "receivedAt": "2026-07-23T12:00:00.000Z",
      "text": "Hello from local email simulation.",
      "messageId": "<test@example.com>",
      "rejected": false
    }
  ]
}

GET /inbox/:id

Returns one stored message by id.

Example Request

curl "https://your-worker.workers.dev/inbox/550e8400-e29b-41d4-a716-446655440000"

Success Response

Same shape as a single object in messages[] above.

Error Response

{
  "error": "Message not found",
  "code": "NOT_FOUND"
}

Error Codes

  • 404 - Message id not found (NOT_FOUND)
  • 400 - Missing message id (MISSING_ID)

Use Cases

  • Build support@ / hello@ edge inboxes
  • Prototype spam filters before forwarding
  • Capture inbound mail for webhook-style automation
  • Teach Email Workers + KV patterns end to end

Limitations

  • Requires Email Routing enabled on a Cloudflare zone
  • Stores truncated text/html previews (about 4KB each)
  • Messages expire after 7 days (KV TTL)
  • Does not forward or reply unless you extend the handler

Deployment

Create KV namespace

Create a KV namespace and set its id in wrangler.json for the INBOX binding.

Route email and test

In Email Routing, send an address to this Worker, then inspect with:

curl "https://your-worker.workers.dev/inbox"

Local Development

cd apps/experiments/email-worker-inbox
npm install
npm run dev

Simulate an inbound email:

curl -X POST 'http://localhost:8787/cdn-cgi/handler/email?from=sender@example.com&to=inbox@example.com' \
  --data-binary @- <<'EOF'
From: sender@example.com
To: inbox@example.com
Subject: Testing Email Workers
Message-ID: <test@example.com>
Content-Type: text/plain

Hello from local email simulation.
EOF

Then inspect:

curl "http://localhost:8787/inbox"

Local email simulation uses Wrangler’s /cdn-cgi/handler/email helper. Production delivery requires Email Routing configured on your zone.

Configuration

Binding / dependencyPurpose
INBOX (KV)Stores message index + bodies
postal-mimeParses inbound MIME messages

Cloudflare Features Used

Next Steps

On this page