In most serverless environments, Cloudflare Workers included, you can not send e-mail through SMTP. Also, many client SDKs for providers such as Mailgun or Sendgrid assume you are on the Node platform and will not work in many serverless runtimes. Luckily most providers also provide a REST API to send e-mail.
I ended up going with Mailgun, below is some example Typescript code that works in Cloudflare Workers.
declare const MAILGUN_API_BASE_URL: string;
declare const MAILGUN_API_KEY: string;
export interface EmailData {
from: string;
to: string;
subject: string;
text: string;
html: string
cc?: string;
bcc?: string;
"h-Reply-To"?: string;
"o:testmode"?: boolean;
}
function urlEncodeObject(obj: {[s: string]: any}) {
return Object.keys(obj)
.map(k => encodeURIComponent(k) + "=" + encodeURIComponent(obj[k]))
.join("&");
}
export function sendMail(data: EmailData) {
const dataUrlEncoded = urlEncodeObject(data);
const opts = {
method: "POST",
headers: {
Authorization: "Basic " + btoa("api:" + MAILGUN_API_KEY),
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": dataUrlEncoded.length.toString()
},
body: dataUrlEncoded,
}
return fetch(`${MAILGUN_API_BASE_URL}/messages`, opts);
}
You will have to set the global environment variables MAILGUN_API_BASE_URL
and MAILGUN_API_KEY
for your worker script using wrangler. The API base url can be put in the environment variables, MAILGUN_API_KEY
should be added as a secret which you can do using the wrangler cli:
wrangler secret put MAILGUN_API_KEY
It will prompt you for the secret value afterwards.
Top comments (1)
I tried this with wrangler running the worker:
[WARNING] The entrypoint src/index.ts has exports like an ES Module, but hasn't defined a default export like a module worker normally would. Building the worker using "service-worker" format...
⬣ Listening at localhost:8787
Total Upload: 0.63 KiB / gzip: 0.38 KiB
✘ [ERROR] Error on remote worker: ParseError: A request to the Cloudflare API (/accounts/57267b529e6d603103c1a98d4e7aa9ae/workers/scripts/contact-us/edge-preview) failed.
(/data/webapps/cloudFlare/workers-site/contact-us/node_modules/wrangler/wrangler-dist/cli.js:117147:17)
at fetchResult
(/data/webapps/cloudFlare/workers-site/contact-us/node_modules/wrangler/wrangler-dist/cli.js:117120:5)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async createPreviewToken
(/data/webapps/cloudFlare/workers-site/contact-us/node_modules/wrangler/wrangler-dist/cli.js:120828:29)
at async createWorkerPreview
(/data/webapps/cloudFlare/workers-site/contact-us/node_modules/wrangler/wrangler-dist/cli.js:120843:17)
at async start
(/data/webapps/cloudFlare/workers-site/contact-us/node_modules/wrangler/wrangler-dist/cli.js:121364:16)
{
text: 'A request to the Cloudflare API
(/accounts/57267b529e6d603103c1a98d4e7aa9ae/workers/scripts/contact-us/edge-preview)
failed.',
notes: [
{
text: 'No event handlers were registered. This script does nothing.\n' +
' [code: 10021]'
}
],
location: undefined,
kind: 'error',
code: 10021
}