Test email routing behavior locally using wrangler dev to simulate incoming emails and verify your routing logic before deploying.
- Sign up for a Cloudflare account ↗.
- Install
Node.js↗.
Node.js version manager
Use a Node version manager like Volta ↗ or nvm ↗ to avoid permission issues and change Node.js versions. Wrangler, discussed later in this guide, requires a Node version of 16.17.0 or later.
Configure your Wrangler file:
{
"name": "email-routing-worker",
// Set this to today's date
"compatibility_date": "2026-07-20",
}name = "email-routing-worker"
# Set this to today's date
compatibility_date = "2026-07-20"import * as PostalMime from "postal-mime";
export default {
async email(message, env, ctx) {
// Parse the raw email message
const parser = new PostalMime.default();
const rawEmail = new Response(message.raw);
const email = await parser.parse(await rawEmail.arrayBuffer());
console.log("Received email:", {
from: message.from,
to: message.to,
subject: email.subject,
text: email.text,
html: email.html,
});
// Route based on recipient
if (message.to.includes("support@")) {
await message.forward("support-team@example.com");
} else {
await message.forward("general@example.com");
}
},
};Start your development server:
npx wrangler devSend a test email using the local endpoint. The request body must be a raw email message in RFC 5322 ↗ format, and the message must include a Message-ID header:
curl --request POST 'http://localhost:8787/cdn-cgi/handler/email' \
--url-query 'from=sender@example.com' \
--url-query 'to=recipient@example.com' \
--data-raw 'Received: from smtp.example.com (127.0.0.1)
by cloudflare-email.com (unknown) id 4fwwffRXOpyR
for <recipient@example.com>; Tue, 27 Aug 2024 15:50:20 +0000
From: "John" <sender@example.com>
Reply-To: sender@example.com
To: recipient@example.com
Subject: Testing Email Workers Local Dev
Content-Type: text/html; charset="windows-1252"
X-Mailer: Curl
Date: Tue, 27 Aug 2024 08:49:44 -0700
Message-ID: <6114391943504294873000@ZSH-GHOSTTY>
Hi there'This will output the parsed email structure in the console:
{
"headers": [
{
"key": "received",
"value": "from smtp.example.com (127.0.0.1) by cloudflare-email.com (unknown) id 4fwwffRXOpyR for <recipient@example.com>; Tue, 27 Aug 2024 15:50:20 +0000"
},
{ "key": "from", "value": "\"John\" <sender@example.com>" },
{ "key": "reply-to", "value": "sender@example.com" },
{ "key": "to", "value": "recipient@example.com" },
{ "key": "subject", "value": "Testing Email Workers Local Dev" },
{ "key": "content-type", "value": "text/html; charset=\"windows-1252\"" },
{ "key": "x-mailer", "value": "Curl" },
{ "key": "date", "value": "Tue, 27 Aug 2024 08:49:44 -0700" },
{
"key": "message-id",
"value": "<6114391943504294873000@ZSH-GHOSTTY>"
}
],
"from": { "address": "sender@example.com", "name": "John" },
"to": [{ "address": "recipient@example.com", "name": "" }],
"replyTo": [{ "address": "sender@example.com", "name": "" }],
"subject": "Testing Email Workers Local Dev",
"messageId": "<6114391943504294873000@ZSH-GHOSTTY>",
"date": "2024-08-27T15:49:44.000Z",
"html": "Hi there\n",
"attachments": []
}- Deploy your routing worker: Route emails get started
- See advanced patterns: Email routing examples