cloudflare-email-router
Version:
Support advanced email routing on Cloudflare Workers.
97 lines (95 loc) • 2.86 kB
JavaScript
// src/router.ts
var _router_counter = 0;
var EmailRouter = class _EmailRouter {
constructor(config = { name: `router-${_router_counter++}` }) {
this.config = config;
}
rules = [];
get name() {
return this.config.name;
}
/**
* Matches the given email message against the defined rules and returns the first matching rule.
* @param message The email message to match against the rules.
* @returns The first matching rule or null if no rule matches the message.
*/
async checkout(message) {
for (const rule of this.rules) {
const matched = await rule.match(message);
if (matched) {
return rule;
}
}
return null;
}
/**
* Processes the email message and returns the result of the matching route handle.
* @param ctx - The email context object.
* @param next - The next middleware function.
* @returns An object containing the matched route handle or null if no match was found.
*/
async process(ctx, next) {
const matched = await this.checkout(ctx.message);
if (matched) {
await matched.handle(ctx, next || (() => Promise.resolve()));
return { matched };
}
return { matched: null };
}
async handle(ctx, next) {
await this.process(ctx, next);
}
match(matcher, handler_subrouter) {
let name = "";
if (typeof matcher === "string") {
name = matcher;
matcher = (message) => new RegExp(`^${matcher}$`).test(message.to);
} else if (matcher instanceof RegExp) {
const regex = matcher;
name = regex.source;
matcher = (message) => regex.test(message.to);
} else if (typeof matcher === "function") {
name = matcher.name;
}
if (handler_subrouter instanceof _EmailRouter) {
const precondition = matcher;
const subrouter = handler_subrouter;
name = `${name} (${subrouter.config.name})`;
matcher = async (message) => {
if (await precondition(message)) {
return subrouter.checkout(message) !== null;
}
return false;
};
} else if (typeof handler_subrouter === "function") {
const handler = handler_subrouter;
const anonymous_middleware = {
name: handler_subrouter.name,
async handle(ctx, next) {
await handler(ctx.message);
await next();
}
};
handler_subrouter = anonymous_middleware;
}
this.rules.push({
name,
match: matcher,
handle: handler_subrouter.handle.bind(handler_subrouter)
});
return this;
}
};
// src/utils.ts
var CATCH_ALL = () => true;
function REJECT_ALL(reason = "Sorry, we don't accept emails to this address.") {
return [CATCH_ALL, (message) => {
var _a;
return (_a = message.reject) == null ? void 0 : _a.call(message, reason);
}];
}
export {
CATCH_ALL,
EmailRouter,
REJECT_ALL
};