Send email from a Cloudflare-hosted static site

Cloudflare Email Routing forwards inbound mail to another address. It does not send. If you want messages to leave hello@yourdomain on their way to somebody else, you need an outbound mail server somewhere, and a Cloudflare-hosted static site (Pages or Workers) has none behind it. The three answers below differ in where that outbound mail server lives.

Cloudflare’s own Email Sending product is on the roadmap but still gated on GA; none of the paths below depend on it.

Which path fits depends on what else you need from the setup. The ranking below is for an operator with this setup: a Publii-generated static site, Cloudflare as registrar and DNS, inbound already forwarded to a personal Gmail via Email Routing, one or two addresses to send from.

A mailbox host that replaces Cloudflare Email Routing

For most people whose site looks like this, the simplest answer is a hosted mailbox provider that handles inbound and outbound both. One account replaces Cloudflare Email Routing entirely: the host sits on your MX, holds the mailbox, and gives you SMTP credentials for sending. The Workers and Pages side of the site does not change.

Four providers at the small-site end of this market:

  • Purelymail, around $10 a year for unlimited domains and aliases with standard IMAP and SMTP. Low-cost catch-all mailbox hosting with no frills; the control panel is spartan but the mail works. (purelymail.com)
  • Migadu, pay-what-you-send Micro tier from $19 a year. Standard SMTP, generous alias limits, European host. Good if you want proper per-domain quotas.
  • Zoho Mail, Forever Free plan still listed for one domain and up to five users, web-only access, custom-domain support. Zoho’s free terms have shifted before, so check the current plan page before signing up.
  • Fastmail, €3 a month Basic (billed annually; monthly billing runs €4). More polished webmail and mobile apps than the others, and the easiest handoff if the person reading the email is non-technical.

The mechanics are the same across all four. Change the MX records at Cloudflare DNS to the host’s values, verify the domain, then authenticate SMTP from your mail client (or an application) with the per-mailbox username and password the host provides. Deleting the Cloudflare Email Routing rules is the last step; leaving them in place while MX propagates is harmless but eventually redundant.

For a one-domain site with two or three aliases, every option above lands under $50 a year.

A transactional relay behind a form endpoint

If what you actually need is a contact form that emails you, and the mailbox you read it in is still a personal Gmail reached via Cloudflare Email Routing, a transactional sender wins on simplicity. The form posts to an endpoint; the endpoint hits a sending API; the message arrives at your inbox already signed and authenticated.

The sender choice tracks volume and whether you also want a mailbox:

  • Postmark, $15 a month for 10,000 messages, with the cleanest API and the fastest support in the category. Overbuilt for a contact form, but the free developer tier is 100 messages a month indefinitely.
  • Resend, free up to 3,000 messages a month, developer-first API. Native fit if the endpoint is a Cloudflare Worker; the SDK call is one HTTPS POST.
  • Mailgun, Basic plan from $15 a month. Right choice at higher volume.

The endpoint itself is a Cloudflare Worker on the same zone (a few lines of code taking the form’s JSON and forwarding it to the sender’s API) or a hosted form service like Formspree or Basin that bakes both the endpoint and the sending in. Workers wins on cost at any volume above the hosted-form free tiers; the hosted service wins if you do not want to write code.

The caveat: this path sends from your domain but does not give you a mailbox. Replies land in whatever Reply-To you set, usually your Gmail. If you also want to send manually from hello@yourdomain, you still need a mailbox host as well.

A Cloudflare Worker calling a sending API

The all-Cloudflare path removes the second vendor. The Publii contact form posts JSON to a Worker at /api/contact on the same Cloudflare domain; the Worker calls the sender’s API; done. For a Worker running on Cloudflare’s fetch runtime, Resend’s API is the natural integration (one HTTPS POST, API key in environment).

Two Cloudflare-native options are worth knowing about, both with sharper edges than they look:

  • MailChannels’ Email Sending API for Cloudflare Workers was terminated on 30 June 2024. Any guide still recommending api.mailchannels.net for sending from a Worker is out of date; MailChannels no longer accepts requests from the Workers integration at all. (MailChannels announcement)
  • Cloudflare Workers’ send_email binding is part of Email Routing. Sending to addresses already verified as Email Routing destinations on your account is free on all plans; sending to other recipients counts against Email Sending’s Beta limits (Workers Paid plan). Useful today for a form that mails your own Gmail (the destination you already verified for inbound forwarding) without a third-party API; use it as a general outbound sender only once Email Sending leaves Beta. (Cloudflare’s documentation)

If the goal is a contact form that reaches your own inbox, the send_email binding solves it without a third-party API at all, at zero cost. For general outbound to customers or newsletter subscribers, the binding works today under the Email Sending Beta’s Workers Paid-plan limits; most operators at that scale still pick a dedicated transactional sender via the Worker and keep send_email for the free verified-destination case.

Domain authentication across all three paths

Every path above requires SPF (Sender Policy Framework) is a DNS TXT record that lists the servers allowed to send mail using your domain. Receivers compare the sending IP to that list and use the result as one input to their accept/reject decision. Read full reference → and DKIM (DomainKeys Identified Mail) is a cryptographic signature attached to each outgoing message, verifiable against a public key published in DNS. It lets receivers confirm the message was not altered in transit and originated from a server the domain authorised to sign on its behalf. Read full reference → on the sending domain, or Gmail drops the message silently. The mailbox host, the transactional sender, and the Workers send_email binding all publish their own records; copy them into Cloudflare DNS as TXT entries and verify in the sender’s dashboard before the first send. DMARC (Domain-based Message Authentication, Reporting, and Conformance) is a DNS TXT record that tells receivers what to do with mail from your domain that fails SPF or DKIM, and where to send reports about those failures. Read full reference → is optional for a low-volume setup but worth adding once SPF and DKIM align, because Gmail’s current sender rules weight it.

Deliverability is nobody’s default. A new sender on a new domain starts with no reputation; the first few messages from hello@yourdomain are evaluated on the authentication records alone. Get those right and the deliverability question answers itself. Get them wrong and no amount of provider-switching recovers it.