Implementing an Email Delivery Service with Cloudflare Workers
Tags: email, javascript, tutorial, programming
Published: 2024-06-17 18:28:59

Without using the STMP server or three-party mail forwarding services, only through Cloudflare Workers and Email Routing, it is free to implement a mail delivery service.

Cloudflare Workers and Email Routing are both on a free plan, which is more than enough for individual users.

## Prepare
Register for a Cloudflare account

## Enable Cloudflare Email Routing
Refer to the official document to enable it.

## Deploy Workers
* clone/download https://github.com/alivefree/cf-email-workers
``` javascript 
 import { Hono } from "hono"
 import { cors } from "hono/cors"
 import { EmailMessage } from "cloudflare:email"
 import { createMimeMessage } from "mimetext"
 
 const worker = new Hono();

 // cors 
 worker.use('*', (c, next) => {
   const origins = c.env.ALLOWED_ORIGINS == '*' ? '*' : c.env.ALLOWED_ORIGINS.split(',');
   const corsMiddleware = cors(origins);
   return corsMiddleware(c, next);
 });

 // Mail sending interface, can be modified to any api you want
 worker.post('/send', async (c) => {
   const text = await c.req.text();
   const body = JSON.parse(text);
   if (!body['subject'] || !body['body']) {
     c.status(400)
     return c.json({
         "status": "error",
         "message": "Missing subject or body"
     })
   }
 
   const msg = createMimeMessage()
   msg.setSender({ name: c.env.SENDER_NAME, addr: c.env.SENDER_ADDRESS })
   msg.setRecipient(c.env.RECIPIENT_ADDRESS)
   msg.setSubject(body['subject'])
   msg.addMessage({
       contentType: 'text/html',
       data: body['body']
   })
 
   var message = new EmailMessage(
       c.env.SENDER_ADDRESS,
       c.env.RECIPIENT_ADDRESS,
       msg.asRaw()
   );
 
   try {
       // The SEB here comes from the send_email configuration in wrangler.toml
       await c.env.SEB.send(message)
   } catch (e) {
       c.status(500)
       return c.json({
           "status": "error",
           "message": "Email failed to send",
           "error_details": e.message
       });
   }
 
   return c.json({
       "status": "success",
       "message": "Email sent successfully"
   });
   
 });
 
 export default worker;
```

* Modifying Custom Configurations(wrangler.toml)
``` yaml
 # The name configuration here corresponds to c.env.SEB.send in the code, which needs to be synchronized.
 send_email = [
     {type = "send_email", name = "SEB", destination_address = "xxx"},
 ]
 
 [vars]
 ALLOWED_ORIGINS = "*"
 RECIPIENT_ADDRESS = "*"
 SENDER_ADDRESS = "*"
 SENDER_NAME = "*"
```

* deploy to Cloudflare Workers
```bash
$ npm install -g wrangler
$ wrangler login
$ wrangler deploy
```

## Call
After successful deployment, you can call the API to send emails to other projects
API: worker domain/API
``` javascript
fetch('https://example.workers.dev/send', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    subject: 'subject',
    body: 'email content'
  })
})
```
You can modify the content of the body to customize the email content and make it more aesthetically pleasing.

The Email Worker code deployed in this article has been opened on [GitHub](https://github.com/alivefree/cf-email-workers).