A walkthrough of Cloudflare Email Service, a beta feature letting Workers send transactional email without a third-party provider or API key via an env.EMAIL.send() binding. Covers onboarding a sending domain (DNS/SPF/DKIM/DMARC records), configuring the send_email binding in wrangler.jsonc, restricting allowed destination addresses, sending a welcome email example, simulating sends locally with wrangler dev versus real sends with remote: true, handling errors like E_SENDER_NOT_VERIFIED and E_RATE_LIMIT_EXCEEDED, and key limits (50 recipients, 5 MiB message size, daily quota that grows over time, with verified destination addresses exempt from quota).
Table of contents
Email Sending and Email Routing are differentSet up the sending domainAdd the email bindingSend an emailTest without sending a real emailHandle sending errorsUseful limits to knowQuestions this post answers
How do I send an email from a Cloudflare Worker without using a third-party email API?
Add a send_email binding named EMAIL to wrangler.jsonc, then call env.EMAIL.send() with to, from, subject, html, and text fields inside the Worker. No API key is needed since Cloudflare's Email Service handles delivery natively, and the call returns a messageId for tracking in Cloudflare's logs. daily.dev surfaces practical Workers guides like this one for developers wiring up backend email flows.
What does the E_SENDER_NOT_VERIFIED error mean in Cloudflare Email Service?
It means the sending domain has not finished onboarding in Email Service, so Cloudflare will not deliver mail from it yet. Other errors include E_RATE_LIMIT_EXCEEDED, which signals the account's daily sending quota was hit and the request should be retried later. Both are returned as an error.code property when the send call is wrapped in try...catch. Developers debugging Worker email failures can track these error codes and fixes on daily.dev.
How can I test Cloudflare Worker email sending without actually sending real emails?
By default, running wrangler dev simulates the send_email binding: it logs the email and writes its content to local files instead of delivering it. To send a real email during local development instead, add remote: true to the binding configuration in wrangler.jsonc, which routes env.EMAIL.send() calls to the live Cloudflare Email Service. daily.dev helps developers stay current on Workers tooling like local email simulation in wrangler dev.