Tech 5 min read

Cloudflare Email Service Hits Public Beta: Sending and Receiving Mail from Agents

IkesanContents

Cloudflare Email Service went public beta. After a private beta that produced real-world cases like customer support agents, invoice processing, and identity verification flows, the service is now generally available.

The Agents Week announcements have rolled out through Sandboxes GA, Durable Object Facets, and the Unified CLI, Mesh and Enterprise MCP Reference Architecture, and Project Think, Browser Run, and Workflows v2. Email Service caps the series. The framing is that agents should show up where users already are, and one of those places is the inbox.

Sending: Workers Binding and REST API

Start with how sending works. It’s available on Workers Paid plans.

Add the following binding to wrangler.jsonc, and you can send mail from a Worker via env.EMAIL.send().

"send_email": [{"name": "EMAIL"}]
export default {
  async fetch(request, env, ctx) {
    await env.EMAIL.send({
      to: "user@example.com",
      from: "notifications@your-domain.com",
      subject: "Your order has shipped",
      text: "Your order #1234 has shipped..."
    });
    return new Response("Email sent");
  },
};

No API keys or secrets to manage — Cloudflare handles SPF, DKIM, and DMARC automatically. Offloading the authentication layer that decides whether your mail gets flagged as spam is quietly important. It wipes out the most tedious part of rolling your own email sending.

You can also drive it from the REST API.

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/email/sending/send" \
  --header "Authorization: Bearer <API_TOKEN>" \
  --header "Content-Type: application/json" \
  --data '{
    "to": "user@example.com",
    "from": "notifications@your-domain.com",
    "subject": "Your order has shipped",
    "text": "Your order #1234 has shipped..."
  }'

TypeScript, Python, and Go SDKs are all supported. You can also send directly from the Wrangler CLI.

wrangler email send \
  --to "teammate@example.com" \
  --from "agent@your-domain.com" \
  --subject "Build completed" \
  --text "The build passed. Deployed to staging."

This is handy when the agent is running locally or inside a sandbox, since it keeps context overhead low. An MCP server for hitting the Cloudflare API is also available, and it works under Code Mode (formerly Cursor Mode).

Receiving: Email Routing Plus the onEmail Hook

Receiving is built on top of the existing Email Routing service. Email Routing forwards inbound mail for a domain to a Worker or an external address, and it has been offered free for several years.

The Agents SDK now includes an onEmail hook.

import { Agent, routeAgentEmail } from "agents";
import { createAddressBasedEmailResolver } from "agents/email";
import PostalMime from "postal-mime";

export class SupportAgent extends Agent {
  async onEmail(email: AgentEmail) {
    const raw = await email.getRaw();
    const parsed = await PostalMime.parse(raw);

    // Persist state across sessions via Durable Objects
    this.setState({
      ...this.state,
      ticket: {
        from: email.from,
        subject: parsed.subject,
        body: parsed.text,
        messageId: parsed.messageId
      }
    });

    // Send a reply
    await this.sendEmail({
      binding: this.env.EMAIL,
      fromName: "Support Agent",
      from: "support@yourdomain.com",
      to: this.state.ticket.from,
      inReplyTo: this.state.ticket.messageId,
      subject: `Re: ${this.state.ticket.subject}`,
      text: "Thanks for reaching out..."
    });
  }
}

export default {
  async email(message, env) {
    await routeAgentEmail(message, env, {
      resolver: createAddressBasedEmailResolver("SupportAgent"),
    });
  },
};

this.setState() pins conversation history and contact info to the agent instance. You don’t need to stand up a separate backend database — the inbox itself acts as memory storage.

Address-Based Routing

You can route a single domain to multiple agents.

AddressAgent
support@yourdomain.comSupportAgent
sales@yourdomain.comSalesAgent
billing@yourdomain.comBillingAgent

Subaddressing (the + separator) is supported too, so NotificationAgent+user123@yourdomain.com embeds a user ID in the address and delivers to a specific agent instance. Useful when you want to manage many per-user agents under a single domain.

HMAC-SHA256 for Reply Routing

Accurate reply routing uses HMAC-SHA256 signatures. This prevents header forgery and guarantees that replies land back on the original agent instance. Even in multi-agent setups, conversation context doesn’t cross the wires.

Reference Implementation: Agentic Inbox

Cloudflare also published an open-source reference implementation called Agentic Inbox. It ships with a full email-client feature set.

  • Threaded conversation UI and email rendering
  • Attachment storage on R2
  • Message classification with Workers AI
  • An MCP server that lets agents review drafts
  • A one-click deploy option

The MCP server piece is the interesting part. An agent receives mail, drafts a reply, and a human reviews and approves that draft through MCP tools before it sends — a HITL (Human-in-the-Loop) flow. Combined with the Live View and HITL features added in Browser Run, you can build a system where an agent drives mail-triggered work and checks in with a human at the right moments, without much scaffolding.

Relationship to Email Routing

Email Service is positioned as “Email Routing + sending + Agent integration.” Existing Email Routing only covered inbound routing, leaving outbound to services like SendGrid or Postmark. This release closes that asymmetry.

Use cases surfaced during the private beta include customer support agents, invoice processing, account verification flows, and multi-agent workflows. Each leans on mail as its substrate. Unlike synchronous interfaces (web forms, chat), the asynchronous nature of email matches how agents actually work — the agent doesn’t have to reply immediately, it can just send a notification once its processing is done.

Agents Week has been rounding out the foundation Cloudflare has built for always-on agents — Sandboxes (code execution), Durable Object Facets (state management), Workflows v2 (async job control) — and Email Service (mail I/O) now joins the list. Email may be a less flashy channel than web forms or chat, but its deep roots in enterprise workflows give it outsized practical impact.