Skip to content
Cloudflare Email Service

Cloudflare Email Service Skill

Wire up Cloudflare Email Sending and Email Routing — the send_email binding, the inbound email() handler, and the deliverability setup that keeps mail out of spam.

GitHub Docs

Install

Install with the skills CLI

One command for Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf and dozens of other agents. Needs Node.js; the skill is fetched straight from cloudflare/skills.

$ npx skills add cloudflare/skills --skill cloudflare-email-service

Run it in a terminal. The CLI finds the agents installed on your machine, asks which ones to add the skill to, and whether to install it into the folder you ran it from or for all your projects.

Other ways to install

Copy the whole skill folder — SKILL.md and any scripts or references beside it — into ~/.claude/skills/cloudflare-email-service/, where Claude Code picks it up in every project. Only git is needed.

tmp=$(mktemp -d) && \
  git clone --depth 1 --branch main https://github.com/cloudflare/skills.git "$tmp" && \
  mkdir -p ~/.claude/skills && \
  cp -R "$tmp"/skills/cloudflare-email-service ~/.claude/skills/cloudflare-email-service

No scripts or references next to it? Saving the SKILL.md alone as ~/.claude/skills/cloudflare-email-service/SKILL.md works too.

Using another agent? Its personal skills folder
Codex
~/.agents/skills/
Cursor
~/.cursor/skills/
GitHub Copilot
~/.copilot/skills/
Gemini CLI
~/.gemini/skills/
Windsurf
~/.codeium/windsurf/skills/
OpenCode
~/.config/opencode/skills/

About

  • Prerequisite gate: domain onboarding, send_email binding, postal-mime
  • Documents the REST vs Workers field asymmetry (address/reply_to vs email/replyTo)
  • Covers inbound Email Routing via the Workers email() handler
  • Deliverability reference for SPF, DKIM, DMARC, bounces and suppressions

Cloudflare Email Service launched in 2025 and is still moving quickly, which makes it a product agents confidently get wrong from stale training data. This official skill covers both halves — sending transactional mail and routing inbound mail — and leans hard on retrieval, naming the Cloudflare docs, the REST API spec, @cloudflare/workers-types and the Agents SDK repo as the sources of truth it may itself lag behind.

It begins with a prerequisites gate, which is the step that saves the most time. Before any email code is written the agent checks that the domain is onboarded (npx wrangler email sending list, then wrangler email sending enable), that send_email is present in wrangler.jsonc, and that postal-mime is installed when inbound mail is being parsed. From there a task table routes to the right reference: the Workers binding for sending, the REST API for external apps, the email() handler for Email Routing, or the deliverability guide for SPF, DKIM, DMARC, bounces and suppressions.

The strongest section is a common-mistakes table drawn from real integration failures, with the cause and fix for each. Several are API asymmetries no one guesses right: the REST API takes { "address": ... } and reply_to, while the Workers binding takes { "email": ... } and replyTo. Others are runtime traps — message.raw is a single-use stream, so a second read returns empty unless you buffer it first. And some are policy: Email Service is for transactional mail, not newsletters or bulk campaigns, and forwarding only works to verified destination addresses.

Aimed at developers building transactional email or inbound-mail automation on Workers, including email-driven agents via the Agents SDK. Apache-2.0.

SKILL.md

The instructions your agent loads, as published by Cloudflare.

SKILL.md
name
cloudflare-email-service
description
Implement or troubleshoot Cloudflare Email Sending and Email Routing integrations and their delivery configuration.

Cloudflare Email Service

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.

Retrieval Sources
SourceHow to retrieveUse for
Cloudflare docsCloudflare MCP docs tool or URL https://developers.cloudflare.com/email-service/API reference, limits, pricing, latest features
REST API spechttps://developers.cloudflare.com/api/resources/email_sendingOpenAPI spec for the Email Sending REST API
Workers typeshttps://www.npmjs.com/package/@cloudflare/workers-typesType signatures, binding shapes
Agents SDK docsEmail agent walkthroughEmail handling in Agents SDK
FIRST: Check Prerequisites

