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.
Minimal Example
Section titled “Minimal Example”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(), },});Worker Runtime Usage
Section titled “Worker Runtime Usage”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"); },};HTML Email
Section titled “HTML Email”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"); },};Restrict Allowed Senders
Section titled “Restrict Allowed Senders”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"], }), },});Restrict Destinations
Section titled “Restrict Destinations”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 }, }), },});Properties
Section titled “Properties”Input Properties
Section titled “Input Properties”destinationAddress(string, optional): Restrict all sends to a single destination addressallowedDestinationAddresses(string[], optional): Restrict sends to a fixed allowlist of destination addressesallowedSenderAddresses(string[], optional): Restrict sends to a fixed allowlist of sender addressesdev.remote(boolean, optional): Use Cloudflare’s remote binding while developing locally