---
title: Email Routing Changelog
image: https://developers.cloudflare.com/cf-twitter-card.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/changelog/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Changelog

New updates and improvements at Cloudflare.

[ Subscribe to RSS ](https://developers.cloudflare.com/changelog/rss/index.xml) [ View RSS feeds ](https://developers.cloudflare.com/fundamentals/new-features/available-rss-feeds/) 

Email Routing

![hero image](https://developers.cloudflare.com/_astro/hero.CVYJHPAd_26AMqX.svg) 

Jul 21, 2025
1. ### [Subaddressing support in Email Routing](https://developers.cloudflare.com/changelog/post/2025-07-21-subaddressing/)  
[ Email Routing ](https://developers.cloudflare.com/email-routing/)  
Subaddressing, as defined in [RFC 5233 ↗](https://www.rfc-editor.org/rfc/rfc5233), also known as plus addressing, is now supported in Email Routing. This enables using the "+" separator to augment your custom addresses with arbitrary detail information.  
Now you can send an email to `user+detail@example.com` and it will be captured by the `user@example.com` custom address. The `+detail` part is ignored by Email Routing, but it can be captured next in the processing chain in the logs, an [Email Worker](https://developers.cloudflare.com/email-routing/email-workers/) or an [Agent application ↗](https://github.com/cloudflare/agents/tree/main/examples/email-agent).  
Customers can use this feature to dynamically add context to their emails, such as tracking the source of an email or categorizing emails without needing to create multiple custom addresses.  
![Subaddressing](https://developers.cloudflare.com/_astro/subaddressing.x65bljxx_Z2W6LN.webp)  
Check our [Developer Docs](https://developers.cloudflare.com/email-routing/setup/email-routing-addresses/#subaddressing) to learn on to enable subaddressing in Email Routing.

Jun 30, 2025
1. ### [Mail authentication requirements for Email Routing](https://developers.cloudflare.com/changelog/post/2025-06-30-mail-authentication/)  
[ Email Routing ](https://developers.cloudflare.com/email-routing/)  
The Email Routing platform supports [SPF ↗](https://datatracker.ietf.org/doc/html/rfc7208) records and [DKIM (DomainKeys Identified Mail) ↗](https://en.wikipedia.org/wiki/DomainKeys%5FIdentified%5FMail) signatures and honors these protocols when the sending domain has them configured. However, if the sending domain doesn't implement them, we still forward the emails to upstream mailbox providers.  
Starting on July 3, 2025, we will require all emails to be authenticated using at least one of the protocols, SPF or DKIM, to forward them. We also strongly recommend that all senders implement the DMARC protocol.  
If you are using a Worker with an Email trigger to receive email messages and forward them upstream, you will need to handle the case where the forward action may fail due to missing authentication on the incoming email.  
SPAM has been a long-standing issue with email. By enforcing mail authentication, we will increase the efficiency of identifying abusive senders and blocking bad emails. If you're an email server delivering emails to large mailbox providers, it's likely you already use these protocols; otherwise, please ensure you have them properly configured.

Apr 08, 2025
1. ### [Local development support for Email Workers](https://developers.cloudflare.com/changelog/post/2025-04-08-local-development/)  
[ Email Routing ](https://developers.cloudflare.com/email-routing/)  
Email Workers enables developers to programmatically take action on anything that hits their email inbox. If you're building with Email Workers, you can now test the behavior of an Email Worker script, receiving, replying and sending emails in your local environment using `wrangler dev`.  
Below is an example that shows you how you can receive messages using the `email()` handler and parse them using [postal-mime ↗](https://www.npmjs.com/package/postal-mime):  
TypeScript  
```  
import * as PostalMime from "postal-mime";  
export default {  
  async email(message, env, ctx) {  
    const parser = new PostalMime.default();  
    const rawEmail = new Response(message.raw);  
    const email = await parser.parse(await rawEmail.arrayBuffer());  
    console.log(email);  
  },  
};  
```  
Now when you run `npx wrangler dev`, wrangler will expose a local `/cdn-cgi/handler/email` endpoint that you can `POST` email messages to and trigger your Worker's `email()` handler:  
Terminal window  
```  
curl -X POST 'http://localhost:8787/cdn-cgi/handler/email' \  
  --url-query 'from=sender@example.com' \  
  --url-query 'to=recipient@example.com' \  
  --header 'Content-Type: application/json' \  
  --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 is what you get 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": []  
}  
```  
Local development is a critical part of the development flow, and also works for sending, replying and forwarding emails. See [our documentation](https://developers.cloudflare.com/email-routing/email-workers/local-development/) for more information.

Mar 12, 2025
1. ### [Threaded replies now possible in Email Workers](https://developers.cloudflare.com/changelog/post/2025-03-12-reply-limits/)  
[ Email Routing ](https://developers.cloudflare.com/email-routing/)  
We’re removing some of the restrictions in Email Routing so that AI Agents and task automation can better handle email workflows, including how Workers can [reply](https://developers.cloudflare.com/email-routing/email-workers/reply-email-workers/) to incoming emails.  
It's now possible to keep a threaded email conversation with an [Email Worker](https://developers.cloudflare.com/email-routing/email-workers/) script as long as:  
   * The incoming email has to have valid [DMARC ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/).  
   * The email can only be replied to once in the same `EmailMessage` event.  
   * The recipient in the reply must match the incoming sender.  
   * The outgoing sender domain must match the same domain that received the email.  
   * Every time an email passes through Email Routing or another MTA, an entry is added to the `References` list. We stop accepting replies to emails with more than 100 `References` entries to prevent abuse or accidental loops.  
Here's an example of a Worker responding to Emails using a Workers AI model:  
AI model responding to emails  
```  
import PostalMime from "postal-mime";  
import { createMimeMessage } from "mimetext";  
import { EmailMessage } from "cloudflare:email";  
export default {  
  async email(message, env, ctx) {  
    const email = await PostalMime.parse(message.raw);  
    const res = await env.AI.run("@cf/meta/llama-2-7b-chat-fp16", {  
      messages: [  
        {  
          role: "user",  
          content: email.text ?? "",  
        },  
      ],  
    });  
    // message-id is generated by mimetext  
    const response = createMimeMessage();  
    response.setHeader("In-Reply-To", message.headers.get("Message-ID")!);  
    response.setSender("agent@example.com");  
    response.setRecipient(message.from);  
    response.setSubject("Llama response");  
    response.addMessage({  
      contentType: "text/plain",  
      data:  
        res instanceof ReadableStream  
          ? await new Response(res).text()  
          : res.response!,  
    });  
    const replyMessage = new EmailMessage(  
      "<email>",  
      message.from,  
      response.asRaw(),  
    );  
    await message.reply(replyMessage);  
  },  
} satisfies ExportedHandler<Env>;  
```  
See [Reply to emails from Workers](https://developers.cloudflare.com/email-routing/email-workers/reply-email-workers/) for more information.

[Search all changelog entries](https://developers.cloudflare.com/search/?contentType=Changelog+entry) 