Skip to content
Metis Suite
Esc
↑↓navigate↵open⌘Jpreview
On this page

Set up the Cloudflare Email gateway

Deploy a Cloudflare Worker that receives, stores and sends mail for one of your domains.

The Cloudflare Email gateway is a Cloudflare Worker. It receives mail through Email Routing, stores messages in D1 with raw mail and attachments in R2, and sends through Cloudflare Email Sending. You deploy one Worker per domain.

Before you start

  • The domain is a zone on your Cloudflare account. Email Routing needs Cloudflare DNS.
  • Your Cloudflare account is on the Workers Paid plan, which Email Sending needs to send to any recipient.
  • You have a Cloudflare API token with Zone, Email Routing: Edit and Zone, DNS: Edit, and you can deploy Workers with wrangler.
  • You have Bun and a copy of the Metis Suite source code:
git clone https://github.com/trymetis/metis.git
cd metis
bun install
cd apps/gateway-cloudflare

Deploy the Worker

Create the database

bun run db:create

It prints a D1 database id. Paste it into wrangler.jsonc as database_id, and set MAIL_DOMAIN there to your domain.

Create the storage bucket

bun run r2:create

Create the tables

bun run db:apply

Set the admin token

Generate a long random value, for example with openssl rand -hex 32, then store it as the Worker’s admin token:

bun run secret

Keep this value: you need it to create mailbox tokens.

Deploy

bun run deploy

It prints the Worker’s workers.dev address. You need it below.

Connect your domain

Run the setup with your API token, your zone id and the addresses you want to receive mail for:

CLOUDFLARE_API_TOKEN=... CLOUDFLARE_ZONE_ID=... \
  MAIL_ADDRESSES=alice@example.com,bob@example.com \
  bun run setup

The setup turns on Email Routing for the zone, creates a routing rule for each address, sets the domain up for Email Sending, and adds the DNS records sending needs (SPF, DKIM, DMARC and a bounce record). It is safe to run again: run it with more addresses whenever you add one. Set WORKER_NAME if you named the Worker differently.

Without MAIL_ADDRESSES, the setup sends every address on the domain to the Worker instead (a catch-all). Aliases then work with no setup, but the domain accepts more spam. Mail for an address with no token is kept, and it appears once you create a token for that address.

Register it in Metis Suite

Open Dashboard, System, Cloudflare Email under Providers. Click Add server and fill in:

  • Name: what users see in the connect dialog.
  • Domain: your domain, such as example.com, without https://.
  • Worker endpoint: the Worker’s https:// address.

Click Save changes and enter your authenticator code.

You can also set the starting list before the first start:

METIS_CLOUDFLARE_SERVERS=[{"name":"Example Mail","domain":"example.com","endpoint":"https://metis-cf-mail.you.workers.dev"}]

Create mailbox tokens

Create a token for each address and give it to its owner. See Mailbox tokens.

Cloudflare limits

  • A D1 row holds at most 2 MB, so message bodies are cut at 1 MB. Raw mail and attachments are kept in R2 in full.
  • Email Sending includes 3,000 emails a month on Workers Paid, then is billed per 1,000. A message can have at most 50 recipients. Email Sending is in beta.
  • Email Routing allows at most 200 routing rules per zone. Beyond that, use catch-all mode.

Was this page helpful?