Simple Inbox

Simple Inbox

A private, self-hosted inbox on one Cloudflare Worker.

Simple Inbox is a clean-room mail workspace that runs as one Cloudflare Worker named simple-inbox-cf. One deployment serves the web app and API, receives Email Routing events, and keeps mail indefinitely.

browser ---- fetch() ----> simple-inbox-cf ----> D1
Email Routing -- email() ------|                 private R2
Cloudflare Cron -- scheduled() ----------------> Email Sending

D1 holds queryable mailbox state. A private R2 bucket holds canonical raw .eml objects. The browser uses authenticated APIs, including streamed attachment uploads through the Worker’s R2 binding.

What is included

  • Passwordless owner sign-in with one-time magic links.
  • Thread, search, archive, read/unread, starred, spam, trash, compose, and reply flows.
  • Multi-select in the conversation list to move many conversations to Trash or Spam, or back out of them, at once, with Undo.
  • Canonical raw-message and attachment download after mailbox authorization.
  • Inbound capture, owner forwarding, opaque reply aliases, and outbound Email Sending.
  • Durable send idempotency and explicit unknown delivery state.
  • Indefinite storage with no automatic expiration.
  • Direct R2 attachment uploads with permanent download links in outgoing mail.
  • A first-run /setup wizard for owner, mailbox, origin, mail domain, and retention settings.
  • Embedded OpenAPI and operator/security documentation.

First deployment

The root Wrangler config declares one Worker plus D1, R2, Email Sending, rate limiting, and private attachment storage. Wrangler provisions D1/R2, and the root deploy task builds, migrates, and deploys:

vp run deploy

This is a remote, state-changing command. Before using it, follow the local verification and account checks in Deployment. Cloudflare also requires Email Routing to be enabled and one owner-controlled destination verified before it can attach the Worker's email binding.

Create two independent secret values of at least 32 random bytes:

  • AUTH_TOKEN_PEPPER protects authentication-token digests;
  • SETUP_TOKEN authorizes the first-run wizard.

After deployment, open the chosen HTTPS origin at /setup. For a synthetic local test, use values such as owner@example.test, mail.example.test, and inbox@mail.example.test. Setup writes all installation records atomically; until it succeeds, protected APIs fail closed, inbound mail is rejected, and retention stays idle.

Email Sending domain verification, bucket lifecycle changes, and Email Routing activation remain explicit Cloudflare Dashboard owner steps.

One-click deployment

Launch Cloudflare's deployment flow from the public source repository:

Deploy Simple Inbox to Cloudflare

Deploy to Cloudflare requires the source repository to remain public.

Routes

  • /setup — required only before the first installation completes.
  • /sign-in and /auth/verify — passwordless authentication.
  • /inbox — authenticated mail workspace.
  • /docs — this public guide.
  • /api/v1/health, /api/v1/capabilities, /api/v1/openapi.json — public service metadata.
  • Other /api/v1/* inbox routes — authenticated and mailbox scoped.

The mail package's /internal/* Hono routes are in-process infrastructure and are never exposed by the public Worker router.

Continue reading

  • Deployment — deploy, complete setup, configure Cloudflare, test, and recover.
  • Architecture — the single-Worker runtime and logical module boundaries.
  • Security — secrets, authorization, privacy, retention, and incident safeguards.
  • API — versioned contracts and error behavior.

On this page