This commit is contained in:
2025-05-28 11:39:54 +00:00
parent 0e610cba16
commit 77ff948404
10 changed files with 677 additions and 344 deletions

View File

@ -0,0 +1,60 @@
import * as plugins from '../../plugins.js';
import { EventEmitter } from 'node:events';
import type { IEmailRoute, IEmailMatch, IEmailAction, IEmailContext } from './interfaces.js';
import type { Email } from '../core/classes.email.js';
/**
* Email router that evaluates routes and determines actions
*/
export class EmailRouter extends EventEmitter {
private routes: IEmailRoute[];
private patternCache: Map<string, boolean> = new Map();
/**
* Create a new email router
* @param routes Array of email routes
*/
constructor(routes: IEmailRoute[]) {
super();
this.routes = this.sortRoutesByPriority(routes);
}
/**
* Sort routes by priority (higher priority first)
* @param routes Routes to sort
* @returns Sorted routes
*/
private sortRoutesByPriority(routes: IEmailRoute[]): IEmailRoute[] {
return [...routes].sort((a, b) => {
const priorityA = a.priority ?? 0;
const priorityB = b.priority ?? 0;
return priorityB - priorityA; // Higher priority first
});
}
/**
* Get all configured routes
* @returns Array of routes
*/
public getRoutes(): IEmailRoute[] {
return [...this.routes];
}
/**
* Update routes
* @param routes New routes
*/
public updateRoutes(routes: IEmailRoute[]): void {
this.routes = this.sortRoutesByPriority(routes);
this.clearCache();
this.emit('routesUpdated', this.routes);
}
/**
* Clear the pattern cache
*/
public clearCache(): void {
this.patternCache.clear();
this.emit('cacheCleared');
}
}

View File

@ -0,0 +1,101 @@
import type { Email } from '../core/classes.email.js';
import type { IExtendedSmtpSession } from '../delivery/smtpserver/interfaces.js';
/**
* Route configuration for email routing
*/
export interface IEmailRoute {
/** Route identifier */
name: string;
/** Order of evaluation (higher priority evaluated first, default: 0) */
priority?: number;
/** Conditions to match */
match: IEmailMatch;
/** Action to take when matched */
action: IEmailAction;
}
/**
* Match criteria for email routing
*/
export interface IEmailMatch {
/** Email patterns to match recipients: "*@example.com", "admin@*" */
recipients?: string | string[];
/** Email patterns to match senders */
senders?: string | string[];
/** IP addresses or CIDR ranges to match */
clientIp?: string | string[];
/** Require authentication status */
authenticated?: boolean;
// Optional advanced matching
/** Headers to match */
headers?: Record<string, string | RegExp>;
/** Message size range */
sizeRange?: { min?: number; max?: number };
/** Subject line patterns */
subject?: string | RegExp;
/** Has attachments */
hasAttachments?: boolean;
}
/**
* Action to take when route matches
*/
export interface IEmailAction {
/** Type of action to perform */
type: 'forward' | 'deliver' | 'reject' | 'process';
/** Forward action configuration */
forward?: {
/** Target host to forward to */
host: string;
/** Target port (default: 25) */
port?: number;
/** Authentication credentials */
auth?: {
user: string;
pass: string;
};
/** Preserve original headers */
preserveHeaders?: boolean;
/** Additional headers to add */
addHeaders?: Record<string, string>;
};
/** Reject action configuration */
reject?: {
/** SMTP response code */
code: number;
/** SMTP response message */
message: string;
};
/** Process action configuration */
process?: {
/** Enable content scanning */
scan?: boolean;
/** Enable DKIM signing */
dkim?: boolean;
/** Delivery queue priority */
queue?: 'normal' | 'priority' | 'bulk';
};
/** Delivery options (applies to forward/process/deliver) */
delivery?: {
/** Rate limit (messages per minute) */
rateLimit?: number;
/** Number of retry attempts */
retries?: number;
};
}
/**
* Context for route evaluation
*/
export interface IEmailContext {
/** The email being routed */
email: Email;
/** The SMTP session */
session: IExtendedSmtpSession;
}