Before writing any email code, verify the basics are in place:

  1. Domain onboarded? Run 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](references/cli-and-mcp.md) for full setup instructions.
  2. Binding configured? Look for send_email in wrangler.jsonc (for Workers)
  3. postal-mime installed? Run npm ls postal-mime (only needed for receiving/parsing emails)
What Do You Need?

Start here. Find your situation, then follow the link for full details.

I want to...PathReference
Send emails from a Cloudflare WorkerWorkers binding (no API keys needed)[sending.md](references/sending.md)
Send emails from an AI agent built with [Cloudflare Agents SDK](https://developers.cloudflare.com/agents/)onEmail() + replyToEmail() in Agent class[sending.md](references/sending.md)
Send emails from an external app or agent (Node.js, Go, Python, etc.)REST API with Bearer token[rest-api.md](references/rest-api.md)
Send emails from a coding agent (Claude Code, Cursor, Copilot, etc.)MCP tools, wrangler CLI, or REST API[cli-and-mcp.md](references/cli-and-mcp.md)
Receive and process incoming emails (Email Routing)Workers email() handler[routing.md](references/routing.md)
Set up Email Sending or Email Routingwrangler email sending enable / wrangler email routing enable, or Dashboard[cli-and-mcp.md](references/cli-and-mcp.md)
Improve deliverability, avoid spam foldersAuthentication, content, compliance[deliverability.md](references/deliverability.md)
Sending Workflow

Prefer the binding for Workers; use REST for external apps or when explicitly requested. Read [sending.md](references/sending.md) or [rest-api.md](references/rest-api.md) 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.

Common Mistakes
MistakeWhy It HappensFix
Forgetting send_email binding in wrangler configEmail Service uses a binding, not an API keyAdd "send_email": [{ "name": "EMAIL" }] to wrangler.jsonc
Sending from an unverified domainDomain must be onboarded onto Email Sending before first sendRun wrangler email sending enable yourdomain.com or onboard in Dashboard
Reading message.raw twice in email handlerThe raw stream is single-use — second read returns emptyBuffer first: const raw = await new Response(message.raw).arrayBuffer()
Missing text field (HTML only)Some email clients only show plain text; also helps spam scoresAlways include both html and text versions
Using email for marketing/bulk sendsEmail Service is for transactional email onlyUse a dedicated marketing email platform for newsletters and campaigns
Forwarding to unverified destinationsmessage.forward() only works with verified addressesRun wrangler email routing addresses create user@gmail.com or add in Dashboard
Testing with fake addressesBounces from non-existent addresses hurt sender reputationUse real addresses you control during development
Hardcoding API tokens in source codeTokens in code get committed and leakedUse environment variables or Cloudflare secrets
Ignoring the from domain requirementThe from address must use a domain onboarded to Email ServiceVerify the domain first, then send from anything@that-domain.com
Using email key in REST API from objectREST API uses address not email for from objectUse { "address": "...", "name": "..." } for REST, { "email": "...", "name": "..." } for Workers
Using replyTo in REST APIREST API uses snake_case field namesUse reply_to for REST API, replyTo for Workers binding
References

Read the reference that matches your situation. You don't need all of them.

  • [references/sending.md](references/sending.md) — Documentation map for Workers binding, attachments, and Agents SDK email.
  • [references/rest-api.md](references/rest-api.md) — Documentation map for HTTP sending, request schemas, responses, and errors.
  • [references/routing.md](references/routing.md) — Inbound email() handler, forwarding, replying, parsing. For receiving emails.
  • [references/cli-and-mcp.md](references/cli-and-mcp.md) — Domain setup, wrangler commands, MCP tools. For first-time setup.
  • [references/deliverability.md](references/deliverability.md) — SPF/DKIM/DMARC, bounces, suppressions, best practices.
Install

Courier's official skill for building and debugging multi-channel notifications — email, SMS, push, in-app inbox, Slack, Teams and WhatsApp — from one send call.

Browse all skills →