start the path to rust
This commit is contained in:
79
dist_ts/mail/routing/classes.dns.manager.d.ts
vendored
Normal file
79
dist_ts/mail/routing/classes.dns.manager.d.ts
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
import type { IEmailDomainConfig } from './interfaces.js';
|
||||
/** External DcRouter interface shape used by DnsManager */
|
||||
interface IDcRouterLike {
|
||||
storageManager: IStorageManagerLike;
|
||||
dnsServer?: any;
|
||||
options?: {
|
||||
dnsNsDomains?: string[];
|
||||
dnsScopes?: string[];
|
||||
};
|
||||
}
|
||||
/** External StorageManager interface shape used by DnsManager */
|
||||
interface IStorageManagerLike {
|
||||
get(key: string): Promise<string | null>;
|
||||
set(key: string, value: string): Promise<void>;
|
||||
}
|
||||
/**
|
||||
* DNS validation result
|
||||
*/
|
||||
export interface IDnsValidationResult {
|
||||
valid: boolean;
|
||||
errors: string[];
|
||||
warnings: string[];
|
||||
requiredChanges: string[];
|
||||
}
|
||||
/**
|
||||
* Manages DNS configuration for email domains
|
||||
* Handles both validation and creation of DNS records
|
||||
*/
|
||||
export declare class DnsManager {
|
||||
private dcRouter;
|
||||
private storageManager;
|
||||
constructor(dcRouter: IDcRouterLike);
|
||||
/**
|
||||
* Validate all domain configurations
|
||||
*/
|
||||
validateAllDomains(domainConfigs: IEmailDomainConfig[]): Promise<Map<string, IDnsValidationResult>>;
|
||||
/**
|
||||
* Validate a single domain configuration
|
||||
*/
|
||||
validateDomain(config: IEmailDomainConfig): Promise<IDnsValidationResult>;
|
||||
/**
|
||||
* Validate forward mode configuration
|
||||
*/
|
||||
private validateForwardMode;
|
||||
/**
|
||||
* Validate internal DNS mode configuration
|
||||
*/
|
||||
private validateInternalDnsMode;
|
||||
/**
|
||||
* Validate external DNS mode configuration
|
||||
*/
|
||||
private validateExternalDnsMode;
|
||||
/**
|
||||
* Check DNS records for a domain
|
||||
*/
|
||||
private checkDnsRecords;
|
||||
/**
|
||||
* Resolve NS records for a domain
|
||||
*/
|
||||
private resolveNs;
|
||||
/**
|
||||
* Get base domain from email domain (e.g., mail.example.com -> example.com)
|
||||
*/
|
||||
private getBaseDomain;
|
||||
/**
|
||||
* Ensure all DNS records are created for configured domains
|
||||
* This is the main entry point for DNS record management
|
||||
*/
|
||||
ensureDnsRecords(domainConfigs: IEmailDomainConfig[], dkimCreator?: any): Promise<void>;
|
||||
/**
|
||||
* Create DNS records for internal-dns mode domains
|
||||
*/
|
||||
private createInternalDnsRecords;
|
||||
/**
|
||||
* Create DKIM DNS records for all domains
|
||||
*/
|
||||
private createDkimRecords;
|
||||
}
|
||||
export {};
|
||||
415
dist_ts/mail/routing/classes.dns.manager.js
Normal file
415
dist_ts/mail/routing/classes.dns.manager.js
Normal file
File diff suppressed because one or more lines are too long
165
dist_ts/mail/routing/classes.dnsmanager.d.ts
vendored
Normal file
165
dist_ts/mail/routing/classes.dnsmanager.d.ts
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import { DKIMCreator } from '../security/classes.dkimcreator.js';
|
||||
/**
|
||||
* Interface for DNS record information
|
||||
*/
|
||||
export interface IDnsRecord {
|
||||
name: string;
|
||||
type: string;
|
||||
value: string;
|
||||
ttl?: number;
|
||||
dnsSecEnabled?: boolean;
|
||||
}
|
||||
/**
|
||||
* Interface for DNS lookup options
|
||||
*/
|
||||
export interface IDnsLookupOptions {
|
||||
/** Cache time to live in milliseconds, 0 to disable caching */
|
||||
cacheTtl?: number;
|
||||
/** Timeout for DNS queries in milliseconds */
|
||||
timeout?: number;
|
||||
}
|
||||
/**
|
||||
* Interface for DNS verification result
|
||||
*/
|
||||
export interface IDnsVerificationResult {
|
||||
record: string;
|
||||
found: boolean;
|
||||
valid: boolean;
|
||||
value?: string;
|
||||
expectedValue?: string;
|
||||
error?: string;
|
||||
}
|
||||
/**
|
||||
* Manager for DNS-related operations, including record lookups, verification, and generation
|
||||
*/
|
||||
export declare class DNSManager {
|
||||
dkimCreator: DKIMCreator;
|
||||
private cache;
|
||||
private defaultOptions;
|
||||
constructor(dkimCreatorArg: DKIMCreator, options?: IDnsLookupOptions);
|
||||
/**
|
||||
* Lookup MX records for a domain
|
||||
* @param domain Domain to look up
|
||||
* @param options Lookup options
|
||||
* @returns Array of MX records sorted by priority
|
||||
*/
|
||||
lookupMx(domain: string, options?: IDnsLookupOptions): Promise<plugins.dns.MxRecord[]>;
|
||||
/**
|
||||
* Lookup TXT records for a domain
|
||||
* @param domain Domain to look up
|
||||
* @param options Lookup options
|
||||
* @returns Array of TXT records
|
||||
*/
|
||||
lookupTxt(domain: string, options?: IDnsLookupOptions): Promise<string[][]>;
|
||||
/**
|
||||
* Find specific TXT record by subdomain and prefix
|
||||
* @param domain Base domain
|
||||
* @param subdomain Subdomain prefix (e.g., "dkim._domainkey")
|
||||
* @param prefix Record prefix to match (e.g., "v=DKIM1")
|
||||
* @param options Lookup options
|
||||
* @returns Matching TXT record or null if not found
|
||||
*/
|
||||
findTxtRecord(domain: string, subdomain?: string, prefix?: string, options?: IDnsLookupOptions): Promise<string | null>;
|
||||
/**
|
||||
* Verify if a domain has a valid SPF record
|
||||
* @param domain Domain to verify
|
||||
* @returns Verification result
|
||||
*/
|
||||
verifySpfRecord(domain: string): Promise<IDnsVerificationResult>;
|
||||
/**
|
||||
* Verify if a domain has a valid DKIM record
|
||||
* @param domain Domain to verify
|
||||
* @param selector DKIM selector (usually "mta" in our case)
|
||||
* @returns Verification result
|
||||
*/
|
||||
verifyDkimRecord(domain: string, selector?: string): Promise<IDnsVerificationResult>;
|
||||
/**
|
||||
* Verify if a domain has a valid DMARC record
|
||||
* @param domain Domain to verify
|
||||
* @returns Verification result
|
||||
*/
|
||||
verifyDmarcRecord(domain: string): Promise<IDnsVerificationResult>;
|
||||
/**
|
||||
* Check all email authentication records (SPF, DKIM, DMARC) for a domain
|
||||
* @param domain Domain to check
|
||||
* @param dkimSelector DKIM selector
|
||||
* @returns Object with verification results for each record type
|
||||
*/
|
||||
verifyEmailAuthRecords(domain: string, dkimSelector?: string): Promise<{
|
||||
spf: IDnsVerificationResult;
|
||||
dkim: IDnsVerificationResult;
|
||||
dmarc: IDnsVerificationResult;
|
||||
}>;
|
||||
/**
|
||||
* Generate a recommended SPF record for a domain
|
||||
* @param domain Domain name
|
||||
* @param options Configuration options for the SPF record
|
||||
* @returns Generated SPF record
|
||||
*/
|
||||
generateSpfRecord(domain: string, options?: {
|
||||
includeMx?: boolean;
|
||||
includeA?: boolean;
|
||||
includeIps?: string[];
|
||||
includeSpf?: string[];
|
||||
policy?: 'none' | 'neutral' | 'softfail' | 'fail' | 'reject';
|
||||
}): IDnsRecord;
|
||||
/**
|
||||
* Generate a recommended DMARC record for a domain
|
||||
* @param domain Domain name
|
||||
* @param options Configuration options for the DMARC record
|
||||
* @returns Generated DMARC record
|
||||
*/
|
||||
generateDmarcRecord(domain: string, options?: {
|
||||
policy?: 'none' | 'quarantine' | 'reject';
|
||||
subdomainPolicy?: 'none' | 'quarantine' | 'reject';
|
||||
pct?: number;
|
||||
rua?: string;
|
||||
ruf?: string;
|
||||
daysInterval?: number;
|
||||
}): IDnsRecord;
|
||||
/**
|
||||
* Save DNS record recommendations to a file
|
||||
* @param domain Domain name
|
||||
* @param records DNS records to save
|
||||
*/
|
||||
saveDnsRecommendations(domain: string, records: IDnsRecord[]): Promise<void>;
|
||||
/**
|
||||
* Get cache key value
|
||||
* @param key Cache key
|
||||
* @returns Cached value or undefined if not found or expired
|
||||
*/
|
||||
private getFromCache;
|
||||
/**
|
||||
* Set cache key value
|
||||
* @param key Cache key
|
||||
* @param data Data to cache
|
||||
* @param ttl TTL in milliseconds
|
||||
*/
|
||||
private setInCache;
|
||||
/**
|
||||
* Clear the DNS cache
|
||||
* @param key Optional specific key to clear, or all cache if not provided
|
||||
*/
|
||||
clearCache(key?: string): void;
|
||||
/**
|
||||
* Promise-based wrapper for dns.resolveMx
|
||||
* @param domain Domain to resolve
|
||||
* @param timeout Timeout in milliseconds
|
||||
* @returns Promise resolving to MX records
|
||||
*/
|
||||
private dnsResolveMx;
|
||||
/**
|
||||
* Promise-based wrapper for dns.resolveTxt
|
||||
* @param domain Domain to resolve
|
||||
* @param timeout Timeout in milliseconds
|
||||
* @returns Promise resolving to TXT records
|
||||
*/
|
||||
private dnsResolveTxt;
|
||||
/**
|
||||
* Generate all recommended DNS records for proper email authentication
|
||||
* @param domain Domain to generate records for
|
||||
* @returns Array of recommended DNS records
|
||||
*/
|
||||
generateAllRecommendedRecords(domain: string): Promise<IDnsRecord[]>;
|
||||
}
|
||||
431
dist_ts/mail/routing/classes.dnsmanager.js
Normal file
431
dist_ts/mail/routing/classes.dnsmanager.js
Normal file
File diff suppressed because one or more lines are too long
54
dist_ts/mail/routing/classes.domain.registry.d.ts
vendored
Normal file
54
dist_ts/mail/routing/classes.domain.registry.d.ts
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import type { IEmailDomainConfig } from './interfaces.js';
|
||||
/**
|
||||
* Registry for email domain configurations
|
||||
* Provides fast lookups and validation for domains
|
||||
*/
|
||||
export declare class DomainRegistry {
|
||||
private domains;
|
||||
private defaults;
|
||||
constructor(domainConfigs: IEmailDomainConfig[], defaults?: {
|
||||
dnsMode?: 'forward' | 'internal-dns' | 'external-dns';
|
||||
dkim?: IEmailDomainConfig['dkim'];
|
||||
rateLimits?: IEmailDomainConfig['rateLimits'];
|
||||
});
|
||||
/**
|
||||
* Get default DKIM configuration
|
||||
*/
|
||||
private getDefaultDkimConfig;
|
||||
/**
|
||||
* Apply defaults to a domain configuration
|
||||
*/
|
||||
private applyDefaults;
|
||||
/**
|
||||
* Check if a domain is registered
|
||||
*/
|
||||
isDomainRegistered(domain: string): boolean;
|
||||
/**
|
||||
* Check if an email address belongs to a registered domain
|
||||
*/
|
||||
isEmailRegistered(email: string): boolean;
|
||||
/**
|
||||
* Get domain configuration
|
||||
*/
|
||||
getDomainConfig(domain: string): IEmailDomainConfig | undefined;
|
||||
/**
|
||||
* Get domain configuration for an email address
|
||||
*/
|
||||
getEmailDomainConfig(email: string): IEmailDomainConfig | undefined;
|
||||
/**
|
||||
* Extract domain from email address
|
||||
*/
|
||||
private extractDomain;
|
||||
/**
|
||||
* Get all registered domains
|
||||
*/
|
||||
getAllDomains(): string[];
|
||||
/**
|
||||
* Get all domain configurations
|
||||
*/
|
||||
getAllConfigs(): IEmailDomainConfig[];
|
||||
/**
|
||||
* Get domains by DNS mode
|
||||
*/
|
||||
getDomainsByMode(mode: 'forward' | 'internal-dns' | 'external-dns'): IEmailDomainConfig[];
|
||||
}
|
||||
119
dist_ts/mail/routing/classes.domain.registry.js
Normal file
119
dist_ts/mail/routing/classes.domain.registry.js
Normal file
@@ -0,0 +1,119 @@
|
||||
import { logger } from '../../logger.js';
|
||||
/**
|
||||
* Registry for email domain configurations
|
||||
* Provides fast lookups and validation for domains
|
||||
*/
|
||||
export class DomainRegistry {
|
||||
domains = new Map();
|
||||
defaults;
|
||||
constructor(domainConfigs, defaults) {
|
||||
// Set defaults
|
||||
this.defaults = {
|
||||
dnsMode: defaults?.dnsMode || 'external-dns',
|
||||
...this.getDefaultDkimConfig(),
|
||||
...defaults?.dkim,
|
||||
rateLimits: defaults?.rateLimits
|
||||
};
|
||||
// Process and store domain configurations
|
||||
for (const config of domainConfigs) {
|
||||
const processedConfig = this.applyDefaults(config);
|
||||
this.domains.set(config.domain.toLowerCase(), processedConfig);
|
||||
logger.log('info', `Registered domain: ${config.domain} with DNS mode: ${processedConfig.dnsMode}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get default DKIM configuration
|
||||
*/
|
||||
getDefaultDkimConfig() {
|
||||
return {
|
||||
selector: 'default',
|
||||
keySize: 2048,
|
||||
rotateKeys: false,
|
||||
rotationInterval: 90
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Apply defaults to a domain configuration
|
||||
*/
|
||||
applyDefaults(config) {
|
||||
return {
|
||||
...config,
|
||||
dnsMode: config.dnsMode || this.defaults.dnsMode,
|
||||
dkim: {
|
||||
...this.getDefaultDkimConfig(),
|
||||
...this.defaults,
|
||||
...config.dkim
|
||||
},
|
||||
rateLimits: {
|
||||
...this.defaults.rateLimits,
|
||||
...config.rateLimits,
|
||||
outbound: {
|
||||
...this.defaults.rateLimits?.outbound,
|
||||
...config.rateLimits?.outbound
|
||||
},
|
||||
inbound: {
|
||||
...this.defaults.rateLimits?.inbound,
|
||||
...config.rateLimits?.inbound
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Check if a domain is registered
|
||||
*/
|
||||
isDomainRegistered(domain) {
|
||||
return this.domains.has(domain.toLowerCase());
|
||||
}
|
||||
/**
|
||||
* Check if an email address belongs to a registered domain
|
||||
*/
|
||||
isEmailRegistered(email) {
|
||||
const domain = this.extractDomain(email);
|
||||
if (!domain)
|
||||
return false;
|
||||
return this.isDomainRegistered(domain);
|
||||
}
|
||||
/**
|
||||
* Get domain configuration
|
||||
*/
|
||||
getDomainConfig(domain) {
|
||||
return this.domains.get(domain.toLowerCase());
|
||||
}
|
||||
/**
|
||||
* Get domain configuration for an email address
|
||||
*/
|
||||
getEmailDomainConfig(email) {
|
||||
const domain = this.extractDomain(email);
|
||||
if (!domain)
|
||||
return undefined;
|
||||
return this.getDomainConfig(domain);
|
||||
}
|
||||
/**
|
||||
* Extract domain from email address
|
||||
*/
|
||||
extractDomain(email) {
|
||||
const parts = email.toLowerCase().split('@');
|
||||
if (parts.length !== 2)
|
||||
return null;
|
||||
return parts[1];
|
||||
}
|
||||
/**
|
||||
* Get all registered domains
|
||||
*/
|
||||
getAllDomains() {
|
||||
return Array.from(this.domains.keys());
|
||||
}
|
||||
/**
|
||||
* Get all domain configurations
|
||||
*/
|
||||
getAllConfigs() {
|
||||
return Array.from(this.domains.values());
|
||||
}
|
||||
/**
|
||||
* Get domains by DNS mode
|
||||
*/
|
||||
getDomainsByMode(mode) {
|
||||
return Array.from(this.domains.values()).filter(config => config.dnsMode === mode);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kb21haW4ucmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL3JvdXRpbmcvY2xhc3Nlcy5kb21haW4ucmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXpDOzs7R0FHRztBQUNILE1BQU0sT0FBTyxjQUFjO0lBQ2pCLE9BQU8sR0FBb0MsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNyRCxRQUFRLENBR2Q7SUFFRixZQUNFLGFBQW1DLEVBQ25DLFFBSUM7UUFFRCxlQUFlO1FBQ2YsSUFBSSxDQUFDLFFBQVEsR0FBRztZQUNkLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxJQUFJLGNBQWM7WUFDNUMsR0FBRyxJQUFJLENBQUMsb0JBQW9CLEVBQUU7WUFDOUIsR0FBRyxRQUFRLEVBQUUsSUFBSTtZQUNqQixVQUFVLEVBQUUsUUFBUSxFQUFFLFVBQVU7U0FDakMsQ0FBQztRQUVGLDBDQUEwQztRQUMxQyxLQUFLLE1BQU0sTUFBTSxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ25DLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbkQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFBRSxlQUFlLENBQUMsQ0FBQztZQUMvRCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxzQkFBc0IsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLGVBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3RHLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxvQkFBb0I7UUFDMUIsT0FBTztZQUNMLFFBQVEsRUFBRSxTQUFTO1lBQ25CLE9BQU8sRUFBRSxJQUFJO1lBQ2IsVUFBVSxFQUFFLEtBQUs7WUFDakIsZ0JB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
|
||||
64
dist_ts/mail/routing/classes.email.config.d.ts
vendored
Normal file
64
dist_ts/mail/routing/classes.email.config.d.ts
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { EmailProcessingMode } from '../delivery/interfaces.js';
|
||||
export type { EmailProcessingMode };
|
||||
/**
|
||||
* Domain rule interface for pattern-based routing
|
||||
*/
|
||||
export interface IDomainRule {
|
||||
pattern: string;
|
||||
mode: EmailProcessingMode;
|
||||
target?: {
|
||||
server: string;
|
||||
port?: number;
|
||||
useTls?: boolean;
|
||||
authentication?: {
|
||||
user?: string;
|
||||
pass?: string;
|
||||
};
|
||||
};
|
||||
mtaOptions?: IMtaOptions;
|
||||
contentScanning?: boolean;
|
||||
scanners?: IContentScanner[];
|
||||
transformations?: ITransformation[];
|
||||
rateLimits?: {
|
||||
maxMessagesPerMinute?: number;
|
||||
maxRecipientsPerMessage?: number;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* MTA options interface
|
||||
*/
|
||||
export interface IMtaOptions {
|
||||
domain?: string;
|
||||
allowLocalDelivery?: boolean;
|
||||
localDeliveryPath?: string;
|
||||
dkimSign?: boolean;
|
||||
dkimOptions?: {
|
||||
domainName: string;
|
||||
keySelector: string;
|
||||
privateKey?: string;
|
||||
};
|
||||
smtpBanner?: string;
|
||||
maxConnections?: number;
|
||||
connTimeout?: number;
|
||||
spoolDir?: string;
|
||||
}
|
||||
/**
|
||||
* Content scanner interface
|
||||
*/
|
||||
export interface IContentScanner {
|
||||
type: 'spam' | 'virus' | 'attachment';
|
||||
threshold?: number;
|
||||
action: 'tag' | 'reject';
|
||||
blockedExtensions?: string[];
|
||||
}
|
||||
/**
|
||||
* Transformation interface
|
||||
*/
|
||||
export interface ITransformation {
|
||||
type: string;
|
||||
header?: string;
|
||||
value?: string;
|
||||
domains?: string[];
|
||||
append?: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
2
dist_ts/mail/routing/classes.email.config.js
Normal file
2
dist_ts/mail/routing/classes.email.config.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5lbWFpbC5jb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL3JvdXRpbmcvY2xhc3Nlcy5lbWFpbC5jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
|
||||
171
dist_ts/mail/routing/classes.email.router.d.ts
vendored
Normal file
171
dist_ts/mail/routing/classes.email.router.d.ts
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
import { EventEmitter } from 'node:events';
|
||||
import type { IEmailRoute, IEmailContext } from './interfaces.js';
|
||||
/**
|
||||
* Email router that evaluates routes and determines actions
|
||||
*/
|
||||
export declare class EmailRouter extends EventEmitter {
|
||||
private routes;
|
||||
private patternCache;
|
||||
private storageManager?;
|
||||
private persistChanges;
|
||||
/**
|
||||
* Create a new email router
|
||||
* @param routes Array of email routes
|
||||
* @param options Router options
|
||||
*/
|
||||
constructor(routes: IEmailRoute[], options?: {
|
||||
storageManager?: any;
|
||||
persistChanges?: boolean;
|
||||
});
|
||||
/**
|
||||
* Sort routes by priority (higher priority first)
|
||||
* @param routes Routes to sort
|
||||
* @returns Sorted routes
|
||||
*/
|
||||
private sortRoutesByPriority;
|
||||
/**
|
||||
* Get all configured routes
|
||||
* @returns Array of routes
|
||||
*/
|
||||
getRoutes(): IEmailRoute[];
|
||||
/**
|
||||
* Update routes
|
||||
* @param routes New routes
|
||||
* @param persist Whether to persist changes (defaults to persistChanges setting)
|
||||
*/
|
||||
updateRoutes(routes: IEmailRoute[], persist?: boolean): Promise<void>;
|
||||
/**
|
||||
* Set routes (alias for updateRoutes)
|
||||
* @param routes New routes
|
||||
* @param persist Whether to persist changes
|
||||
*/
|
||||
setRoutes(routes: IEmailRoute[], persist?: boolean): Promise<void>;
|
||||
/**
|
||||
* Clear the pattern cache
|
||||
*/
|
||||
clearCache(): void;
|
||||
/**
|
||||
* Evaluate routes and find the first match
|
||||
* @param context Email context
|
||||
* @returns Matched route or null
|
||||
*/
|
||||
evaluateRoutes(context: IEmailContext): Promise<IEmailRoute | null>;
|
||||
/**
|
||||
* Check if a route matches the context
|
||||
* @param route Route to check
|
||||
* @param context Email context
|
||||
* @returns True if route matches
|
||||
*/
|
||||
private matchesRoute;
|
||||
/**
|
||||
* Check if email recipients match patterns
|
||||
* @param email Email to check
|
||||
* @param patterns Patterns to match
|
||||
* @returns True if any recipient matches
|
||||
*/
|
||||
private matchesRecipients;
|
||||
/**
|
||||
* Check if email sender matches patterns
|
||||
* @param email Email to check
|
||||
* @param patterns Patterns to match
|
||||
* @returns True if sender matches
|
||||
*/
|
||||
private matchesSenders;
|
||||
/**
|
||||
* Check if client IP matches patterns
|
||||
* @param context Email context
|
||||
* @param patterns IP patterns to match
|
||||
* @returns True if IP matches
|
||||
*/
|
||||
private matchesClientIp;
|
||||
/**
|
||||
* Check if email headers match patterns
|
||||
* @param email Email to check
|
||||
* @param headerPatterns Header patterns to match
|
||||
* @returns True if headers match
|
||||
*/
|
||||
private matchesHeaders;
|
||||
/**
|
||||
* Check if email size matches range
|
||||
* @param email Email to check
|
||||
* @param sizeRange Size range to match
|
||||
* @returns True if size is in range
|
||||
*/
|
||||
private matchesSize;
|
||||
/**
|
||||
* Check if email subject matches pattern
|
||||
* @param email Email to check
|
||||
* @param pattern Pattern to match
|
||||
* @returns True if subject matches
|
||||
*/
|
||||
private matchesSubject;
|
||||
/**
|
||||
* Check if a string matches a glob pattern
|
||||
* @param str String to check
|
||||
* @param pattern Glob pattern
|
||||
* @returns True if matches
|
||||
*/
|
||||
private matchesPattern;
|
||||
/**
|
||||
* Convert glob pattern to RegExp
|
||||
* @param pattern Glob pattern
|
||||
* @returns Regular expression
|
||||
*/
|
||||
private globToRegExp;
|
||||
/**
|
||||
* Check if IP is in CIDR range
|
||||
* @param ip IP address to check
|
||||
* @param cidr CIDR notation (e.g., '192.168.0.0/16')
|
||||
* @returns True if IP is in range
|
||||
*/
|
||||
private ipInCidr;
|
||||
/**
|
||||
* Convert IP address to number
|
||||
* @param ip IP address
|
||||
* @returns Number representation
|
||||
*/
|
||||
private ipToNumber;
|
||||
/**
|
||||
* Calculate approximate email size in bytes
|
||||
* @param email Email to measure
|
||||
* @returns Size in bytes
|
||||
*/
|
||||
private calculateEmailSize;
|
||||
/**
|
||||
* Save current routes to storage
|
||||
*/
|
||||
saveRoutes(): Promise<void>;
|
||||
/**
|
||||
* Load routes from storage
|
||||
* @param options Load options
|
||||
*/
|
||||
loadRoutes(options?: {
|
||||
merge?: boolean;
|
||||
replace?: boolean;
|
||||
}): Promise<IEmailRoute[]>;
|
||||
/**
|
||||
* Add a route
|
||||
* @param route Route to add
|
||||
* @param persist Whether to persist changes
|
||||
*/
|
||||
addRoute(route: IEmailRoute, persist?: boolean): Promise<void>;
|
||||
/**
|
||||
* Remove a route by name
|
||||
* @param name Route name
|
||||
* @param persist Whether to persist changes
|
||||
*/
|
||||
removeRoute(name: string, persist?: boolean): Promise<void>;
|
||||
/**
|
||||
* Update a route
|
||||
* @param name Route name
|
||||
* @param route Updated route data
|
||||
* @param persist Whether to persist changes
|
||||
*/
|
||||
updateRoute(name: string, route: IEmailRoute, persist?: boolean): Promise<void>;
|
||||
/**
|
||||
* Get a route by name
|
||||
* @param name Route name
|
||||
* @returns Route or undefined
|
||||
*/
|
||||
getRoute(name: string): IEmailRoute | undefined;
|
||||
}
|
||||
494
dist_ts/mail/routing/classes.email.router.js
Normal file
494
dist_ts/mail/routing/classes.email.router.js
Normal file
File diff suppressed because one or more lines are too long
441
dist_ts/mail/routing/classes.unified.email.server.d.ts
vendored
Normal file
441
dist_ts/mail/routing/classes.unified.email.server.d.ts
vendored
Normal file
@@ -0,0 +1,441 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import { EventEmitter } from 'events';
|
||||
import { DKIMCreator } from '../security/classes.dkimcreator.js';
|
||||
interface IIPWarmupConfig {
|
||||
enabled?: boolean;
|
||||
ips?: string[];
|
||||
[key: string]: any;
|
||||
}
|
||||
interface IReputationMonitorConfig {
|
||||
enabled?: boolean;
|
||||
domains?: string[];
|
||||
[key: string]: any;
|
||||
}
|
||||
import type { IEmailRoute, IEmailDomainConfig } from './interfaces.js';
|
||||
import { Email } from '../core/classes.email.js';
|
||||
import { DomainRegistry } from './classes.domain.registry.js';
|
||||
import { BounceType, BounceCategory } from '../core/classes.bouncemanager.js';
|
||||
import type { SmtpClient } from '../delivery/smtpclient/smtp-client.js';
|
||||
import { MultiModeDeliverySystem } from '../delivery/classes.delivery.system.js';
|
||||
import { UnifiedDeliveryQueue } from '../delivery/classes.delivery.queue.js';
|
||||
import { UnifiedRateLimiter, type IHierarchicalRateLimits } from '../delivery/classes.unified.rate.limiter.js';
|
||||
import type { EmailProcessingMode, ISmtpSession as IBaseSmtpSession } from '../delivery/interfaces.js';
|
||||
/** External DcRouter interface shape used by UnifiedEmailServer */
|
||||
interface DcRouter {
|
||||
storageManager: any;
|
||||
dnsServer?: any;
|
||||
options?: any;
|
||||
}
|
||||
/**
|
||||
* Extended SMTP session interface with route information
|
||||
*/
|
||||
export interface IExtendedSmtpSession extends ISmtpSession {
|
||||
/**
|
||||
* Matched route for this session
|
||||
*/
|
||||
matchedRoute?: IEmailRoute;
|
||||
}
|
||||
/**
|
||||
* Options for the unified email server
|
||||
*/
|
||||
export interface IUnifiedEmailServerOptions {
|
||||
ports: number[];
|
||||
hostname: string;
|
||||
domains: IEmailDomainConfig[];
|
||||
banner?: string;
|
||||
debug?: boolean;
|
||||
useSocketHandler?: boolean;
|
||||
auth?: {
|
||||
required?: boolean;
|
||||
methods?: ('PLAIN' | 'LOGIN' | 'OAUTH2')[];
|
||||
users?: Array<{
|
||||
username: string;
|
||||
password: string;
|
||||
}>;
|
||||
};
|
||||
tls?: {
|
||||
certPath?: string;
|
||||
keyPath?: string;
|
||||
caPath?: string;
|
||||
minVersion?: string;
|
||||
ciphers?: string;
|
||||
};
|
||||
maxMessageSize?: number;
|
||||
maxClients?: number;
|
||||
maxConnections?: number;
|
||||
connectionTimeout?: number;
|
||||
socketTimeout?: number;
|
||||
routes: IEmailRoute[];
|
||||
defaults?: {
|
||||
dnsMode?: 'forward' | 'internal-dns' | 'external-dns';
|
||||
dkim?: IEmailDomainConfig['dkim'];
|
||||
rateLimits?: IEmailDomainConfig['rateLimits'];
|
||||
};
|
||||
outbound?: {
|
||||
maxConnections?: number;
|
||||
connectionTimeout?: number;
|
||||
socketTimeout?: number;
|
||||
retryAttempts?: number;
|
||||
defaultFrom?: string;
|
||||
};
|
||||
rateLimits?: IHierarchicalRateLimits;
|
||||
ipWarmupConfig?: IIPWarmupConfig;
|
||||
reputationMonitorConfig?: IReputationMonitorConfig;
|
||||
}
|
||||
/**
|
||||
* Extended SMTP session interface for UnifiedEmailServer
|
||||
*/
|
||||
export interface ISmtpSession extends IBaseSmtpSession {
|
||||
/**
|
||||
* User information if authenticated
|
||||
*/
|
||||
user?: {
|
||||
username: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
/**
|
||||
* Matched route for this session
|
||||
*/
|
||||
matchedRoute?: IEmailRoute;
|
||||
}
|
||||
/**
|
||||
* Authentication data for SMTP
|
||||
*/
|
||||
import type { ISmtpAuth } from '../delivery/interfaces.js';
|
||||
export type IAuthData = ISmtpAuth;
|
||||
/**
|
||||
* Server statistics
|
||||
*/
|
||||
export interface IServerStats {
|
||||
startTime: Date;
|
||||
connections: {
|
||||
current: number;
|
||||
total: number;
|
||||
};
|
||||
messages: {
|
||||
processed: number;
|
||||
delivered: number;
|
||||
failed: number;
|
||||
};
|
||||
processingTime: {
|
||||
avg: number;
|
||||
max: number;
|
||||
min: number;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Unified email server that handles all email traffic with pattern-based routing
|
||||
*/
|
||||
export declare class UnifiedEmailServer extends EventEmitter {
|
||||
private dcRouter;
|
||||
private options;
|
||||
private emailRouter;
|
||||
domainRegistry: DomainRegistry;
|
||||
private servers;
|
||||
private stats;
|
||||
dkimCreator: DKIMCreator;
|
||||
private ipReputationChecker;
|
||||
private bounceManager;
|
||||
private ipWarmupManager;
|
||||
private senderReputationMonitor;
|
||||
deliveryQueue: UnifiedDeliveryQueue;
|
||||
deliverySystem: MultiModeDeliverySystem;
|
||||
private rateLimiter;
|
||||
private dkimKeys;
|
||||
private smtpClients;
|
||||
constructor(dcRouter: DcRouter, options: IUnifiedEmailServerOptions);
|
||||
/**
|
||||
* Get or create an SMTP client for the given host and port
|
||||
* Uses connection pooling for efficiency
|
||||
*/
|
||||
getSmtpClient(host: string, port?: number): SmtpClient;
|
||||
/**
|
||||
* Start the unified email server
|
||||
*/
|
||||
start(): Promise<void>;
|
||||
/**
|
||||
* Handle a socket from smartproxy in socket-handler mode
|
||||
* @param socket The socket to handle
|
||||
* @param port The port this connection is for (25, 587, 465)
|
||||
*/
|
||||
handleSocket(socket: plugins.net.Socket | plugins.tls.TLSSocket, port: number): Promise<void>;
|
||||
/**
|
||||
* Stop the unified email server
|
||||
*/
|
||||
stop(): Promise<void>;
|
||||
/**
|
||||
* Process email based on routing rules
|
||||
*/
|
||||
processEmailByMode(emailData: Email | Buffer, session: IExtendedSmtpSession): Promise<Email>;
|
||||
/**
|
||||
* Execute action based on route configuration
|
||||
*/
|
||||
private executeAction;
|
||||
/**
|
||||
* Handle forward action
|
||||
*/
|
||||
private handleForwardAction;
|
||||
/**
|
||||
* Handle process action
|
||||
*/
|
||||
private handleProcessAction;
|
||||
/**
|
||||
* Handle deliver action
|
||||
*/
|
||||
private handleDeliverAction;
|
||||
/**
|
||||
* Handle reject action
|
||||
*/
|
||||
private handleRejectAction;
|
||||
/**
|
||||
* Handle email in MTA mode (programmatic processing)
|
||||
*/
|
||||
private _handleMtaMode;
|
||||
/**
|
||||
* Handle email in process mode (store-and-forward with scanning)
|
||||
*/
|
||||
private _handleProcessMode;
|
||||
/**
|
||||
* Get file extension from filename
|
||||
*/
|
||||
private getFileExtension;
|
||||
/**
|
||||
* Set up DKIM configuration for all domains
|
||||
*/
|
||||
private setupDkimForDomains;
|
||||
/**
|
||||
* Apply per-domain rate limits from domain configurations
|
||||
*/
|
||||
private applyDomainRateLimits;
|
||||
/**
|
||||
* Check and rotate DKIM keys if needed
|
||||
*/
|
||||
private checkAndRotateDkimKeys;
|
||||
/**
|
||||
* Generate SmartProxy routes for email ports
|
||||
*/
|
||||
generateProxyRoutes(portMapping?: Record<number, number>): any[];
|
||||
/**
|
||||
* Update server configuration
|
||||
*/
|
||||
updateOptions(options: Partial<IUnifiedEmailServerOptions>): void;
|
||||
/**
|
||||
* Update email routes
|
||||
*/
|
||||
updateEmailRoutes(routes: IEmailRoute[]): void;
|
||||
/**
|
||||
* Get server statistics
|
||||
*/
|
||||
getStats(): IServerStats;
|
||||
/**
|
||||
* Get domain registry
|
||||
*/
|
||||
getDomainRegistry(): DomainRegistry;
|
||||
/**
|
||||
* Update email routes dynamically
|
||||
*/
|
||||
updateRoutes(routes: IEmailRoute[]): void;
|
||||
/**
|
||||
* Send an email through the delivery system
|
||||
* @param email The email to send
|
||||
* @param mode The processing mode to use
|
||||
* @param rule Optional rule to apply
|
||||
* @param options Optional sending options
|
||||
* @returns The ID of the queued email
|
||||
*/
|
||||
sendEmail(email: Email, mode?: EmailProcessingMode, route?: IEmailRoute, options?: {
|
||||
skipSuppressionCheck?: boolean;
|
||||
ipAddress?: string;
|
||||
isTransactional?: boolean;
|
||||
}): Promise<string>;
|
||||
/**
|
||||
* Handle DKIM signing for an email
|
||||
* @param email The email to sign
|
||||
* @param domain The domain to sign with
|
||||
* @param selector The DKIM selector
|
||||
*/
|
||||
private handleDkimSigning;
|
||||
/**
|
||||
* Process a bounce notification email
|
||||
* @param bounceEmail The email containing bounce notification information
|
||||
* @returns Processed bounce record or null if not a bounce
|
||||
*/
|
||||
processBounceNotification(bounceEmail: Email): Promise<boolean>;
|
||||
/**
|
||||
* Process an SMTP failure as a bounce
|
||||
* @param recipient Recipient email that failed
|
||||
* @param smtpResponse SMTP error response
|
||||
* @param options Additional options for bounce processing
|
||||
* @returns Processed bounce record
|
||||
*/
|
||||
processSmtpFailure(recipient: string, smtpResponse: string, options?: {
|
||||
sender?: string;
|
||||
originalEmailId?: string;
|
||||
statusCode?: string;
|
||||
headers?: Record<string, string>;
|
||||
}): Promise<boolean>;
|
||||
/**
|
||||
* Check if an email address is suppressed (has bounced previously)
|
||||
* @param email Email address to check
|
||||
* @returns Whether the email is suppressed
|
||||
*/
|
||||
isEmailSuppressed(email: string): boolean;
|
||||
/**
|
||||
* Get suppression information for an email
|
||||
* @param email Email address to check
|
||||
* @returns Suppression information or null if not suppressed
|
||||
*/
|
||||
getSuppressionInfo(email: string): {
|
||||
reason: string;
|
||||
timestamp: number;
|
||||
expiresAt?: number;
|
||||
} | null;
|
||||
/**
|
||||
* Get bounce history information for an email
|
||||
* @param email Email address to check
|
||||
* @returns Bounce history or null if no bounces
|
||||
*/
|
||||
getBounceHistory(email: string): {
|
||||
lastBounce: number;
|
||||
count: number;
|
||||
type: BounceType;
|
||||
category: BounceCategory;
|
||||
} | null;
|
||||
/**
|
||||
* Get all suppressed email addresses
|
||||
* @returns Array of suppressed email addresses
|
||||
*/
|
||||
getSuppressionList(): string[];
|
||||
/**
|
||||
* Get all hard bounced email addresses
|
||||
* @returns Array of hard bounced email addresses
|
||||
*/
|
||||
getHardBouncedAddresses(): string[];
|
||||
/**
|
||||
* Add an email to the suppression list
|
||||
* @param email Email address to suppress
|
||||
* @param reason Reason for suppression
|
||||
* @param expiresAt Optional expiration time (undefined for permanent)
|
||||
*/
|
||||
addToSuppressionList(email: string, reason: string, expiresAt?: number): void;
|
||||
/**
|
||||
* Remove an email from the suppression list
|
||||
* @param email Email address to remove from suppression
|
||||
*/
|
||||
removeFromSuppressionList(email: string): void;
|
||||
/**
|
||||
* Get the status of IP warmup process
|
||||
* @param ipAddress Optional specific IP to check
|
||||
* @returns Status of IP warmup
|
||||
*/
|
||||
getIPWarmupStatus(ipAddress?: string): any;
|
||||
/**
|
||||
* Add a new IP address to the warmup process
|
||||
* @param ipAddress IP address to add
|
||||
*/
|
||||
addIPToWarmup(ipAddress: string): void;
|
||||
/**
|
||||
* Remove an IP address from the warmup process
|
||||
* @param ipAddress IP address to remove
|
||||
*/
|
||||
removeIPFromWarmup(ipAddress: string): void;
|
||||
/**
|
||||
* Update metrics for an IP in the warmup process
|
||||
* @param ipAddress IP address
|
||||
* @param metrics Metrics to update
|
||||
*/
|
||||
updateIPWarmupMetrics(ipAddress: string, metrics: {
|
||||
openRate?: number;
|
||||
bounceRate?: number;
|
||||
complaintRate?: number;
|
||||
}): void;
|
||||
/**
|
||||
* Check if an IP can send more emails today
|
||||
* @param ipAddress IP address to check
|
||||
* @returns Whether the IP can send more today
|
||||
*/
|
||||
canIPSendMoreToday(ipAddress: string): boolean;
|
||||
/**
|
||||
* Check if an IP can send more emails in the current hour
|
||||
* @param ipAddress IP address to check
|
||||
* @returns Whether the IP can send more this hour
|
||||
*/
|
||||
canIPSendMoreThisHour(ipAddress: string): boolean;
|
||||
/**
|
||||
* Get the best IP to use for sending an email based on warmup status
|
||||
* @param emailInfo Information about the email being sent
|
||||
* @returns Best IP to use or null
|
||||
*/
|
||||
getBestIPForSending(emailInfo: {
|
||||
from: string;
|
||||
to: string[];
|
||||
domain: string;
|
||||
isTransactional?: boolean;
|
||||
}): string | null;
|
||||
/**
|
||||
* Set the active IP allocation policy for warmup
|
||||
* @param policyName Name of the policy to set
|
||||
*/
|
||||
setIPAllocationPolicy(policyName: string): void;
|
||||
/**
|
||||
* Record that an email was sent using a specific IP
|
||||
* @param ipAddress IP address used for sending
|
||||
*/
|
||||
recordIPSend(ipAddress: string): void;
|
||||
/**
|
||||
* Get reputation data for a domain
|
||||
* @param domain Domain to get reputation for
|
||||
* @returns Domain reputation metrics
|
||||
*/
|
||||
getDomainReputationData(domain: string): any;
|
||||
/**
|
||||
* Get summary reputation data for all monitored domains
|
||||
* @returns Summary data for all domains
|
||||
*/
|
||||
getReputationSummary(): any;
|
||||
/**
|
||||
* Add a domain to the reputation monitoring system
|
||||
* @param domain Domain to add
|
||||
*/
|
||||
addDomainToMonitoring(domain: string): void;
|
||||
/**
|
||||
* Remove a domain from the reputation monitoring system
|
||||
* @param domain Domain to remove
|
||||
*/
|
||||
removeDomainFromMonitoring(domain: string): void;
|
||||
/**
|
||||
* Record an email event for domain reputation tracking
|
||||
* @param domain Domain sending the email
|
||||
* @param event Event details
|
||||
*/
|
||||
recordReputationEvent(domain: string, event: {
|
||||
type: 'sent' | 'delivered' | 'bounce' | 'complaint' | 'open' | 'click';
|
||||
count?: number;
|
||||
hardBounce?: boolean;
|
||||
receivingDomain?: string;
|
||||
}): void;
|
||||
/**
|
||||
* Check if DKIM key exists for a domain
|
||||
* @param domain Domain to check
|
||||
*/
|
||||
hasDkimKey(domain: string): boolean;
|
||||
/**
|
||||
* Record successful email delivery
|
||||
* @param domain Sending domain
|
||||
*/
|
||||
recordDelivery(domain: string): void;
|
||||
/**
|
||||
* Record email bounce
|
||||
* @param domain Sending domain
|
||||
* @param receivingDomain Receiving domain that bounced
|
||||
* @param bounceType Type of bounce (hard/soft)
|
||||
* @param reason Bounce reason
|
||||
*/
|
||||
recordBounce(domain: string, receivingDomain: string, bounceType: 'hard' | 'soft', reason: string): void;
|
||||
/**
|
||||
* Get the rate limiter instance
|
||||
* @returns The unified rate limiter
|
||||
*/
|
||||
getRateLimiter(): UnifiedRateLimiter;
|
||||
}
|
||||
export {};
|
||||
1469
dist_ts/mail/routing/classes.unified.email.server.js
Normal file
1469
dist_ts/mail/routing/classes.unified.email.server.js
Normal file
File diff suppressed because one or more lines are too long
5
dist_ts/mail/routing/index.d.ts
vendored
Normal file
5
dist_ts/mail/routing/index.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './classes.email.router.js';
|
||||
export * from './classes.unified.email.server.js';
|
||||
export * from './classes.dns.manager.js';
|
||||
export * from './interfaces.js';
|
||||
export * from './classes.domain.registry.js';
|
||||
7
dist_ts/mail/routing/index.js
Normal file
7
dist_ts/mail/routing/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
// Email routing components
|
||||
export * from './classes.email.router.js';
|
||||
export * from './classes.unified.email.server.js';
|
||||
export * from './classes.dns.manager.js';
|
||||
export * from './interfaces.js';
|
||||
export * from './classes.domain.registry.js';
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL3JvdXRpbmcvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsMkJBQTJCO0FBQzNCLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyxtQ0FBbUMsQ0FBQztBQUNsRCxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyw4QkFBOEIsQ0FBQyJ9
|
||||
187
dist_ts/mail/routing/interfaces.d.ts
vendored
Normal file
187
dist_ts/mail/routing/interfaces.d.ts
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
import type { Email } from '../core/classes.email.js';
|
||||
import type { IExtendedSmtpSession } from './classes.unified.email.server.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;
|
||||
/** 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';
|
||||
};
|
||||
/** Options for various action types */
|
||||
options?: {
|
||||
/** MTA specific options */
|
||||
mtaOptions?: {
|
||||
domain?: string;
|
||||
allowLocalDelivery?: boolean;
|
||||
localDeliveryPath?: string;
|
||||
dkimSign?: boolean;
|
||||
dkimOptions?: {
|
||||
domainName: string;
|
||||
keySelector: string;
|
||||
privateKey?: string;
|
||||
};
|
||||
smtpBanner?: string;
|
||||
maxConnections?: number;
|
||||
connTimeout?: number;
|
||||
spoolDir?: string;
|
||||
};
|
||||
/** Content scanning configuration */
|
||||
contentScanning?: boolean;
|
||||
scanners?: Array<{
|
||||
type: 'spam' | 'virus' | 'attachment';
|
||||
threshold?: number;
|
||||
action: 'tag' | 'reject';
|
||||
blockedExtensions?: string[];
|
||||
}>;
|
||||
/** Email transformations */
|
||||
transformations?: Array<{
|
||||
type: string;
|
||||
header?: string;
|
||||
value?: string;
|
||||
domains?: string[];
|
||||
append?: boolean;
|
||||
[key: string]: any;
|
||||
}>;
|
||||
};
|
||||
/** 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;
|
||||
}
|
||||
/**
|
||||
* Email domain configuration
|
||||
*/
|
||||
export interface IEmailDomainConfig {
|
||||
/** Domain name */
|
||||
domain: string;
|
||||
/** DNS handling mode */
|
||||
dnsMode: 'forward' | 'internal-dns' | 'external-dns';
|
||||
/** DNS configuration based on mode */
|
||||
dns?: {
|
||||
/** For 'forward' mode */
|
||||
forward?: {
|
||||
/** Skip DNS validation (default: false) */
|
||||
skipDnsValidation?: boolean;
|
||||
/** Target server's expected domain */
|
||||
targetDomain?: string;
|
||||
};
|
||||
/** For 'internal-dns' mode */
|
||||
internal?: {
|
||||
/** TTL for DNS records in seconds (default: 3600) */
|
||||
ttl?: number;
|
||||
/** MX record priority (default: 10) */
|
||||
mxPriority?: number;
|
||||
};
|
||||
/** For 'external-dns' mode */
|
||||
external?: {
|
||||
/** Custom DNS servers (default: system DNS) */
|
||||
servers?: string[];
|
||||
/** Which records to validate (default: ['MX', 'SPF', 'DKIM', 'DMARC']) */
|
||||
requiredRecords?: ('MX' | 'SPF' | 'DKIM' | 'DMARC')[];
|
||||
};
|
||||
};
|
||||
/** Per-domain DKIM settings (DKIM always enabled) */
|
||||
dkim?: {
|
||||
/** DKIM selector (default: 'default') */
|
||||
selector?: string;
|
||||
/** Key size in bits (default: 2048) */
|
||||
keySize?: number;
|
||||
/** Automatically rotate keys (default: false) */
|
||||
rotateKeys?: boolean;
|
||||
/** Days between key rotations (default: 90) */
|
||||
rotationInterval?: number;
|
||||
};
|
||||
/** Per-domain rate limits */
|
||||
rateLimits?: {
|
||||
outbound?: {
|
||||
messagesPerMinute?: number;
|
||||
messagesPerHour?: number;
|
||||
messagesPerDay?: number;
|
||||
};
|
||||
inbound?: {
|
||||
messagesPerMinute?: number;
|
||||
connectionsPerIp?: number;
|
||||
recipientsPerMessage?: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
2
dist_ts/mail/routing/interfaces.js
Normal file
2
dist_ts/mail/routing/interfaces.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL21haWwvcm91dGluZy9pbnRlcmZhY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
|
||||
Reference in New Issue
Block a user