Send transactional emails from your Cloudflare Workers using Resend.com. Perfect for contact forms.
- Prerequisites
- Getting Started
- Environment Variables
- Usage
- Changing the Sender Username
- Adding Cloudflare Turnstile captcha
- Add your domain to Resend.com: Follow the instructions on the Resend.com dashboard to add your domain.
- Generate Resend.com API key: Create a new API key with
Sending accesspermission. This will be used to authenticate your emails.
- Install dependencies: Run
npm installto install the required dependencies. - Run the setup script: Run
./cli.jsand follow the instructions.
This will create a .dev.vars file with your RESEND_CONFIG and SALT values.
-
Set environment variables: Use the created
RESEND_CONFIGandSALTvalues and run:npx wrangler secret put RESEND_CONFIGnpx wrangler secret put SALT
(Alternatively, you can set these values via your Cloudflare Dashboard.)
-
Deploy the Cloudflare Worker: Run
npm run deployto deploy the Cloudflare Worker.
The following environment variables are used in this project:

RESEND_CONFIG*: includes:- API key from Resend.com (
api_key) - Domain name used in Resend.com setup (
domain) - Custom profile name (
profile) (used in request 'profile' header or path param)
- API key from Resend.com (
Multiple configs supported via | separator
SALT: a random value used for recipient email encryption (if you want to obfuscate your email address)ENCRYPT_EMAIL_PATH: URL path suffix for email encryption (if you wish to expose the email encryption URL to live environment)CAPTCHA_SECRETS: Cloudflare Turnstile captcha secrets keys (if you need captcha validation before sending email)
This section covers how to use the Cloudflare Worker to send emails through Resend.com and how to encrypt email addresses for added security.
To send an email, make a request to the Cloudflare Worker with the required parameters. The worker handles the email sending process using Resend.com, based on the Resend.com - [POST] Send Email endpoint.
[POST] /send/:profile OR [POST] /send with the profile header
Content type: application/json and application/x-www-form-urlencoded are supported.
Required payload values:
recipient: string | string[] - The recipient email address. Max 50. e.g. "yourpersonalemail@gmail.com" (this can be the encrypted email or plain email)email: string | string[] - The reply-to email address. e.g. "john.smith@example.com"html: string - The HTML version of the message
Optional values:
name: string - The sender label, e.g. "John Smith".subject: string - The email subject.bcc: string | string[] - The Bcc recipient email address.cc: string | string[] - The Cc recipient email address.scheduled_at: string - Schedule email to be sent later. The date should be in ISO 8601 format (e.g: 2024-08-05T11:52:01.858Z).text: string - The plain text version of the message.headers: object - Custom headers to add to the email.attachments: object[] - Filename and content of attachments (max 40mb per email) (example).tags: object[] - Custom data passed in key/value pairs (example).- Any key starting with
:will be appended to thehtmlmessage as additional content.
[POST] /send/main
{
"recipient": "john.smith@example.com",
"name": "John Smith",
"email": "john@gmail.com",
"html": "<p>My sample message from API</p>",
"subject": "What is love?",
":Favourite pet": "Dragon",
":Favourite Colour": "Orange"
}Bruno collection available in bruno folder.
Note: From Resend.com the react, from, to, reply_to parameters are not supported.
Examples can be found in the examples folder.
Optional parameters:
includeMeta: Should collect information about the sender, such as userAgent, Location, IP address etc (default:true)preventThreading: Should prevent threading e.g. in Gmail (default:true)
For added security, you can encrypt the recipient email address before including it in the payload. Either:
Run your worker locally and use the encrypt endpoint:
npm run start
Then navigate to http://localhost:8787/encrypt?email=johndoe@example.com
Set ENCRYPT_EMAIL_PATH as your environment variable and navigate to https://yourworkerurl.com/encrypt/${ENCRYPT_EMAIL_PATH}?email=johndoe@example.com
By default, the sender username is set to submissions-noreply, which translates to the sender being submissions-noreply@yourdomain.com. If you wish to change this, you can edit the EMAIL_SENDER_USERNAME value in wrangler.toml and deploy, or set it via your Cloudflare Dashboard.
Follow the Get started with Turnstile guide and use the turnstile sitekey in CAPTCHA_SECRETS environment variable. For example: profile=main&key=1x0000000000000000000000000000000AA
- Add configurable CORS policies


