Cloudflare Email Service
CloudflareOfficialPublished by Cloudflare
- Skill
- Tool integration
- Cloud and DevOps
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The Cloudflare Email Service skill provides a framework for implementing transactional email sending and inbound email routing within the Cloudflare ecosystem. It covers domain onboarding, configuration of Workers bindings, REST API usage, and best practices for maintaining high deliverability. The skill emphasizes using retrieval-based methods to ensure developers access the most current API specifications and platform limits, as the service is rapidly evolving.
What it does
- Enables transactional email sending via Cloudflare Workers or REST API.
- Configures inbound email routing and processing using Workers handlers.
- Provides commands for domain onboarding and DNS record management.
- Offers guidance on deliverability, including SPF, DKIM, and DMARC configuration.
- Supports integration with Cloudflare Agents SDK for automated email workflows.
- Facilitates monitoring of sending limits, bounce handling, and suppression lists.
When to use it
- When you need to send transactional emails from a Cloudflare Worker or external application.
- When you need to receive and process incoming emails programmatically.
- When setting up a new domain for email services on the Cloudflare platform.
- When troubleshooting email delivery issues or managing suppression lists.
- When integrating email capabilities into an AI agent built with the Cloudflare Agents SDK.
Advantages
- Native integration with Cloudflare Workers and infrastructure.
- Automatic handling of SPF, DKIM, and bounce management.
- Unified platform for both sending and routing email.
- Direct access to analytics and delivery feedback via API.
- Supports both programmatic (API/Worker) and CLI-based management.
Usage examples
- “How do I enable email sending for my domain example.com using the CLI?”
- The agent will provide the command 'npx wrangler email sending enable example.com' and explain how to verify DNS records.
- “Show me how to send a transactional email from a Cloudflare Worker.”
- The agent will guide you to configure the 'send_email' binding in wrangler.jsonc and use the appropriate Worker binding syntax.
- “How can I check my daily email sending quota?”
- The agent will provide the REST API endpoint for the limits resource and explain how to authenticate using your API token.
- “What is the best way to handle incoming emails in a Worker?”
- The agent will explain the use of the email() handler and provide a pattern for parsing raw email content.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/cloudflare/cloudflare-email-service/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip cloudflare-email-service.zip -d .agents/skills
Documentation by Cloudflare
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
| Source | How to retrieve | Use for |
|---|---|---|
| Cloudflare docs | Cloudflare MCP docs tool or URL https://developers.cloudflare.com/email-service/index.md | API reference, limits, pricing, latest features |
| REST API spec | https://developers.cloudflare.com/api/resources/email_sending/index.md | 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 | Email handling in Agents SDK |
FIRST: Check Prerequisites
Before writing any email code, verify the basics are in place:
Domain onboarded? Run
npx wrangler email sending listto see which domains have email sending enabled. If the domain isn't listed, runnpx wrangler email sending enable userdomain.comor see cli-and-mcp.md for full setup instructions.Binding configured? Look for
send_emailinwrangler.jsonc(for Workers)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... | Path | Reference |
|---|---|---|
| Send emails from a Cloudflare Worker | Workers binding (no API keys needed) | sending.md |
| Send emails from an AI agent built with Cloudflare Agents SDK | onEmail() + replyToEmail() in Agent class | sending.md |
| Send emails from an external app or agent (Node.js, Go, Python, etc.) | REST API with Bearer token | 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 |
| Receive and process incoming emails (Email Routing) | Workers email() handler | routing.md |
| Set up Email Sending or Email Routing | wrangler email sending enable / wrangler email routing enable, or Dashboard | cli-and-mcp.md |
| Improve deliverability, avoid spam folders | Authentication, content, compliance | deliverability.md |
Sending Workflow
Prefer the binding for Workers; use REST for external apps or when explicitly requested. Read sending.md or 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
| 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 [email protected] 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 [email protected] |
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 |
References
Read the reference that matches your situation. You don't need all of them.
references/sending.md — Documentation map for Workers binding, attachments, and Agents SDK email.
references/rest-api.md — Documentation map for HTTP sending, request schemas, responses, and errors.
references/routing.md — Inbound
email()handler, forwarding, replying, parsing. For receiving emails.references/cli-and-mcp.md — Domain setup, wrangler commands, MCP tools. For first-time setup.
references/deliverability.md — SPF/DKIM/DMARC, bounces, suppressions, best practices.
Skill feedback
If the user reports that this skill gave incorrect or outdated guidance, or is missing information, read references/skill-feedback.md.
Files
- ATTRIBUTION.mdAdded by AutoGineer884 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md6.6 KiB
- references/cli-and-mcp.md4.0 KiB
- references/deliverability.md8.8 KiB
- references/rest-api.md1.8 KiB
- references/routing.md7.3 KiB
- references/sending.md2.6 KiB
- references/skill-feedback.md2.8 KiB
references/deliverability.md
Email Deliverability & Best Practices
For full details, see the deliverability docs and email authentication docs. All the monitoring endpoints below can be called via the REST API, Wrangler CLI, or the Cloudflare MCP server.
What Cloudflare Handles
When you onboard a domain, Cloudflare auto-configures:
SPF — TXT records authorizing Cloudflare's sending infrastructure
DKIM — Records for cryptographic signing of outbound emails
IP reputation — Managed sending infrastructure optimized for deliverability
Soft bounce retries — Automatic exponential backoff for temporary failures
Suppression lists — Hard-bounced addresses automatically blocked
Feedback loops — ISP complaint signals processed and acted on
Consider adding a DMARC record if you don't have one: v=DMARC1; p=quarantine; rua=mailto:[email protected]
Bounce Handling
Hard bounces — permanent failures (address doesn't exist, domain doesn't exist). Never retried. Address auto-added to suppression list. Sending to suppressed address returns E_RECIPIENT_SUPPRESSED.
Soft bounces — temporary failures (mailbox full, server down, greylisting). Cloudflare auto-retries with exponential backoff.
Suppression Lists
Account list (your account) — spam complaints from recipients. Cloudflare integrates with Postmasters to auto-suppress. You can manually add/remove addresses in the Dashboard.
See the suppressions docs for details.
Your Responsibilities
Content
Include both HTML and plain text versions
Use a recognizable sender name:
{ email: "[email protected]", name: "My App" }Write honest subject lines — avoid ALL CAPS, excessive punctuation
Include
List-Unsubscribeheaders for recurring emailsUse full URLs from your domain — avoid URL shorteners
List Quality
Validate email addresses before sending
Implement double opt-in for subscriptions
Honor unsubscribe requests promptly
Transactional Only
Email Service is for transactional email (triggered by user actions: signups, password resets, order confirmations). Marketing/bulk campaigns are not permitted — use a dedicated marketing platform.
Monitoring Deliverability
Dashboard
Per-domain and account-wide analytics are available in the Cloudflare dashboard:
Log in to the Cloudflare dashboard and select your account.
Go to Compute & AI > Email Service.
Select a domain or view account-wide metrics.
Select the Analytics tab.
Send Response
Every send (REST API or Workers binding) returns immediate delivery feedback. Check the response to track per-send outcomes:
{
"result": {
"delivered": ["[email protected]"],
"permanent_bounces": ["[email protected]"],
"queued": ["[email protected]"]
}
}Log these to build your own delivery rate metrics.
Sending Limits
Check your account's daily sending quota:
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/email/sending/limits" \
--header "Authorization: Bearer <API_TOKEN>"Returns:
{
"result": {
"quota": { "value": 5000, "unit": "day" }
}
}Suppression List
Addresses that hard-bounced or received spam complaints are auto-suppressed. You can query and manage suppressions via the API.
List suppressions (account-wide):
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/email/sending/suppression?page=1&per_page=100&order=created_at&direction=desc" \
--header "Authorization: Bearer <API_TOKEN>"Returns:
{
"page": 1,
"per_page": 100,
"total": 2,
"result": [
{
"id": "396a5436-d4b0-42a6-b3fc-48e8fa522321",
"email": "[email protected]",
"reason": "hard_bounce",
"created_at": "2026-03-15T10:00:00Z",
"expires_at": null
}
]
}Query params: page, per_page (max 1000), order (email | expires_at | created_at), direction (asc | desc).
Manually suppress an address:
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/email/sending/suppression" \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{ "email": "[email protected]", "expires_at": "2026-06-01T00:00:00Z" }'expires_at is optional — omit for permanent suppression.
Remove a suppression:
curl -X DELETE "https://api.cloudflare.com/client/v4/accounts/{account_id}/email/sending/suppression/{suppression_id}" \
--header "Authorization: Bearer <API_TOKEN>"GraphQL Analytics API
Email Service exposes two zone-level datasets via the GraphQL Analytics API. You can explore the schema interactively at graphql.cloudflare.com/explorer. Metrics are retained for 31 days.
| Dataset | Description |
|---|---|
emailSendingAdaptiveGroups | Aggregated counts grouped by dimensions (status, date, domain, auth results, etc.) |
emailSendingAdaptive | Individual email events with full detail (from, to, subject, messageId, errors, etc.) |
These are zone-level datasets — query under viewer > zones, not accounts.
Aggregated dimensions (emailSendingAdaptiveGroups):
| Dimension | Type | Description |
|---|---|---|
date | Date | Day-level grouping |
datetime | Time | Exact timestamp (also: datetimeMinute, datetimeFiveMinutes, datetimeFifteenMinutes, datetimeHour) |
status | string | Delivery status |
eventType | string | Event type |
sendingDomain | string | The sending domain |
envelopeTo | string | Recipient address |
errorCause | string | Error cause for failed sends |
arc, dkim, dmarc, spf | string | Email authentication results |
isSpam, isNDR, isLastEvent | uint8 | Boolean flags |
spamScore, spamThreshold | uint32 | Spam scoring |
Individual event fields (emailSendingAdaptive) additionally include: from, to, subject, messageId, sessionId, errorDetail.
Email counts by status and date:
query EmailSendingByStatus(
$zoneTag: string!
$start: Date!
$end: Date!
) {
viewer {
zones(filter: { zoneTag: $zoneTag }) {
emailSendingAdaptiveGroups(
filter: { date_geq: $start, date_leq: $end }
limit: 10000
orderBy: [date_DESC]
) {
count
dimensions {
date
status
}
}
}
}
}Filter by status (e.g. only failures):
query EmailFailures(
$zoneTag: string!
$start: Date!
$end: Date!
) {
viewer {
zones(filter: { zoneTag: $zoneTag }) {
emailSendingAdaptiveGroups(
filter: { date_geq: $start, date_leq: $end, status: "deliveryFailed" }
limit: 10000
orderBy: [date_DESC]
) {
count
dimensions {
date
errorCause
sendingDomain
}
}
}
}
}Individual email events (troubleshooting):
query RecentEmailEvents(
$zoneTag: string!
$start: Time!
$end: Time!
) {
viewer {
zones(filter: { zoneTag: $zoneTag }) {
emailSendingAdaptive(
filter: { datetime_geq: $start, datetime_leq: $end }
limit: 50
orderBy: [datetime_DESC]
) {
datetime
from
to
subject
status
eventType
sendingDomain
messageId
errorCause
errorDetail
dkim
dmarc
spf
isSpam
}
}
}
}Note: emailSendingAdaptive filters use datetime_geq/datetime_leq (Time type, e.g. "2026-04-01T00:00:00Z"), while emailSendingAdaptiveGroups uses date_geq/date_leq (Date type, e.g. "2026-04-01").
curl example:
curl "https://api.cloudflare.com/client/v4/graphql" \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{
"query": "query($zoneTag:string!,$start:Date!,$end:Date!){viewer{zones(filter:{zoneTag:$zoneTag}){emailSendingAdaptiveGroups(filter:{date_geq:$start,date_leq:$end},limit:10000,orderBy:[date_DESC]){count,dimensions{date,status}}}}}",
"variables": {
"zoneTag": "<ZONE_ID>",
"start": "2026-03-15",
"end": "2026-04-15"
}
}'Metrics to Watch
| Metric | Target | If Out of Range |
|---|---|---|
| Delivery rate | > 95% | Check for invalid addresses; verify DNS records |
| Hard bounce rate | < 2% | Clean your email list |
| Complaint rate | < 0.1% | Make unsubscribe easier; stop unwanted emails |
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs an API key, Needs Node.js
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Cloudflare
- Publisher
- Cloudflare (Official)
- Source
- cloudflare/skills · skills/cloudflare-email-service · commit 6eb6c78
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Cloudflare.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download cloudflare-email-service.zip