AWS SES vs Cloudflare Email (2026): Pricing, Encryption, and a Serverless Mailbox
AWS SES vs Cloudflare Email (2026): Pricing, Encryption, and a Serverless Mailbox
SES is cheaper for sending. Cloudflare is better — and free — for receiving. Cloudflare’s $0.35 per 1,000 emails is a rate, not a $0.35 charge for sending one message.
This write-up verifies those claims against current docs (late August 2026), then covers encryption, a SES-send + Cloudflare-receive hybrid, and whether a Cloudflare R2 bucket can act as a mailbox for Thunderbird.
Sources: Cloudflare Email Service pricing, limits, SMTP, MTA-STS, Workers Paid, AWS SES pricing, SES security protocols, SES quotas.
Does one Cloudflare send cost $0.35?
No.
Cloudflare Email Sending on the Workers Paid plan is:
| Layer | What you pay | When |
|---|---|---|
| Fixed | $5 / month Workers Paid | Required to send to arbitrary recipients |
| Included | 3,000 outbound emails / month | Inside that $5 |
| Overage | $0.35 per 1,000 emails = $0.00035 per email | After the 3,000 |
$0.35 per 1,000 is the same kind of unit price as SES’s $0.10 per 1,000. One extra email does not buy a 1,000-email block.
| What you send | Extra Email Sending charge | Total Cloudflare bill |
|---|---|---|
| 1 email / month | $0 (inside the 3,000) | $5 (Workers Paid) |
| 3,000 emails | $0 | $5 |
| 3,001 emails | ~$0.00035, not $0.35 | ~$5.00035 |
| 10,000 emails | (7,000 / 1,000) × $0.35 = $2.45 | $7.45 |
SES à-la-carte is the same idea: 1 email is $0.0001, not $0.10.
Caveat: Cloudflare has not published an explicit “we never round Email Sending up to the next 1,000” rule (Durable Objects do round some units). Public calculators and the SES-style wording treat it as per-email. The only real minimum is the $5 Workers Paid plan.
Other billing details:
- Sends to verified destination addresses (your own Gmail/Outlook, etc.) are free and do not count toward the 3,000, on Free or Paid.
- Hard bounces do count. API rejects / suppression-list blocks do not.
- Email Routing (inbound) is unlimited and free. An Email Worker that handles inbound mail is billed as a normal Worker (10M requests included on Paid). That is not the $0.35 charge.
- $0.35 is outbound sending only.
Price comparison
SES is cheaper for sending. Cloudflare is cheaper (free) for receiving.
Cloudflare (official)
- Inbound Email Routing: unlimited, free, Free or Paid
- Outbound Email Sending: beta, Workers Paid only
- Workers Paid: $5 / month
- 3,000 included outbound / month, then $0.35 / 1,000
- Message size: 5 MiB general send, 25 MiB inbound and verified-destination sends
- SMTP exists now:
smtp.mx.cloudflare.net:465implicit TLS (added 8 Jun 2026)
AWS SES (official, August 2026)
Two price tracks:
| Track | Who | Outbound |
|---|---|---|
| À-la-carte | Existing users, or anyone who switches | $0.10 / 1,000 + $0.12/GB attachments |
| Essentials (default for new accounts since 21 Jul 2026) | New SES accounts | $0.16 / 1,000 (bundles Virtual Deliverability Manager) |
You can switch a new account to à-la-carte. The old “3,000 free SES messages for 12 months” is gone for new customers. Inbound: $0.10 / 1,000 + $0.09 / 1,000 chunks (256 KB). Message size: 40 MB (v2 API / SMTP).
Same volumes, outbound only
À-la-carte SES ($0.10/1k) vs Cloudflare ($5 + $0.35/1k after 3k):
| Volume / month | SES à-la-carte | SES Essentials (new default) | Cloudflare |
|---|---|---|---|
| 1 | $0.0001 | $0.00016 | $5.00 |
| 3,000 | $0.30 | $0.48 | $5.00 |
| 10,000 | $1.00 | $1.60 | $7.45 |
| 100,000 | $10 | $16 | ~$39 |
| 1,000,000 | $100 | $160 | ~$354 |
SES is about 3.5× cheaper per email on à-la-carte, ~2.2× on Essentials. At tiny volume Cloudflare’s $5 floor dominates; at scale SES wins easily.
Hybrid is the cost-optimal split: Cloudflare Email Routing inbound, SES outbound.
Feature comparison
| Aspect | AWS SES | Cloudflare Email Service |
|---|---|---|
| Status | GA since 2011 | Email Sending public beta (~April 2026); Routing is mature |
| Best for | Lowest send cost, AWS stack, high volume | Workers apps, edge DX, free inbound |
| Endpoints | Regional (multi-region available) | Single global anycast endpoint |
| Client APIs | SMTP + HTTP API, IAM | Workers binding, REST API, SMTP (port 465) |
| DNS | You configure SPF/DKIM/DMARC | Auto SPF/DKIM/DMARC when the domain is on Cloudflare DNS |
| Deliverability tools | Configuration sets, suppression, dedicated IPs, VDM | Automatic IP reputation (claimed; sending still beta) |
| Dedicated IPs | Managed $15/account + per-email; Standard $24.95/IP | Not offered as a SKU |
| Inbound | Paid; rules → Lambda/S3/Mail Manager | Unlimited free routing + Email Workers |
SES wins on price, maturity, and raw scale. Cloudflare wins on developer experience inside Workers.
Encryption
Both encrypt in transit. Neither is end-to-end encrypted by default. Providers can read plaintext unless you encrypt before handoff.
You → service (submission)
- SES: HTTPS for the API; SMTP STARTTLS (ports 25/587/2587) or TLS Wrapper. TLS 1.2/1.3 required.
- Cloudflare: HTTPS for API/Workers; SMTP implicit TLS only on 465. No plaintext, no STARTTLS.
Service → recipient (delivery)
- SES: opportunistic TLS by default. You can Require TLS or drop on a configuration set. This is real, documented control.
- Cloudflare: MTA-STS is documented for inbound to your domain. There is no SES-style “require TLS or drop” knob for outbound delivery in the public docs.
End-to-end (S/MIME / OpenPGP)
- SES: explicitly supports the S/MIME and PGP MIME types. You encrypt in the client; SES transports ciphertext.
- Cloudflare: no first-class S/MIME/PGP docs. Raw MIME over SMTP should pass ciphertext through. The Workers
send()/ REST JSONhtml/textAPIs are a worse fit for pre-encrypted payloads.
At rest
- SES: encrypts at rest by default (AWS-owned keys). Inbound to S3 can use KMS.
- Cloudflare Routing: forwarding is designed not to keep a mailbox copy. If a Worker writes to R2, R2 encrypts at rest.
E2EE with SES send + Cloudflare receive is possible. Encrypt in the client → SES delivers ciphertext → a Cloudflare Worker stores ciphertext in R2 (or forwards). Headers (From, To, Subject) stay visible unless you use PGP subject encryption.
Can the mailbox be an R2 bucket?
Yes for storage. No for a drop-in Thunderbird inbox.
What works without a classic mail server
- MX → Cloudflare Email Routing
- An Email Worker receives the raw message
- The Worker
put()s the.eml(ciphertext) into R2 - Optional D1/KV index of From / Date / Message-ID
- A custom client lists R2/D1, downloads, and decrypts locally
Cloudflare’s own Agentic Inbox is this pattern: Workers + Durable Objects + R2 + a web client. Not Thunderbird.
What does not work out of the box
Thunderbird speaks IMAP/POP/SMTP. R2 is object storage. There is no “subscribe this bucket as INBOX.”
| Approach | Effort | Reality |
|---|---|---|
Download .eml and open in Thunderbird |
Low | Manual, not a mailbox |
| Custom add-on / local sync script | Medium–high | You are writing a mail client adapter |
| IMAP-to-R2 bridge | High | That is a server (or a long-running process) |
| Webmail on Workers (Agentic Inbox style) | Medium | The realistic serverless path |
Sending from Thunderbird is easy: SMTP to SES (STARTTLS 587) or to Cloudflare (smtp.mx.cloudflare.net:465). OpenPGP/S/MIME encrypt first, then submit.
Storage can be R2. Thunderbird cannot listen to R2 natively.
Effort and complexity
| Goal | Effort | Notes |
|---|---|---|
| Inbound aliases → Gmail/Outlook (CF Email Routing only) | Low (30–60 min) | Free. No Workers Paid. Best “just works” receive path |
| App transactional send via CF Workers | Low if already on Workers | Binding, domain onboard, Paid $5. Beta deliverability |
| App transactional send via SES | Medium | Verify domain, leave sandbox, IAM/SMTP, bounces/complaints. Cheapest at volume |
| Hybrid: CF receive + SES send | Low–medium | Best cost split. Domain can stay on CF DNS |
| Worker stores mail in R2, web UI to read | Medium | Real project; CF already has reference apps |
| True E2EE personal mail with Thunderbird + R2 | High | Key exchange, no native R2 IMAP, spam/deliverability, helper code |
Personal / low volume (hundreds of mails per month):
- Receive: Cloudflare Routing → existing inbox. $0
- Send: SES SMTP from Thunderbird. Pennies, some AWS setup
- You do not need Workers Paid unless you want Workers processing or Cloudflare sending
Building a private E2EE mailbox is doable, but you are building mail infrastructure (Worker, R2 layout, index, auth, client). A small web app that decrypts in-browser is less work than pretending R2 is IMAP.
Architecture in one sentence
Thunderbird encrypts → SES delivers cheaply → Cloudflare Worker stores ciphertext in R2 → a custom client (not stock Thunderbird) downloads and decrypts. Inbound routing on Cloudflare is free; SES sending is ~$0.10 per 1,000; Cloudflare sending is $5/month plus $0.35 per 1,000 after 3,000, billed as a per-email rate, not $0.35 per message.
Bottom line
- $0.35/1k is not $0.35 per email. One send inside the 3,000 is covered by the $5 Workers Paid plan. One send after that is about $0.00035.
- SES is cheaper for sending (~3.5× on à-la-carte). Cloudflare is cheaper for receiving (free).
- Hybrid is the boring right answer for cost: Cloudflare Email Routing inbound, SES outbound.
- E2EE is client-side, not a provider feature. SES is the better carrier for S/MIME/PGP. Cloudflare is a fine ciphertext dump via Worker → R2.
- R2 can be the store. Thunderbird cannot be the native client without extra software.