Skills
Skill 2 of 14
Implement or troubleshoot Cloudflare Email Sending and Email Routing integrations and their delivery configuration.
3 minutes · 667 words · 6 sections
Install
npx skills add cloudflare/skills --skill cloudflare-email-servicenpx skills add cloudflare/skills/plugin marketplace add cloudflare/skillsThe first command installs just this skill, by the name in its SKILL.md; the second installs the whole repository.
Your knowledge of the Cloudflare Email Service, Email Routing or Email Sending may be outdated. Prefer retrieval over pre-training for any Cloudflare Email Service task.
Cloudflare Email Service lets you send transactional emails and route incoming emails, all within the Cloudflare platform. Your knowledge of this product may be outdated — it launched in 2025 and is evolving rapidly. Prefer retrieval over pre-training for any Email Service task.
If there is any discrepancy between this skill and the sources below, always trust the original source. The Cloudflare docs, REST API spec, @cloudflare/workers-types, and Agents SDK repo are the source of truth. This skill is a convenience guide — it may lag behind the latest changes. When in doubt, retrieve from the sources below and use what they say.
| Source | How to retrieve | Use for |
|---|---|---|
| Cloudflare docs | Cloudflare MCP docs tool or URL https://developers.cloudflare.com/email-service/ | API reference, limits, pricing, latest features |
| REST API spec | https://developers.cloudflare.com/api/resources/email_sending | OpenAPI spec for the Email Sending REST API |
| Workers types | https://www.npmjs.com/package/@cloudflare/workers-types | Type signatures, binding shapes |
| Agents SDK docs | Email agent walkthrough (opens in a new tab) | Email handling in Agents SDK |
Before writing any email code, verify the basics are in place:
npx wrangler email sending list to see which domains have email sending enabled. If the domain isn’t listed, run npx wrangler email sending enable userdomain.com or see cli-and-mcp.md (opens in a new tab) for full setup instructions.send_email in wrangler.jsonc (for Workers)npm ls postal-mime (only needed for receiving/parsing emails)Start here. Find your situation, then follow the link for full details.
| I want to… | Path | Reference |
|---|---|---|
| Send emails from a Cloudflare Worker | Workers binding (no API keys needed) | sending.md (opens in a new tab) |
| Send emails from an AI agent built with Cloudflare Agents SDK (opens in a new tab) | onEmail() + replyToEmail() in Agent class | sending.md (opens in a new tab) |
| Send emails from an external app or agent (Node.js, Go, Python, etc.) | REST API with Bearer token | rest-api.md (opens in a new tab) |
| Send emails from a coding agent (Claude Code, Cursor, Copilot, etc.) | MCP tools, wrangler CLI, or REST API | cli-and-mcp.md (opens in a new tab) |
| Receive and process incoming emails (Email Routing) | Workers email() handler | routing.md (opens in a new tab) |
| Set up Email Sending or Email Routing | wrangler email sending enable / wrangler email routing enable, or Dashboard | cli-and-mcp.md (opens in a new tab) |
| Improve deliverability, avoid spam folders | Authentication, content, compliance | deliverability.md (opens in a new tab) |
Prefer the binding for Workers; use REST for external apps or when explicitly requested. Read sending.md (opens in a new tab) or rest-api.md (opens in a new tab) to retrieve the documentation for the selected task before writing code. These guides cover setup, recipients, attachments, headers, limits, response handling, and errors; the Workers guide also covers Agents SDK integration and types matched to the project configuration.
| Mistake | Why It Happens | Fix |
|---|---|---|
Forgetting send_email binding in wrangler config | Email Service uses a binding, not an API key | Add "send_email": [{ "name": "EMAIL" }] to wrangler.jsonc |
| Sending from an unverified domain | Domain must be onboarded onto Email Sending before first send | Run wrangler email sending enable yourdomain.com or onboard in Dashboard |
Reading message.raw twice in email handler | The raw stream is single-use — second read returns empty | Buffer first: const raw = await new Response(message.raw).arrayBuffer() |
Missing text field (HTML only) | Some email clients only show plain text; also helps spam scores | Always include both html and text versions |
| Using email for marketing/bulk sends | Email Service is for transactional email only | Use a dedicated marketing email platform for newsletters and campaigns |
| Forwarding to unverified destinations | message.forward() only works with verified addresses | Run wrangler email routing addresses create user@gmail.com or add in Dashboard |
| Testing with fake addresses | Bounces from non-existent addresses hurt sender reputation | Use real addresses you control during development |
| Hardcoding API tokens in source code | Tokens in code get committed and leaked | Use environment variables or Cloudflare secrets |
Ignoring the from domain requirement | The from address must use a domain onboarded to Email Service | Verify the domain first, then send from anything@that-domain.com |
Using email key in REST API from object | REST API uses address not email for from object | Use { "address": "...", "name": "..." } for REST, { "email": "...", "name": "..." } for Workers |
Using replyTo in REST API | REST API uses snake_case field names | Use reply_to for REST API, replyTo for Workers binding |
Read the reference that matches your situation. You don’t need all of them.
email() handler, forwarding, replying, parsing. For receiving emails.main, last pushed 22 September 2026.SKILL.md, not by matching a directory convention. One layout observed: skills/*/SKILL.md.h1 and no skipped levels:.claude-plugin/marketplace.json by Cloudflare, declaring 1 plugin. It is read for editorial metadata only — never as the skill index, which is always the repository tree./cloudflare/skills.md, and each skill at its own .md URL.5 files · 24 KB
Everything this skill ships beside its prose. All of it is set here, as subchapters of skill 2.
Documentation the agent loads on demand, rather than up front.