Skip to content

Latest commit

 

History

History
129 lines (94 loc) · 4.39 KB

File metadata and controls

129 lines (94 loc) · 4.39 KB

Email Service Agent Example

This example shows how to combine the new Cloudflare Email Service sending binding with Agents SDK email routing in one full-stack app.

What this demonstrates

  • Send transactional email from an agent with this.sendEmail()
  • Route inbound email into an agent with routeAgentEmail()
  • Parse MIME content with postal-mime
  • Optionally sign follow-up replies with replyToEmail() and EMAIL_SECRET
  • Keep inbox and outbox state synced to a React client with useAgent()
  • Simulate inbound email locally with /api/simulate-email before you deploy routing

Prerequisites

Before running this example, you need:

  1. A domain onboarded to Cloudflare Email Service

    • Log in to the Cloudflare Dashboard
    • Navigate to Compute & AI > Email Service
    • Select Onboard Domain and choose your domain
    • Add the DNS records (SPF and DKIM) to authorize sending
  2. A verified sender address in the Cloudflare dashboard

    • The example defaults to mailbox-7f3a@example.com
    • Change EMAIL_FROM in wrangler.jsonc to your verified address
  3. DNS propagation (usually 5-15 minutes, up to 24 hours)

Running it

npm install
cp .env.example .env
npm start

Before you send real email, review wrangler.jsonc:

  1. Update vars.EMAIL_FROM to your verified sender address
  2. Optional: add EMAIL_SECRET if you want signed reply routing:
wrangler secret put EMAIL_SECRET

The send_email binding is configured with remote: true, so npm start can call the real Email Service API from local development.

If EMAIL_SECRET is missing, the example still runs. Inbound mail uses address-based routing only, and auto-replies are sent unsigned.

Common Errors

Error Cause Solution
E_SENDER_NOT_VERIFIED Domain or sender not verified Complete domain onboarding in dashboard
E_RATE_LIMIT_EXCEEDED Too many emails sent Wait and retry
E_DAILY_LIMIT_EXCEEDED Daily quota reached Wait for next day or upgrade plan

How to use it

  1. Open the app in your browser
  2. Use Send outbound email to send a real message through Email Service
  3. Use Simulate inbound email to exercise the inbound routing path locally
  4. Deploy the Worker and route EMAIL_FROM to it to receive live email

Key patterns

Send with sendEmail()

const response = await this.sendEmail({
  binding: this.env.EMAIL,
  to,
  from: { email: this.env.EMAIL_FROM, name: "Email Service Agent" },
  replyTo: this.env.EMAIL_FROM,
  subject,
  text: body,
  html: body.replace(/\n/g, "<br />"),
  secret: this.env.EMAIL_SECRET
});

Route inbound mail into the agent

const addressResolver = createAddressBasedEmailResolver("EmailServiceAgent");

await routeAgentEmail(message, env, {
  resolver: async (email, env) => {
    if (env.EMAIL_SECRET) {
      const secureResolver = createSecureReplyEmailResolver(env.EMAIL_SECRET);
      const secureReply = await secureResolver(email, env);
      if (secureReply) return secureReply;
    }

    return addressResolver(email, env);
  }
});

With EMAIL_FROM="mailbox-7f3a@example.com", replies to mailbox-7f3a@example.com route to the EmailServiceAgent instance named mailbox-7f3a.

Local simulation endpoint

The app includes a small HTTP helper so the example is still useful before you deploy routing:

curl -X POST http://localhost:8787/api/simulate-email \
  -H "Content-Type: application/json" \
  -d '{
    "from": "customer@example.com",
    "subject": "Question about my account",
    "body": "Can you confirm my renewal date?"
  }'

That request creates a mock ForwardableEmailMessage and runs it through the same resolver chain as a real routed email.

Deploying for real email

  1. Onboard your domain in Cloudflare Email Service for both sending and routing
  2. Verify the sender address used by EMAIL_FROM
  3. Deploy this Worker with npm run deploy
  4. Add an Email Service routing rule that sends EMAIL_FROM to this Worker

Related docs