Self-hosted email on Cloudflare

Your domain. Your inbox. Your Cloudflare account.

Mailcove is a send-and-receive custom-domain inbox that runs on Cloudflare Workers. Mail lands in your R2 and D1, sends from your domain, and stays behind Cloudflare Access.

WorkersD1R2Email RoutingEmail SendingAccessWorkers AIMIT
https://inbox.shinypage.com
Mailcove app showing a three-pane inbox with folders, threaded messages, and an open conversation
Custom-domain inbox, threaded conversations, full-text search, and an Access-protected UI.
Why Mailcove

Custom-domain email on Cloudflare primitives.

Serverless by default

Inbound mail wakes a Worker, gets parsed, stored, indexed, and stops. Cloudflare handles the edge work.

You own the data

Raw mail and attachments live in your R2. Metadata, threads, and search live in your D1. It is your Cloudflare account.

Private by default

The inbox UI sits behind Cloudflare Access, and the Worker verifies the Access JWT on API requests.

Product walkthrough

A real inbox for domains you control.

Read, search, reply, switch between rich email and chat-style threads, and manage routing from one private UI. Mailcove keeps the familiar parts of email while moving the storage and control plane into your Cloudflare account.

inbox.shinypage.com/search
Mailcove search results filtered to a pizza thread
Search

Find anything. Catch up in three bullets.

Full-text search runs across every message in your own D1. Open a thread and Workers AI summarizes the conversation inline: what was decided, what is pending, and what needs a reply.

  • FTS5 search over subject, participants, and body text.
  • AI summaries and drafts use Cloudflare Workers AI.
  • Your search index lives in D1.
inbox.shinypage.com/thread
Mailcove chat view showing a cleaned-up conversation thread
Rich + chat

Read the original email, then switch to the clean thread.

Rich view keeps formatted email in a sandboxed frame. Chat view turns the same thread into plain conversation bubbles, stripping the email cruft when you just want to catch up and reply.

  • Toggle between Rich and Chat per thread.
  • Thread-aware replies.
  • Multiple send identities.
inbox.shinypage.com/domains
Mailcove domain management dialog showing Email Routing and sending setup
Domains

Email Routing from the same UI.

Manage receiving, sending, catch-all behavior, forwarding destinations, and per-address rules for the domains in your Cloudflare account. Changes apply to live Email Routing, so the UI treats them as real infrastructure operations.

  • Catch-all to inbox, forward, or drop.
  • Per-address routing rules.
  • Sending domains and sender display names.
⌘K
Mailcove command palette with compose, search, rules, domains, and navigation actions
Keyboard

Built for people who live in the keyboard.

A command palette and shortcut set cover the flow you use all day: compose, search, jump to rules, switch views, archive, star, and reply from the keyboard.

  • ⌘K command palette.
  • Fast view switching.
  • Shortcuts for common mail actions.
Architecture

Three flows, one Worker.

Mail arrives, a Worker wakes up, does the job, and stops. You pay for invocations instead of uptime.

Inbound

  1. *@shinypage.com hits Email Routing.
  2. The Worker email() handler parses with postal-mime.
  3. Raw EML, bodies, and attachments go to R2. Threads and search rows go to D1.

Outbound

  1. The app calls POST /api/send.
  2. The send_email binding sends from your sending domain.
  3. Reply-To points back to your real custom-domain address.

UI

  1. React app ships through Workers Assets.
  2. Cloudflare Access protects the inbox host.
  3. API requests are verified before mail data leaves storage.
What you run

Managed primitives for mail.

D1 for metadata and search

Threads, folders, unread state, identities, rules, and FTS5 search live in SQLite in your account.

R2 for raw mail and attachments

Keep the original message source, parsed bodies, and binary attachments in object storage you control.

Email Routing and Email Sending

Cloudflare handles the mail edge. Mailcove handles parsing, app logic, storage, search, and UI.

Access and Workers AI

Access protects the inbox. Workers AI powers optional summaries and drafts from the thread text you choose to send it.

Deploy

Deploy it to your own account in an afternoon.

Bring a Cloudflare account, a domain, and Wrangler. The setup is infrastructure work, but it is the kind you can finish in an afternoon.

1. ProvisionCreate the D1 database and R2 bucket, then apply migrations.
2. RouteEnable Email Routing catch-all and Email Sending for your domain.
3. ProtectPut the inbox hostname behind Cloudflare Access.
4. DeployBuild the app and ship the Worker.
git clone https://github.com/JacobPritchett/mailcove
cd mailcove
npm install
# create D1 + R2, apply migrations
# enable Email Routing + Email Sending
# protect the inbox host with Cloudflare Access
npm run build && wrangler deploy
Fit

Honest about who it is for.

Good fit

  • You own one or more domains on Cloudflare.
  • You are comfortable running Wrangler and reading deploy logs.
  • You want catch-all addresses and custom-domain mail while avoiding one paid mailbox per address.
  • You want the raw mail and attachments in your own storage.

Skip it if

  • You want a zero-config consumer Gmail replacement.
  • You need hosted support, migration tooling, team admin, or mobile push on day one.
  • You prefer someone else to operate the Cloudflare resources.
  • You need a compliance-certified mailbox vendor.
Security

Private by construction.

Access on every request

The Worker verifies Access JWT issuer and audience before serving private API data.

Sandboxed rendering

Email bodies render in sandboxed iframes, with plain messages adapting to light or dark mode and designed HTML still allowed to bring its own styling.

Your storage only

Raw EML, parsed bodies, and attachments stay in your R2. Metadata and search stay in your D1.

Know what AI sees

Thread text is sent to Workers AI only for summaries and drafts that you request.

FAQ

Practical questions.

Is this a hosted email service?

No. You deploy it to your own Cloudflare account, using your storage, your domain, and your Access policy.

Does it replace Gmail?

For the right person, maybe. It is aimed at developers, small organizations, and tinkerers who care more about custom-domain control than consumer-mailbox polish.

Where does mail live?

Raw messages and attachments live in R2. Message metadata, thread state, rules, and search indexes live in D1.

Should the public site be the same hostname as the inbox?

No. Keep this public website separate from the Access-protected inbox host, for example mailcove.shinypage.com for the site and inbox.shinypage.com for the app.