diff --git a/src/content/changelog/email-routing/2025-03-12-reply-limits.mdx b/src/content/changelog/email-routing/2025-03-12-reply-limits.mdx new file mode 100644 index 000000000000000..d7fa895eff4ef8f --- /dev/null +++ b/src/content/changelog/email-routing/2025-03-12-reply-limits.mdx @@ -0,0 +1,51 @@ +--- +title: Threaded replies now possible in Email Workers +description: You can now use Email Workers to send multiple replies to the same email thread. +date: 2025-03-12T18:00:00Z +--- + +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](/email-routing/email-workers/reply-email-workers/) to incoming emails. + +It's now possible to keep a threaded email conversation with an [Email Worker](/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: + +```ts title="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("", message.from, response.asRaw()); + await message.reply(replyMessage) + } +} satisfies ExportedHandler; +``` + +See [Reply to emails from Workers](/email-routing/email-workers/reply-email-workers/) for more information. \ No newline at end of file diff --git a/src/content/docs/email-routing/email-workers/reply-email-workers.mdx b/src/content/docs/email-routing/email-workers/reply-email-workers.mdx index a35ec6378b2d4e3..5e2cb2173a8fd99 100644 --- a/src/content/docs/email-routing/email-workers/reply-email-workers.mdx +++ b/src/content/docs/email-routing/email-workers/reply-email-workers.mdx @@ -40,12 +40,12 @@ export default { } ``` -To mitigate security risks and abuse, replying to incoming emails has a few requirements: +To mitigate security risks and abuse, replying to incoming emails has a few requirements and limits: * 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 `In-Reply-To` header of the reply message must be set to the `Message-ID` of the incoming message. * 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. -If these and other internal conditions are not met, then `reply()` will fail with an exception, otherwise you can freely compose your reply message and send it back to the original sender. +If these and other internal conditions are not met, `reply()` will fail with an exception. Otherwise, you can freely compose your reply message, send it back to the original sender, and receive subsequent replies multiple times. \ No newline at end of file diff --git a/src/content/docs/email-routing/postmaster.mdx b/src/content/docs/email-routing/postmaster.mdx index 39149664484a582..5602e436cee8f8f 100644 --- a/src/content/docs/email-routing/postmaster.mdx +++ b/src/content/docs/email-routing/postmaster.mdx @@ -28,17 +28,22 @@ The best way to contact us is using our [community forum](https://community.clou Through this standard, the sender publishes its public key to a domain's DNS once, and then signs the body of each message before it leaves the server. The recipient server reads the message, gets the domain public key from the domain's DNS, and validates the signature to ensure the message was not altered in transit. -Email Routing signs email on behalf of `email.cloudflare.net`. If the sender did not sign the email, the receiver will likely use Cloudflare's signature for authentication. +Email Routing adds two new signatures to the emails in transit, one on behalf of the Cloudflare domain used for sender rewriting `email.cloudflare.net`, and another one on behalf of the customer's recipient domain. Below is the DKIM key for `email.cloudflare.net`: ```sh -dig TXT 2022._domainkey.email.cloudflare.net +short +dig TXT cf2024-1._domainkey.email.cloudflare.net +short ``` ```sh output +"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiweykoi+o48IOGuP7GR3X0MOExCUDY/BCRHoWBnh3rChl7WhdyCxW3jgq1daEjPPqoi7sJvdg5hEQVsgVRQP4DcnQDVjGMbASQtrY4WmB1VebF+RPJB2ECPsEDTpeiI5ZyUAwJaVX7r6bznU67g7LvFq35yIo4sdlmtZGV+i0H4cpYH9+3JJ78k" "m4KXwaf9xUJCWF6nxeD+qG6Fyruw1Qlbds2r85U9dkNDVAS3gioCvELryh1TxKGiVTkg4wqHTyHfWsp7KD3WQHYJn0RyfJJu6YEmL77zonn7p2SRMvTMP3ZEXibnC9gz3nnhR6wcYL8Q7zXypKTMD58bTixDSJwIDAQAB" +``` + +You can find the DKIM key for the customer's `example.com` domain by querying the following: -"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnraPy1d8e6+lzeE1HIoUvYWoAOUSREkNHcwxA/ueVM8f6FKXvPu/9gVpgkn8iUyaCfk2z1MW+OVLuFeH64YRMa39mkaQalgke2tZ05SnjRUtYEHYvfrqPuMT+Ouk+GecpgvrtMq5gMXm6ZfeUhQkdWxmMQJGf4fdW5I0piUQJMhK/Qc1dNRSskk" "TiUtXKnsEdjTN2xcnHhyj985S0xOEAxm9Uj1rykPqVvKpqEdjUkujbXOwR0KmHTvPyFpBjCCfxAVqOwwo9zBYuvk/nh0qlDgLIpy0SimrYhNFCq2XBxIj4tdUzIl7qZ5Ck6zLCQ+rjzJ4sm/zA+Ov9kDkbcmyrwIDAQAB" +```sh +dig TXT cf2024-1._domainkey.example.com +short ``` ### DMARC enforcing @@ -88,14 +93,34 @@ example.com. 300 IN TXT "v=spf1 include:_spf.mx.cloudflare.net ~all" [The MX (mail exchange) records](https://www.cloudflare.com/learning/dns/dns-records/dns-mx-record/) tell the Internet where the inbound servers receiving email messages for the zone are. In this case, anyone who wants to send an email to `example.com` can use the `amir.mx.cloudflare.net`, `linda.mx.cloudflare.net`, or `isaac.mx.cloudflare.net` SMTP servers. +### Outbound prefixes + +Email Routing sends its traffic using both IPv4 and IPv6 prefixes, when supported by the upstream SMTP server. + +If you are a postmaster and are having trouble receiving Email Routing's emails, allow the following outbound IP addresses in your server configuration: + +**IPv4** + +`104.30.0.0/19` + +**IPv6** + +`2405:8100:c000::/38` + +_Ranges last updated: December 13th, 2023_ + ### Outbound hostnames -In addition to the outbound prefixes, Email Routing will use the domain `email.cloudflare.net` for the `HELO/EHLO` command. +In addition to the outbound prefixes, Email Routing will use the following outbound domains for the `HELO/EHLO` command: + +- `cloudflare-email.net` +- `cloudflare-email.org` +- `cloudflare-email.com` PTR records (reverse DNS) ensure that each hostname has an corresponding IP. For example: ```sh -dig a0-7.email.cloudflare.net +short +dig a-h.cloudflare-email.net +short ``` ```sh output @@ -107,25 +132,9 @@ dig -x 104.30.0.7 +short ``` ```sh output -a0-7.email.cloudflare.net. +a-h.cloudflare-email.net. ``` -### Outbound prefixes - -Email Routing sends its traffic using both IPv4 and IPv6 prefixes, when supported by the upstream SMTP server. - -If you are a postmaster and are having trouble receiving Email Routing's emails, allow the following outbound IP addresses in your server configuration: - -**IPv4** - -`104.30.0.0/20` - -**IPv6** - -`2405:8100:c000::/38` - -_Ranges last updated: December 13th, 2023_ - ### Sender rewriting Email Routing rewrites the SMTP envelope sender (`MAIL FROM`) to the forwarding domain to avoid issues with [SPF](#spf-record). Email Routing uses the [Sender Rewriting Scheme](https://en.wikipedia.org/wiki/Sender_Rewriting_Scheme) to achieve this. @@ -136,14 +145,27 @@ This has no effect to the end user's experience, though. The message headers wil In most cases, Email Routing forwards the upstream SMTP errors back to the sender client in-session. -### Spam and abusive traffic +### Realtime Block Lists -Handling spam and abusive traffic is essential to any email provider. Email Routing filters emails based on advanced anti-spam criteria, [powered by Email Security (formerly Area 1)](/email-security/). When Email Routing detects and blocks a spam email, you will receive a message with details explaining what happened. For example: +Email Routing uses an internal Domain Name System Blocklists (DNSBL) service to check if the sender's IP is present in one or more Realtime Block Lists (RBL) lists. When the system detects an abusive IP, it blocks the email and returns an SMTP error: ```txt -554 found on one or more DNSBLs (abusixip). Refer to https://developers.cloudflare.com/email-routing/postmaster/#spam-and-abusive-traffic/ +554 found on one or more RBLs (abusixip). Refer to https://developers.cloudflare.com/email-routing/postmaster/#spam-and-abusive-traffic/ +``` +We update our RBLs regularly. You can use combined block list lookup services like [MxToolbox](https://mxtoolbox.com/blacklists.aspx) to check if your IP matches other RBLs. IP reputation blocks are usually temporary, but if you feel your IP should be removed immediately, please contact the RBL's maintainer mentioned in the SMTP error directly. + +### Anti-spam + +In addition to DNSBL, Email Routing uses advanced heuristic and statistical analysis of the email's headers and text to calculate a spam score. We inject the score in the custom `X-Cf-Spamh-Score` header: + +``` +X-Cf-Spamh-Score: 2 ``` +This header is visible in the forwarded email. The higher the score, 5 being the maximum, the more likely the email is spam. Currently, this system is experimental and passive; we do not act on it and suggest that upstream servers and email clients don't act on it either. + +We will update this page with more information as we fine-tune the system. + ### SPF record A SPF DNS record is an anti-spoofing mechanism that is used to specify which IP addresses and domains are allowed to send emails on behalf of your zone. @@ -204,4 +226,4 @@ Email Routing does not support sending or replying from your Cloudflare domain. ### Signs such "`+`" and "`.`" are treated as normal characters for custom addresses -Email Routing does not have advanced routing options. Characters such as `+` or `.`, which perform special actions in email providers like Gmail and Outlook, are currently treated as normal characters on custom addresses. More flexible routing options are in our roadmap. +Email Routing does not have advanced routing options. Characters such as `+` or `.`, which perform special actions in email providers like Gmail and Outlook, are currently treated as normal characters on custom addresses. More flexible routing options are in our roadmap. \ No newline at end of file diff --git a/src/content/learning-paths/sase-overview-course.json b/src/content/learning-paths/sase-overview-course.json index a84d5d2d16eeee1..cd96b466decd7b8 100644 --- a/src/content/learning-paths/sase-overview-course.json +++ b/src/content/learning-paths/sase-overview-course.json @@ -3,10 +3,7 @@ "path": "/learning-paths/sase-overview-course/series/evolution-corporate-networks-1/", "priority": 1, "description": "Watch this series and learn all about Cloudflare's Secure Access Service Edge (SASE) platform to learn how it can revolutionize your corporate network.", - "products": [ - "Cloudflare One" - ], + "products": ["Cloudflare One"], "product_group": "Cloudflare One", "additional_groups": ["Cloudflare One"] } -