Cloudflare Email Service
hodgef/apiker
Send and receive transactional emails with Cloudflare Email Service (Email Sending + Email Routing).
Cloudflare Email Routing for receiving/sending emails via Workers.
$ npx skills add secondsky/claude-skills --skill cloudflare-email-routing -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install secondsky/claude-skills cloudflare-email-routing --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/secondsky/claude-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/cloudflare-email-routing/skills/cloudflare-email-routing .claude/skills/cloudflare-email-routing && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "cloudflare-email-routing" agent skill from https://github.com/secondsky/claude-skills/tree/main/plugins/cloudflare-email-routing/skills/cloudflare-email-routing into .claude/skills/cloudflare-email-routing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cloudflare-email-routing", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/secondsky/claude-skills/tree/main/plugins/cloudflare-email-routing/skills/cloudflare-email-routingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add secondsky/claude-skills --skill cloudflare-email-routing -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install secondsky/claude-skills cloudflare-email-routing --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/secondsky/claude-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/cloudflare-email-routing/skills/cloudflare-email-routing .agents/skills/cloudflare-email-routing && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "cloudflare-email-routing" agent skill from https://github.com/secondsky/claude-skills/tree/main/plugins/cloudflare-email-routing/skills/cloudflare-email-routing into .agents/skills/cloudflare-email-routing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cloudflare-email-routing", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add secondsky/claude-skills --skill cloudflare-email-routing -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install secondsky/claude-skills cloudflare-email-routing --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/secondsky/claude-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/cloudflare-email-routing/skills/cloudflare-email-routing .cursor/skills/cloudflare-email-routing && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "cloudflare-email-routing" agent skill from https://github.com/secondsky/claude-skills/tree/main/plugins/cloudflare-email-routing/skills/cloudflare-email-routing into .cursor/skills/cloudflare-email-routing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cloudflare-email-routing", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/secondsky/claude-skills.git --path plugins/cloudflare-email-routing/skills/cloudflare-email-routing--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add secondsky/claude-skills --skill cloudflare-email-routing -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install secondsky/claude-skills cloudflare-email-routing --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/secondsky/claude-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/cloudflare-email-routing/skills/cloudflare-email-routing .gemini/skills/cloudflare-email-routing && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "cloudflare-email-routing" agent skill from https://github.com/secondsky/claude-skills/tree/main/plugins/cloudflare-email-routing/skills/cloudflare-email-routing into .gemini/skills/cloudflare-email-routing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cloudflare-email-routing", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install secondsky/claude-skills cloudflare-email-routingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add secondsky/claude-skills --skill cloudflare-email-routing -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/secondsky/claude-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/cloudflare-email-routing/skills/cloudflare-email-routing .github/skills/cloudflare-email-routing && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "cloudflare-email-routing" agent skill from https://github.com/secondsky/claude-skills/tree/main/plugins/cloudflare-email-routing/skills/cloudflare-email-routing into .github/skills/cloudflare-email-routing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cloudflare-email-routing", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add secondsky/claude-skills --skill cloudflare-email-routing -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install secondsky/claude-skills cloudflare-email-routing --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/secondsky/claude-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/cloudflare-email-routing/skills/cloudflare-email-routing .opencode/skills/cloudflare-email-routing && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "cloudflare-email-routing" agent skill from https://github.com/secondsky/claude-skills/tree/main/plugins/cloudflare-email-routing/skills/cloudflare-email-routing into .opencode/skills/cloudflare-email-routing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cloudflare-email-routing", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
cloudflare-email-routingCloudflare Email Routing for receiving/sending emails via Workers.
Cloudflare Email Routing is an agent skill from secondsky/claude-skills. Cloudflare Email Routing for receiving/sending emails via Workers. Use for email workers, forwarding, allowlists, or encountering Email Trigger errors, worker call failures, SPF issues.
Its SKILL.md is about 2.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 13 other files, including reference files (for example `references/common-errors.md`, `references/dns-setup.md` and `references/local-development.md`).
It works with Cloudflare and Node.js. The repository describes itself as: Production-ready skills for Claude Code CLI - Cloudflare, React, Tailwind v4, and AI integrations. The licence is MIT.
2 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 8837836. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (TypeScript), which the agent can run.
Shell commands in SKILL.md call:
bunbunxFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
developers.cloudflare.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Cloudflare Email Routing loads about 2.8k tokens when it runs, and up to ~15k if it reads all its reference files. Until then it costs about 53 tokens; SKILL.md has 501 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from secondsky/claude-skills at commit 8837836, republished under its MIT licence (© secondsky). 501 words, ~2,804 tokens.
.claude/skills/cloudflare-email-routing/SKILL.md (or your agent's skills folder). This skill also uses 11 other files; get the full folder from GitHub.Status: Production Ready ✅ | Last Verified: 2025-11-18
Two capabilities:
Both free and work together for complete email functionality.
Dashboard setup:
hello@yourdomain.comInstall dependencies:
bun add postal-mime@2.5.0 mimetext@3.0.27Create email worker:
// src/email.ts
import { EmailMessage } from 'cloudflare:email';
import PostalMime from 'postal-mime';
export default {
async email(message, env, ctx) {
const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
console.log('From:', message.from);
console.log('Subject:', email.subject);
// Forward to destination
await message.forward('you@gmail.com');
}
};Configure wrangler.jsonc:
{
"name": "email-worker",
"main": "src/email.ts",
"compatibility_date": "2025-10-11", // must be >= 2024-09-23 for nodejs_compat
"compatibility_flags": ["nodejs_compat"] // Required! postal-mime needs Node.js compat
}Deploy and connect:
bunx wrangler deployDashboard → Email Workers → Create address → Select worker
Add send email binding:
{
"name": "my-worker",
"main": "src/index.ts",
"compatibility_date": "2025-10-11",
"send_email": [
{
"name": "SES",
"destination_address": "user@example.com"
}
]
}Send from worker:
import { EmailMessage } from 'cloudflare:email';
import { createMimeMessage } from 'mimetext';
const msg = createMimeMessage();
msg.setSender({ name: 'App', addr: 'noreply@yourdomain.com' });
msg.setRecipient('user@example.com');
msg.setSubject('Hello!');
msg.addMessage({
contentType: 'text/plain',
data: 'Email body here'
});
const message = new EmailMessage(
'noreply@yourdomain.com',
'user@example.com',
msg.asRaw()
);
await env.SES.send(message);Load references/setup-guide.md for complete walkthrough.
compatibility_flags: ["nodejs_compat"] for postal-mime (requires compatibility_date >= 2024-09-23)nodejs_compat (postal-mime requires the Node.js compat flag)const allowlist = ['approved@domain.com'];
if (!allowlist.includes(message.from)) {
message.setReject('Not on allowlist');
return;
}
await message.forward('you@gmail.com');const blocklist = ['spam@bad.com'];
if (blocklist.includes(message.from)) {
message.setReject('Blocked');
return;
}
await message.forward('you@gmail.com');const msg = createMimeMessage();
msg.setSender({ addr: 'noreply@yourdomain.com' });
msg.setRecipient(message.from);
msg.setSubject(`Re: ${email.subject}`);
msg.addMessage({
contentType: 'text/plain',
data: 'Thanks for your email!'
});
const reply = new EmailMessage(
'noreply@yourdomain.com',
message.from,
msg.asRaw()
);
await env.SES.send(reply);const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
for (const attachment of email.attachments) {
console.log('Filename:', attachment.filename);
console.log('Type:', attachment.mimeType);
console.log('Size:', attachment.content.byteLength);
}async email(message, env, ctx) {
const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
// Route based on subject
if (email.subject.includes('[Support]')) {
await message.forward('support@yourdomain.com');
} else if (email.subject.includes('[Sales]')) {
await message.forward('sales@yourdomain.com');
} else {
await message.forward('general@yourdomain.com');
}
}message.from // Sender email
message.to // Recipient email
message.headers // Email headers
message.raw // Raw email stream
message.rawSize // Size in bytes
// Methods
message.forward(address) // Forward to address
message.setReject(reason) // Reject emailemail.from // { name, address }
email.to // [{ name, address }]
email.subject // Subject line
email.text // Plain text body
email.html // HTML body
email.attachments // Array of attachments
email.headers // All headerscompatibility_flags: ["nodejs_compat"] (with compatibility_date >= 2024-09-23)async email(message, env, ctx) {
const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
// Create ticket in database
await env.DB.prepare(
'INSERT INTO tickets (email, subject, body, created_at) VALUES (?, ?, ?, ?)'
).bind(message.from, email.subject, email.text, Date.now()).run();
// Send confirmation
const msg = createMimeMessage();
msg.setSender({ addr: 'support@yourdomain.com' });
msg.setRecipient(message.from);
msg.setSubject('Ticket Created');
msg.addMessage({
contentType: 'text/plain',
data: 'Your support ticket has been created.'
});
const confirmation = new EmailMessage(
'support@yourdomain.com',
message.from,
msg.asRaw()
);
await env.SES.send(confirmation);
}export default {
async fetch(request, env, ctx) {
// User signup
const { email, name } = await request.json();
const msg = createMimeMessage();
msg.setSender({ name: 'App', addr: 'noreply@yourdomain.com' });
msg.setRecipient(email);
msg.setSubject('Welcome!');
msg.addMessage({
contentType: 'text/html',
data: `<h1>Welcome, ${name}!</h1>`
});
const message = new EmailMessage(
'noreply@yourdomain.com',
email,
msg.asRaw()
);
await env.SES.send(message);
return new Response('Welcome email sent!');
}
};async email(message, env, ctx) {
const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
// Filter spam keywords
const spamKeywords = ['viagra', 'lottery', 'prince'];
const isSpam = spamKeywords.some(keyword =>
email.subject.toLowerCase().includes(keyword) ||
email.text.toLowerCase().includes(keyword)
);
if (isSpam) {
message.setReject('Spam detected');
return;
}
await message.forward('you@gmail.com');
}references/setup-guide.md when:References (references/):
setup-guide.md - Complete setup walkthrough (enabling routing, email workers, send email)common-errors.md - All 8 documented errors with solutions and preventiondns-setup.md - MX records, SPF, DKIM configuration guidelocal-development.md - Local testing and development patternsTemplates (templates/):
receive-basic.ts - Basic email receiving workerreceive-allowlist.ts - Email allowlist implementationreceive-blocklist.ts - Email blocklist implementationreceive-reply.ts - Auto-reply email workersend-basic.ts - Basic send email examplesend-notification.ts - Notification email patternwrangler-email.jsonc - Wrangler configuration for email routingQuestions? Issues?
references/setup-guide.md for complete setupcompatibility_flags: ["nodejs_compat"] in wrangler.jsonc© secondsky, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 11 other files (references) in plugins/cloudflare-email-routing/skills/cloudflare-email-routing of secondsky/claude-skills.
Open the folder on GitHubat commit 8837836
Cloudflare Email Routing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Cloudflare Email Routing this skillsecondsky/claude-skills | 227 | — | ~2.8k | Automated safety check: Pass | MIT | |
| Cloudflare Email Servicehodgef/apiker | 127 | 3 repos | ~2k | Automated safety check: Pass | MIT | |
| Fumadocsbetter-notify/better-notify | 313 | — | ~2.3k | Automated safety check: Pass | MIT | |
| Workers Best Practiceshodgef/apiker | 127 | 6 repos | ~1.8k | Automated safety check: Pass | MIT | |
| Chart Visualizationbytedance/deer-flow | 83k | 2 repos | ~840 | Automated safety check: Pass | MIT | |
| Web Access via Browser CDPeze-is/web-access | 9.1k | 4 repos | ~2.2k | Automated safety check: Pass | MIT |
hodgef/apiker
Send and receive transactional emails with Cloudflare Email Service (Email Sending + Email Routing).
better-notify/better-notify
A skill your agent uses when writing MDX documentation pages for a Fumadocs project — frontmatter, meta.json, page ordering, and fumadocs-ui React components available inside MDX content.
hodgef/apiker
Reviews and authors Cloudflare Workers code against production best practices.
bytedance/deer-flow
Picks a suitable chart type from 26 options for your data, maps the data to that chart's parameters and generates a chart image through a JavaScript script.
eze-is/web-access
Routes every web task, from searching to logged-in browsing, through a tiered choice of search, fetch, curl or a real Chrome or Edge session driven over CDP.
kepano/obsidian-skills
Renders Markdown notes from Knap templates and JSON data on the command line, including notes built from Defuddle web page output.
secondsky/claude-skills
TanStack AI (alpha) provider-agnostic type-safe chat with streaming for OpenAI, Anthropic, Gemini, Ollama.
secondsky/claude-skills
AutoAnimate (@formkit/auto-animate) zero-config animations for React.
secondsky/claude-skills
MUI Base UI unstyled React components with Floating UI. An agent skill from secondsky/claude-skills.
secondsky/claude-skills
This skill should be used when the user asks to "upload images to Cloudflare", "implement direct creator upload", "configure image transformations", "optimize WebP/AVIF", "create image variants"…
secondsky/claude-skills
Deploy Next.js to Cloudflare Workers via the OpenNext adapter (@opennextjs/cloudflare).
secondsky/claude-skills
Cloudflare Sandboxes SDK for secure code execution in Linux containers at edge.
Works with
Cloudflare Email Routing for receiving/sending emails via Workers. Cloudflare Email Routing is an agent skill from secondsky/claude-skills. Cloudflare Email Routing for receiving/sending emails via Workers.
Cloudflare Email Routing fits situations like: encountering Email Trigger errors; worker call failures.
Run `npx skills add secondsky/claude-skills --skill cloudflare-email-routing -a claude-code`. Or copy the skill folder (plugins/cloudflare-email-routing/skills/cloudflare-email-routing in secondsky/claude-skills) into .claude/skills/cloudflare-email-routing in your project. Claude Code loads it when a task matches its description.
Run `npx skills add secondsky/claude-skills --skill cloudflare-email-routing -a codex`. Or copy the skill folder (plugins/cloudflare-email-routing/skills/cloudflare-email-routing in secondsky/claude-skills) into .agents/skills/cloudflare-email-routing in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add secondsky/claude-skills --skill cloudflare-email-routing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/cloudflare-email-routing, .gemini/skills/cloudflare-email-routing, .github/skills/cloudflare-email-routing and .opencode/skills/cloudflare-email-routing in your project.
Going by SKILL.md and its folder, Cloudflare Email Routing needs TypeScript for the scripts in its folder and the command-line tools its instructions call (bun and bunx). Our summary lists: Node.js.
SKILL.md names 1 domain. As links in the text: developers.cloudflare.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Cloudflare Email Routing is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.8k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 12k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Cloudflare Email Routing: Cloudflare Email Service (hodgef/apiker, 127 stars), Fumadocs (better-notify/better-notify, 313 stars), Workers Best Practices (hodgef/apiker, 127 stars) and Chart Visualization (bytedance/deer-flow, 83k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
secondsky (a GitHub user) maintains it in secondsky/claude-skills, which has 227 GitHub stars. The repository holds 169 skills in this directory. The repository was last updated on September 28, 2026.
Source: secondsky/claude-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.