Seven jobs. One API.
Each of these is code you’d otherwise spread across Resend, a marketing tool and a cron job. Here they are one deploy, on your own Workers. Pick the one you came for.
Login codes and password resets
The email that has to arrive in seconds or your support queue fills up. Send from the Worker that’s already handling the request — no cross-cloud hop, no cold start, median 41ms to accept.
- Idempotency keys so a double-click can’t send twice
- Separate stream and tag, so a newsletter bounce can’t hurt it
- Time-to-accept per provider, plus seed-based placement — not just “delivered”
export default {
async fetch(req, env) {
const code = crypto.randomUUID().slice(0, 6);
await env.MAIL.send({
from: 'Acme <[email protected]>',
to: email,
subject: `${code} is your code`,
template_id: 'tpl_login',
data: { code },
tags: [{ name: 'stream', value: 'auth' }],
}, { idempotencyKey: `otp-${sessionId}` });
return Response.json({ ok: true });
},
};// Stripe webhook -> receipt with the PDF attached
await ms.emails.send({
from: '[email protected]',
to: invoice.customer_email,
subject: `Receipt ${invoice.number}`,
react: <Receipt invoice={invoice} />,
attachments: [{ filename: 'invoice.pdf',
path: invoice.pdf_url }],
tags: [{ name: 'stream', value: 'billing' }],
});Receipts, invoices and statements
Financial mail you may need to produce years later. Attachments and raw MIME live in your own R2 bucket, so retention is a lifecycle rule you write — not a plan tier someone sells you.
- Keep seven years of copies at $0.015/GB, no egress fees
- Batch up to 100 statements per call, queued and throttled
- Exact payload of any historical send, replayable
Attachment ceilings are per transport: Cloudflare Email Service caps a message at 5 MiB (25 MiB only to verified destinations), Amazon SES accepts 40 MB. Attachment docs →
Product notifications & digests
Mentions, comments, alerts, weekly summaries. The volume that makes per-email pricing hurt, and the category where bundling saves both money and inboxes.
Collapse 40 “new comment” emails into one 9am digest per user with an alarm — instead of 40 sends and one unsubscribe.
Categories with their own opt-outs, honoured automatically at send time and in the hosted preference centre.
A million notifications is ≈$363 on Cloudflare, or ≈$115 routed via SES. The math →
Onboarding sequences & win-backs
Day 0 welcome, day 2 nudge if they haven’t created a project, day 7 case study, stop the moment they convert.
Here it’s a Cloudflare Workflow running in your own account: durable steps, day-long waits that cost nothing while sleeping, branching on your own events, and a live count at every node. Automations docs →
Newsletters & product announcements
A visual editor your marketer can use, live segments your engineers can query, A/B tests that promote the winner on their own, and unsubscribe handling that keeps you the right side of CAN-SPAM.
- Create in the API or the editor — editable in both
- Throttle per minute, pause and resume mid-send
- One-click list-unsubscribe headers and a preference centre
Support inbox & reply-by-email
Receiving is free on Cloudflare Email Routing, so “email us back” stops being a feature request. Threads, attachments and search live in a Durable Object per mailbox.
[email protected] routes a reply straight back to the right object, with HMAC-signed headers.
Headers, text, HTML, spam score and attachment keys — one webhook, no MIME parsing in your app.
Assignment, status and canned replies are in the dashboard. See it →
Email for AI agents
Agents need a real address: to receive, to read a thread, and to send only when a human says yes. That is an MCP endpoint with nine tools, an API key for a credential, and a confirmation a person approves in the dashboard before anything leaves.
- Mark a mailbox Agent and it is the only one an agent can read
- Sending returns a confirmation first — you approve it, not the agent
- Works from Claude, Cursor or your own runtime
Wherever your code already runs
- Cloudflare WorkersNative binding, no HTTP hop
- Next.js & RemixServer actions + JSX templates
- Hono & BunTyped client, edge-first
- Rails & DjangoSMTP relay or native SDK
- LaravelMail driver package
- Go, Rust, ElixirFirst-party SDKs
- Java & .NETMaven and NuGet packages
- WordPressSMTP plugin config, five fields
Start with one job. Keep the rest for later.
Deploy it, send an OTP, and the broadcasts, automations and inbound are already sitting there when you need them.