AgentStack
SKILL verified MIT Self-run

Build Cloudflare Email Sending

skill-yigitkonur-skills-by-yigitkonur-build-cloudflare-email-sending · by yigitkonur

Use if sending email via Cloudflare Email Service, replacing Resend/SES/Postmark or send_email.

No reviews yet
0 installs
6 views
0.0% view→install

Install

$ agentstack add skill-yigitkonur-skills-by-yigitkonur-build-cloudflare-email-sending

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README — it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-yigitkonur-skills-by-yigitkonur-build-cloudflare-email-sending)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
16d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Build Cloudflare Email Sending? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Build Cloudflare Email Sending

Cloudflare Email Service (open beta since 2026-04) sends transactional email through three equivalent paths — a Workers send_email binding, a REST API, and SMTP — all sharing one pipeline, one quota, and automatic DKIM/ARC signing. This skill gets a sending domain onboarded, picks the right send path for the caller's architecture, and executes migrations from other providers without breaking email mid-cutover.

When to use

Use this skill if you are:

  • Migrating transactional email off Resend, SES, Postmark, or SendGrid onto

Cloudflare.

  • Fixing Supabase Auth's rate-limited built-in mailer, or fully rebranding

its signup/reset/magic-link emails.

  • Wiring a send_email Workers binding, wrangler email sending, or a

Worker relay for a backend that runs outside Cloudflare (Railway, Fly, Vercel, a VPS).

  • Architecting transactional email from scratch for a stack already on

Workers.

  • Debugging cf-bounce DNS, DKIM/SPF conflicts, or Email Service quota

errors.

This is the sending product (open beta, 2026) — not Email Routing/receiving, not the retired MailChannels path.

First: three facts that shape every decision

  1. The sending domain's DNS zone must be on Cloudflare. Onboarding

auto-creates bounce MX + SPF + DKIM + DMARC records; it cannot do that on external DNS. If the target domain's nameservers point elsewhere, either move the zone first or onboard a different Cloudflare-hosted domain as an interim sender (working substitute now beats perfect sender later — swap from when the zone moves).

  1. **API-token creation is dashboard-gated; the Worker binding needs no token

at all.** For backends running outside Cloudflare, the highest-leverage pattern is a tiny Worker relay: the Worker holds the send_email binding ambiently, the backend calls it over HTTPS with a shared random secret. No Cloudflare credential ever touches the backend.

  1. Quota starts at ~1,000 sends/day and Cloudflare raises it reluctantly

(practitioner reports: a $20-30k/mo account fought to get 5,000/day). 3,000 sends/month included on Workers Paid ($5/mo floor), then $0.35/1k. If projected volume exceeds 1,000/day, file the limit-increase form at the start of the migration, not the end — treat it as a blocking dependency.

Workflow

1. Verify tooling and account

wrangler --version          # need >= 4.110; older versions 404 on sending endpoints
wrangler whoami             # confirms login; note available account IDs

Multi-account logins fail non-interactively — export CLOUDFLARE_ACCOUNT_ID= before every wrangler email command. Find the account that owns the target zone by probing:

CLOUDFLARE_ACCOUNT_ID= wrangler email sending settings 
# "Could not find a zone" → wrong account; repeat with the next id

2. Onboard the sending domain

dig +short NS       # *.ns.cloudflare.com → zone is on Cloudflare; else see fact 1
CLOUDFLARE_ACCOUNT_ID= wrangler email sending enable 
CLOUDFLARE_ACCOUNT_ID= wrangler email sending dns get    # inspect what was created

enable auto-creates, on the cf-bounce subdomain: three bounce MX records, an SPF TXT, a DKIM key at cf-bounce._domainkey, plus _dmarc.. Verify propagation before the first send:

dig +short MX cf-bounce.
dig +short TXT cf-bounce._domainkey. | head -c 40
dig +short TXT _dmarc.

SPF conflict rule: if the root domain already has an SPF record from another sender, Cloudflare's include:_spf.mx.cloudflare.net must be merged into that one record — a second SPF TXT is invalid and tanks deliverability. The cf-bounce records are namespaced and never conflict. Subdomains (notifications.) onboard independently — use one per traffic class for reputation isolation.

3. Pick the send path

