https://github.com/jacoblincool/cloudflare-email-kit
The Cloudflare Email Kit is a powerful toolkit designed to handle both incoming and outgoing emails with ease on Cloudflare Workers, providing developers with a modular approach to integrating email functionalities within serverless applications.
https://github.com/jacoblincool/cloudflare-email-kit
cloudflare cloudflare-workers email router workers
Last synced: 1 day ago
JSON representation
The Cloudflare Email Kit is a powerful toolkit designed to handle both incoming and outgoing emails with ease on Cloudflare Workers, providing developers with a modular approach to integrating email functionalities within serverless applications.
- Host: GitHub
- URL: https://github.com/jacoblincool/cloudflare-email-kit
- Owner: JacobLinCool
- License: mit
- Created: 2023-11-04T20:14:50.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-05-03T15:39:54.000Z (6 days ago)
- Last Synced: 2025-05-03T16:46:35.472Z (6 days ago)
- Topics: cloudflare, cloudflare-workers, email, router, workers
- Language: TypeScript
- Homepage: http://jacoblin.cool/cloudflare-email-kit/
- Size: 370 KB
- Stars: 28
- Watchers: 2
- Forks: 1
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Cloudflare Email Kit
The Cloudflare Email Kit is a powerful toolkit designed to handle both incoming and outgoing emails with ease on Cloudflare Workers. It emphasizes ease of use and composability, providing developers with a modular approach to integrating email functionalities within their serverless applications.
## Features
- **User-Friendly Middleware:** Employ an intuitive middleware system that streamlines email processing.
- **Composable Routing:** Craft complex email handling logic with a highly composable EmailRouter.
- **Cloudflare Integrations:** Store emails effortlessly with Cloudflare’s R2 Object Storage and D1 Database support.
- **Workload Management:** Utilize Cloudflare Queues to efficiently distribute email processing tasks.
- **Email Utilities:** Simplify the art of parsing, crafting and sending emails with a set of convenient utilities.## Getting Started
Begin using the Cloudflare Email Kit with a simple installation:
```sh
pnpm install cloudflare-email
```> The `cloudflare-email` package contains the core functionalities of the Cloudflare Email Kit. For additional features, install the packages listed in the documentation.
## Examples
### Router
Navigate the complexities of email routing with customizable rules and actions.
See [examples/router](examples/router/).
See the example code
```ts
import { CATCH_ALL, EmailKit, EmailRouter, REJECT_ALL, SizeGuard, respond } from "cloudflare-email";
import { Backup } from "cloudflare-email-backup";export interface Env {
R2: R2Bucket;
D1: D1Database;
NOTIFICATION_EMAIL: string;
}export default {
async email(message: ForwardableEmailMessage, env: Env, ctx: ExecutionContext): Promise {
const router = new EmailRouter()
// handle auto-sent emails
.match(
(m) => m.isAuto(),
(m) => m.forward(env.NOTIFICATION_EMAIL),
)
// use a sub-router to handle subdomain emails
.match(
/@test\.csie\.cool$/,
new EmailRouter()
.match(/^admin@/, async (message) => {
const msg = respond(message);
msg.addMessage({
contentType: "text/plain",
data: "Hello, I'm the admin!",
});
await message.reply(msg);
})
.match(
// function matchers are also supported, even async ones which query databases
(m) => m.from.length % 2 === 0,
async (message) => {
const msg = respond(message);
msg.addMessage({
contentType: "text/plain",
data: `The length of your email address is even!`,
});
await message.reply(msg);
},
)
.match(CATCH_ALL, async (message) => {
const msg = respond(message);
msg.addMessage({
contentType: "text/plain",
data: "The length of your email address is odd!",
});
await message.reply(msg);
}),
)
.match(...REJECT_ALL("Your email is rejected! :P"));const kit = new EmailKit()
.use(new SizeGuard(10 * 1024 * 1024))
.use(
new Backup({
bucket: env.R2,
prefix: "backup",
database: env.D1,
table: "emails",
}),
)
.use(router);await kit.process(message);
},
};
```### Parser
Effortlessly parse and interact with email content and attachments.
See [examples/parser](examples/parser/).
See the example code
```ts
import { EmailKit, SizeGuard, respond } from "cloudflare-email";
import { ParsedContext, Parser } from "cloudflare-email-parser";export interface Env {
R2: R2Bucket;
}export default {
async email(message: ForwardableEmailMessage, env: Env): Promise {
const kit = new EmailKit()
.use(new SizeGuard(10 * 1024 * 1024))
.use(new Parser())
.use({
name: "save-attechments",
async handle(ctx: ParsedContext) {
for (const attachment of ctx.parsed.attachments) {
const { filename, content, mimeType } = attachment;
const key = `attachments/${ctx.parsed.messageId}/${filename}`;
console.log(`Saving attachment ${filename} to ${key} ...`);
await env.R2.put(key, content, {
customMetadata: { mime: mimeType },
});
console.log(`Saved attachment ${filename} to ${key}.`);
}const res = respond(ctx.message);
res.addMessage({
contentType: "text/plain",
data: `${ctx.parsed.attachments.length} attachments saved.`,
});
await ctx.message.reply(res);
},
});await kit.process(message);
},
};
```### Cloudflare Queues
Leverage Cloudflare Queues to get more CPU time (15 minutes instead of 30 seconds) to process emails.
See [examples/cloudflare-queues](examples/cloudflare-queues/).
See the example code
```ts
import { EmailKit, EmailRouter, SizeGuard, respond } from "cloudflare-email";
import { Backup } from "cloudflare-email-backup";
import { EmailQueue, EmailQueueMessage } from "cloudflare-email-queue";export interface Env {
R2: R2Bucket;
D1: D1Database;
FIRST: Queue;
SECOND: Queue;
}export default {
// receive email, perform size check, and enqueue it to the coresponding queue
async email(message: ForwardableEmailMessage, env: Env): Promise {
const router = new EmailRouter()
.match(/@first\.csie\.cool$/, new EmailQueue(env.FIRST))
.match(/@second\.csie\.cool$/, new EmailQueue(env.SECOND));const kit = new EmailKit()
.use(new SizeGuard(10 * 1024 * 1024))
.use(
new Backup({
bucket: env.R2,
prefix: "backup",
database: env.D1,
table: "emails",
}),
)
.use(router);await kit.process(message);
},
// checkout the queued messages and process them
async queue(batch: MessageBatch, env: Env) {
const backup = new Backup({
bucket: env.R2,
prefix: "backup",
database: env.D1,
table: "emails",
});// retrieve and re-construct the message
const retrieve = async (m: EmailQueueMessage) => {
const raw = await backup.retrieve(m.message_id, m.from, m.to);
if (!raw) {
throw new Error("Cannot retrieve message.");
}
return EmailQueue.retrieve(m, raw);
};if (batch.queue === "kit-example-first-email-queue") {
for (const m of batch.messages) {
const message = await retrieve(m.body);await new EmailKit()
.use(async (ctx) => {
const reply = respond(ctx.message);
reply.addMessage({
contentType: "text/plain",
data: "Greeting from first domain.",
});
await ctx.message.reply(reply);
})
.handle({ message });m.ack();
}
} else if (batch.queue === "kit-example-second-email-queue") {
for (const m of batch.messages) {
const message = await retrieve(m.body);await new EmailKit()
.use(async (ctx) => {
const reply = respond(ctx.message);
reply.addMessage({
contentType: "text/plain",
data: "Greeting from second domain.",
});await ctx.message.reply(reply);
})
.handle({ message });m.ack();
}
}
},
};
```## Documentation
Dive into the full potential of the Cloudflare Email Kit by visiting the [Documentation](https://jacoblincool.github.io/cloudflare-email-kit).
## Join the Community
We welcome your contributions! To collaborate, fork the repository and submit your pull requests.
## Need Help?
Encountered a snag? Have a suggestion? [Open an issue on the GitHub issues page](https://github.com/JacobLinCool/cloudflare-email-kit/issues/new).