Skip to content
GitHubXDiscordRSS

EmailSender

Learn how to configure Cloudflare Email Service send_email bindings for Workers using Alchemy.

The Cloudflare Email Service Workers API lets your Worker send outbound email through a native send_email binding.

Use EmailSender() inside a Worker’s bindings block when you want first-class, type-safe email sending from env.

Create a Worker with an email binding:

import { EmailSender, Worker } from "alchemy/cloudflare";
const worker = await Worker("mailer", {
name: "mailer",
entrypoint: "./src/worker.ts",
bindings: {
EMAIL: EmailSender(),
},
});

Send a plain-text email from your Worker:

interface Env {
EMAIL: SendEmail;
}
export default {
async fetch(_request: Request, env: Env) {
await env.EMAIL.send({
from: "noreply@example.com",
to: "hello@example.com",
subject: "Hello",
text: "Sent from Cloudflare Email Service.",
});
return new Response("sent");
},
};

Send an HTML email with a plain-text fallback:

interface Env {
EMAIL: SendEmail;
}
export default {
async fetch(_request: Request, env: Env) {
await env.EMAIL.send({
from: "noreply@example.com",
to: "hello@example.com",
subject: "Welcome",
html: "<h1>Welcome</h1><p>Your account is ready.</p>",
text: "Welcome. Your account is ready.",
});
return new Response("sent");
},
};

Lock the binding down to one or more sender addresses:

import { EmailSender, Worker } from "alchemy/cloudflare";
const worker = await Worker("mailer", {
name: "mailer",
entrypoint: "./src/worker.ts",
bindings: {
EMAIL: EmailSender({
allowedSenderAddresses: ["noreply@example.com"],
}),
},
});

Use destinationAddress to pin delivery to a single address, or allowedDestinationAddresses to allow a list of addresses:

import { EmailSender, Worker } from "alchemy/cloudflare";
const worker = await Worker("mailer", {
name: "mailer",
entrypoint: "./src/worker.ts",
bindings: {
EMAIL: EmailSender({
allowedDestinationAddresses: [
"ops@example.com",
"support@example.com",
],
}),
},
});

destinationAddress and allowedDestinationAddresses are mutually exclusive.

Local Development With Remote Email Sending

Section titled “Local Development With Remote Email Sending”

Set dev.remote to true to keep the Worker running locally while the email binding sends through Cloudflare:

import { EmailSender, Worker } from "alchemy/cloudflare";
const worker = await Worker("mailer", {
name: "mailer",
entrypoint: "./src/worker.ts",
bindings: {
EMAIL: EmailSender({
allowedSenderAddresses: ["noreply@example.com"],
dev: { remote: true },
}),
},
});
  • destinationAddress (string, optional): Restrict all sends to a single destination address
  • allowedDestinationAddresses (string[], optional): Restrict sends to a fixed allowlist of destination addresses
  • allowedSenderAddresses (string[], optional): Restrict sends to a fixed allowlist of sender addresses
  • dev.remote (boolean, optional): Use Cloudflare’s remote binding while developing locally