| Caller | Path | Why | |---|---|---| | Code already on Workers | send_email binding | Zero credentials, zero HTTP hop | | Backend outside Cloudflare (Railway/Fly/VPS/Vercel functions) | Worker relay (this skill's template) | Token creation is dashboard-gated; a shared secret to your own Worker is the only credential | | Legacy app that only speaks SMTP | smtp.mx.cloudflare.net:465, user api_token, password = a token with Email Sending: Edit | No code changes | | One-off / CI / smoke test | wrangler email sending send --from ... --to ... --subject ... --text ... | Fastest proof |

For the Worker relay: copy assets/email-sender-worker/ into the repo (e.g. workers/email-sender/), deploy, set the secret, verify:

cd workers/email-sender
CLOUDFLARE_ACCOUNT_ID= npx wrangler deploy
openssl rand -hex 32 | CLOUDFLARE_ACCOUNT_ID= npx wrangler secret put AUTH_TOKEN
# keep the generated value ONLY in the backend's secret store (env var / vault) — never in git

The #1 API landmine: the Workers binding's address-object shape is {email, name} while the REST API's is {address, name}. The bundled Worker template translates; hand-rolled code that passes {address} to the binding fails with "Incorrect type for the 'email' field". The wrangler CLI smoke-send accepts display strings ("Name ").

4. Wire the application with a fallback window

Never hard-cut from the old provider. Route by config: prefer Cloudflare when its env vars are set, fall back to the old provider otherwise — either provider alone keeps email alive, and rollback is unsetting two vars. Keep the old provider's fallback for 2–4 weeks of observed deliverability (the product is beta; no public inbox-placement history exists yet).

Provider-specific mappings, DNS specifics, and code-shape diffs:

  • Migrating from Resend (or SES/Postmark — same shape): read

references/migrate-from-resend.md

  • Replacing Supabase Auth's built-in mailer (confirmation, magic link,

recovery emails): read references/supabase-auth-emails.md

  • Greenfield — architecting email for a new product on Cloudflare:

read references/greenfield-architecture.md

5. Verify end-to-end, then clean up

Every leg gets a live probe — a green deploy is not a delivered email:

# 1 Worker auth gate: wrong token must 401, missing config must 503
curl -s -X POST https:///send -H "Authorization: Bearer wrong" -d '{}' -o /dev/null -w "%{http_code}\n"
# 2 Real send returns a message_id
curl -s -X POST https:///send -H "Authorization: Bearer $EMAIL_SENDER_TOKEN" \
  -H "content-type: application/json" \
  -d '{"from":{"address":"welcome@","name":"Product"},"to":"","subject":"cutover probe","text":"probe"}'
# 3 The email actually lands in that inbox (check spam folder too)
# 4 The OLD provider's send log shows nothing new → traffic really moved
# 5 Quota headroom: GET /accounts//email/sending/limits (or the dashboard)

Delete any test users/rows the probes created. If probes sent to fake addresses, expect them in permanent_bounces — repeated hard bounces auto-suppress recipients, and unsuppression requires a Cloudflare support case, so always probe with a real inbox you control.

Credential hygiene (non-negotiable)

  • The Worker AUTH_TOKEN lives in exactly two places: wrangler secret and

the backend's secret store. Never in git, wrangler.jsonc, docs, or chat.

  • Rotation is a paired operation: wrangler secret put AUTH_TOKEN + update

the backend var in the same change window.

  • SMTP-path tokens are real Cloudflare API tokens — scope to **Email

Sending: Edit** only, nothing broader.

  • When writing examples or reports, show openssl rand -hex 32 as the

generation step, never a literal value.

Failure quick-reference

| Symptom | Cause | Fix | |---|---|---| | wrangler email sending → 404 | wrangler | | "Incorrect type for the 'email' field" | REST shape sent to the binding | {email} for binding, {address} for REST | | ESENDERNOTVERIFIED | domain/subdomain not onboarded | wrangler email sending enable + DNS check | | 429 / ERATELIMITEXCEEDED | daily quota (default ~1,000) | limit-increase form; queue + retry with backoff | | Lands in spam | DMARC alignment missing | verify dmarc TXT exists; merged SPF on root | | Recipient silently gets nothing | auto-suppressed after hard bounces | Cloudflare support case; stop probing fake addresses | | Dashboard shows sends as "dropped" | known Email Routing metrics false-negative | trust the send response's messageid`, not that panel |

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.