Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/email-routing/api.md
1# Email Routing API Reference23## Worker Runtime API45### Email Handler Interface67```typescript8interface ExportedHandler<Env = unknown> {9email?(message: ForwardableEmailMessage, env: Env, ctx: ExecutionContext): void | Promise<void>;10}11```1213### ForwardableEmailMessage1415Main interface for incoming emails:1617```typescript18interface ForwardableEmailMessage {19readonly from: string; // Envelope sender (e.g., "[email protected]")20readonly to: string; // Envelope recipient (e.g., "[email protected]")21readonly headers: Headers; // Web API Headers object22readonly raw: ReadableStream; // Raw MIME message stream2324setReject(reason: string): void;25forward(rcptTo: string, headers?: Headers): Promise<void>;26}27```2829**Key Properties:**3031| Property | Type | Description |32|----------|------|-------------|33| `from` | `string` | Envelope sender (MAIL FROM), not header From |34| `to` | `string` | Envelope recipient (RCPT TO), not header To |35| `headers` | `Headers` | Email headers (Subject, From, To, etc.) |36| `raw` | `ReadableStream` | Raw MIME message (consume once only) |3738**Methods:**3940- `setReject(reason)`: Reject email with bounce message41- `forward(rcptTo, headers?)`: Forward to verified destination, optionally add headers4243### Headers Object4445Standard Web API Headers interface:4647```typescript48// Access headers49const subject = message.headers.get("subject");50const from = message.headers.get("from");51const messageId = message.headers.get("message-id");5253// Check spam score54const spamScore = parseFloat(message.headers.get("x-cf-spamh-score") || "0");55if (spamScore > 5) {56message.setReject("Spam detected");57}58```5960### Common Headers6162`subject`, `from`, `to`, `x-cf-spamh-score` (spam score), `message-id` (deduplication), `dkim-signature` (auth)6364### Envelope vs Header Addresses6566**Critical distinction:**6768```typescript69// Envelope addresses (routing, auth checks)70message.from // "[email protected]" (actual sender)71message.to // "[email protected]" (your address)7273// Header addresses (display, user-facing)74message.headers.get("from") // "Alice <[email protected]>"75message.headers.get("to") // "Bob <[email protected]>"76```7778**Use envelope addresses for:**79- Authentication/SPF checks80- Routing decisions81- Bounce handling8283**Use header addresses for:**84- Display to users85- Reply-To logic86- User-facing filtering8788## SendEmail Binding8990Outbound email API for transactional messages.9192### Configuration9394```jsonc95// wrangler.jsonc96{97"send_email": [98{ "name": "EMAIL" }99]100}101```102103### TypeScript Types104105```typescript106interface Env {107EMAIL: SendEmail;108}109110interface SendEmail {111send(message: EmailMessage): Promise<void>;112}113114interface EmailMessage {115from: string | { name?: string; email: string };116to: string | { name?: string; email: string } | Array<string | { name?: string; email: string }>;117subject: string;118text?: string;119html?: string;120headers?: Headers;121reply_to?: string | { name?: string; email: string };122}123```124125### Send Email Example126127```typescript128interface Env {129EMAIL: SendEmail;130}131132export default {133async fetch(request, env, ctx): Promise<Response> {134await env.EMAIL.send({135from: { name: "Acme Corp", email: "[email protected]" },136to: [137{ name: "Alice", email: "[email protected]" },138"[email protected]"139],140subject: "Your order #12345 has shipped",141text: "Track your package at: https://track.example.com/12345",142html: "<p>Track your package at: <a href='https://track.example.com/12345'>View tracking</a></p>",143reply_to: { name: "Support", email: "[email protected]" }144});145146return new Response("Email sent");147}148} satisfies ExportedHandler<Env>;149```150151### SendEmail Constraints152153- **From address**: Must be on verified domain (your domain with Email Routing enabled)154- **Volume limits**: Transactional only, no bulk/marketing email155- **Rate limits**: 100 emails/minute on Free plan, higher on Paid156- **No attachments**: Use links to hosted files instead157- **No DKIM control**: Cloudflare signs automatically158159## REST API Operations160161Base URL: `https://api.cloudflare.com/client/v4`162163### Authentication164165```bash166curl -H "Authorization: Bearer $API_TOKEN" https://api.cloudflare.com/client/v4/...167```168169### Key Endpoints170171| Operation | Method | Endpoint |172|-----------|--------|----------|173| Enable routing | POST | `/zones/{zone_id}/email/routing/enable` |174| Disable routing | POST | `/zones/{zone_id}/email/routing/disable` |175| List rules | GET | `/zones/{zone_id}/email/routing/rules` |176| Create rule | POST | `/zones/{zone_id}/email/routing/rules` |177| Verify destination | POST | `/zones/{zone_id}/email/routing/addresses` |178| List destinations | GET | `/zones/{zone_id}/email/routing/addresses` |179180### Create Routing Rule Example181182```bash183curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/email/routing/rules" \184-H "Authorization: Bearer $API_TOKEN" \185-H "Content-Type: application/json" \186-d '{187"enabled": true,188"name": "Forward sales",189"matchers": [{"type": "literal", "field": "to", "value": "[email protected]"}],190"actions": [{"type": "forward", "value": ["[email protected]"]}],191"priority": 0192}'193```194195Matcher types: `literal` (exact match), `all` (catch-all).196