2025-05-04 10:10:07 +00:00
|
|
|
import * as plugins from '../plugins.js';
|
|
|
|
import * as paths from '../paths.js';
|
2025-05-07 23:04:54 +00:00
|
|
|
import { SmtpPortConfig, type ISmtpPortSettings } from './classes.smtp.portconfig.js';
|
|
|
|
import { EmailDomainRouter, type IEmailDomainRoutingConfig } from './classes.email.domainrouter.js';
|
2025-05-04 10:10:07 +00:00
|
|
|
import { type IMtaConfig, MtaService } from '../mta/classes.mta.js';
|
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
// Import SMTP store-and-forward components
|
|
|
|
import { SmtpServer } from './classes.smtp.server.js';
|
|
|
|
import { EmailProcessor, type IProcessingResult } from './classes.email.processor.js';
|
|
|
|
import { DeliveryQueue } from './classes.delivery.queue.js';
|
|
|
|
import { DeliverySystem } from './classes.delivery.system.js';
|
|
|
|
|
2025-05-07 22:06:55 +00:00
|
|
|
// Certificate types are available via plugins.tsclass
|
2025-05-07 14:33:20 +00:00
|
|
|
|
2025-05-07 23:04:54 +00:00
|
|
|
/**
|
|
|
|
* Configuration for SMTP forwarding functionality
|
|
|
|
*/
|
|
|
|
export interface ISmtpForwardingConfig {
|
|
|
|
/** Whether SMTP forwarding is enabled */
|
|
|
|
enabled?: boolean;
|
|
|
|
/** SMTP ports to listen on */
|
|
|
|
ports?: number[];
|
|
|
|
/** Default SMTP server hostname */
|
|
|
|
defaultServer: string;
|
|
|
|
/** Default SMTP server port */
|
|
|
|
defaultPort?: number;
|
|
|
|
/** Whether to use TLS when connecting to the default server */
|
|
|
|
useTls?: boolean;
|
|
|
|
/** Preserve source IP address when forwarding */
|
|
|
|
preserveSourceIp?: boolean;
|
|
|
|
/** Domain-specific routing rules */
|
|
|
|
domainRoutes?: Array<{
|
|
|
|
domain: string;
|
|
|
|
server: string;
|
|
|
|
port?: number;
|
|
|
|
}>;
|
|
|
|
}
|
2025-05-07 14:33:20 +00:00
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
|
|
|
|
import type { ISmtpConfig } from './classes.smtp.config.js';
|
2025-05-07 23:04:54 +00:00
|
|
|
|
|
|
|
export interface IDcRouterOptions {
|
2025-05-07 23:45:19 +00:00
|
|
|
/**
|
|
|
|
* Direct SmartProxy configuration - gives full control over HTTP/HTTPS and TCP/SNI traffic
|
|
|
|
* This is the preferred way to configure HTTP/HTTPS and general TCP/SNI traffic
|
|
|
|
*/
|
|
|
|
smartProxyConfig?: plugins.smartproxy.ISmartProxyOptions;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SMTP store-and-forward configuration
|
|
|
|
* This enables advanced email processing capabilities (complementary to smartProxyConfig)
|
|
|
|
*/
|
|
|
|
smtpConfig?: ISmtpConfig;
|
2025-05-07 23:04:54 +00:00
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
/**
|
|
|
|
* Legacy SMTP forwarding configuration
|
|
|
|
* If smtpConfig is provided, this will be ignored
|
|
|
|
*/
|
2025-05-07 23:04:54 +00:00
|
|
|
smtpForwarding?: ISmtpForwardingConfig;
|
|
|
|
|
|
|
|
/** MTA service configuration (if not using SMTP forwarding) */
|
2025-05-04 10:10:07 +00:00
|
|
|
mtaConfig?: IMtaConfig;
|
2025-05-07 23:04:54 +00:00
|
|
|
|
|
|
|
/** Existing MTA service instance to use (if not using SMTP forwarding) */
|
2025-05-07 22:06:55 +00:00
|
|
|
mtaServiceInstance?: MtaService;
|
2025-05-07 23:04:54 +00:00
|
|
|
|
|
|
|
/** TLS/certificate configuration */
|
|
|
|
tls?: {
|
|
|
|
/** Contact email for ACME certificates */
|
|
|
|
contactEmail: string;
|
|
|
|
/** Domain for main certificate */
|
|
|
|
domain?: string;
|
|
|
|
/** Path to certificate file (if not using auto-provisioning) */
|
|
|
|
certPath?: string;
|
|
|
|
/** Path to key file (if not using auto-provisioning) */
|
|
|
|
keyPath?: string;
|
|
|
|
};
|
|
|
|
|
2025-05-07 14:33:20 +00:00
|
|
|
/** DNS server configuration */
|
2025-05-04 10:10:07 +00:00
|
|
|
dnsServerConfig?: plugins.smartdns.IDnsServerOptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DcRouter can be run on ingress and egress to and from a datacenter site.
|
|
|
|
*/
|
2025-05-07 14:33:20 +00:00
|
|
|
/**
|
|
|
|
* Context passed to HTTP routing rules
|
|
|
|
*/
|
|
|
|
/**
|
|
|
|
* Context passed to port proxy (SmartProxy) routing rules
|
|
|
|
*/
|
|
|
|
export interface PortProxyRuleContext {
|
|
|
|
proxy: plugins.smartproxy.SmartProxy;
|
|
|
|
configs: plugins.smartproxy.IPortProxySettings['domainConfigs'];
|
|
|
|
}
|
2025-05-07 23:45:19 +00:00
|
|
|
|
2025-05-04 10:10:07 +00:00
|
|
|
export class DcRouter {
|
2025-05-07 14:33:20 +00:00
|
|
|
public options: IDcRouterOptions;
|
2025-05-07 23:04:54 +00:00
|
|
|
|
|
|
|
// Core services
|
2025-05-07 14:33:20 +00:00
|
|
|
public smartProxy?: plugins.smartproxy.SmartProxy;
|
|
|
|
public mta?: MtaService;
|
|
|
|
public dnsServer?: plugins.smartdns.DnsServer;
|
2025-05-07 23:04:54 +00:00
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
// SMTP store-and-forward components
|
|
|
|
public smtpServer?: SmtpServer;
|
|
|
|
public emailProcessor?: EmailProcessor;
|
|
|
|
public deliveryQueue?: DeliveryQueue;
|
|
|
|
public deliverySystem?: DeliverySystem;
|
|
|
|
|
2025-05-07 23:04:54 +00:00
|
|
|
// Environment access
|
|
|
|
private qenv = new plugins.qenv.Qenv('./', '.nogit/');
|
|
|
|
|
2025-05-04 10:10:07 +00:00
|
|
|
constructor(optionsArg: IDcRouterOptions) {
|
2025-05-07 22:06:55 +00:00
|
|
|
// Set defaults in options
|
|
|
|
this.options = {
|
|
|
|
...optionsArg
|
|
|
|
};
|
2025-05-07 14:33:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public async start() {
|
2025-05-07 23:04:54 +00:00
|
|
|
console.log('Starting DcRouter services...');
|
|
|
|
|
|
|
|
try {
|
2025-05-07 23:45:19 +00:00
|
|
|
// Set up SmartProxy for HTTP/HTTPS and general TCP/SNI traffic
|
|
|
|
if (this.options.smartProxyConfig) {
|
|
|
|
await this.setupSmartProxy();
|
|
|
|
}
|
2025-05-07 23:04:54 +00:00
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
// 2. Set up SMTP handling
|
|
|
|
if (this.options.smtpConfig) {
|
|
|
|
// Set up store-and-forward SMTP processing
|
|
|
|
await this.setupSmtpProcessing();
|
|
|
|
} else if (this.options.smtpForwarding?.enabled) {
|
|
|
|
// Fallback to simple SMTP forwarding for backward compatibility
|
2025-05-07 23:04:54 +00:00
|
|
|
await this.setupSmtpForwarding();
|
|
|
|
} else {
|
2025-05-07 23:45:19 +00:00
|
|
|
// Set up MTA service if no SMTP handling is configured
|
2025-05-07 23:04:54 +00:00
|
|
|
await this.setupMtaService();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3. Set up DNS server if configured
|
|
|
|
if (this.options.dnsServerConfig) {
|
|
|
|
this.dnsServer = new plugins.smartdns.DnsServer(this.options.dnsServerConfig);
|
|
|
|
await this.dnsServer.start();
|
|
|
|
console.log('DNS server started');
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('DcRouter started successfully');
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error starting DcRouter:', error);
|
|
|
|
// Try to clean up any services that may have started
|
|
|
|
await this.stop();
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2025-05-07 23:45:19 +00:00
|
|
|
* Set up SmartProxy with direct configuration
|
2025-05-07 23:04:54 +00:00
|
|
|
*/
|
2025-05-07 23:45:19 +00:00
|
|
|
private async setupSmartProxy(): Promise<void> {
|
|
|
|
if (!this.options.smartProxyConfig) {
|
2025-05-07 23:04:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
console.log('Setting up SmartProxy with direct configuration');
|
2025-05-07 23:04:54 +00:00
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
// Create SmartProxy instance with full configuration
|
|
|
|
this.smartProxy = new plugins.smartproxy.SmartProxy(this.options.smartProxyConfig);
|
2025-05-07 23:04:54 +00:00
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
// Set up event listeners
|
|
|
|
this.smartProxy.on('error', (err) => {
|
|
|
|
console.error('SmartProxy error:', err);
|
2025-05-07 23:04:54 +00:00
|
|
|
});
|
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
if (this.options.smartProxyConfig.acme) {
|
|
|
|
this.smartProxy.on('certificate-issued', (event) => {
|
|
|
|
console.log(`Certificate issued for ${event.domain}, expires ${event.expiryDate}`);
|
|
|
|
});
|
|
|
|
|
|
|
|
this.smartProxy.on('certificate-renewed', (event) => {
|
|
|
|
console.log(`Certificate renewed for ${event.domain}, expires ${event.expiryDate}`);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start SmartProxy
|
2025-05-07 23:04:54 +00:00
|
|
|
await this.smartProxy.start();
|
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
console.log('SmartProxy started successfully');
|
2025-05-07 23:04:54 +00:00
|
|
|
}
|
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
|
2025-05-07 23:04:54 +00:00
|
|
|
/**
|
|
|
|
* Set up the MTA service
|
|
|
|
*/
|
|
|
|
private async setupMtaService() {
|
|
|
|
// Use existing MTA service if provided
|
2025-05-07 22:06:55 +00:00
|
|
|
if (this.options.mtaServiceInstance) {
|
|
|
|
this.mta = this.options.mtaServiceInstance;
|
|
|
|
console.log('Using provided MTA service instance');
|
|
|
|
} else if (this.options.mtaConfig) {
|
|
|
|
// Create new MTA service with the provided configuration
|
|
|
|
this.mta = new MtaService(undefined, this.options.mtaConfig);
|
|
|
|
console.log('Created new MTA service instance');
|
|
|
|
|
2025-05-07 23:04:54 +00:00
|
|
|
// Start the MTA service
|
|
|
|
await this.mta.start();
|
|
|
|
console.log('MTA service started');
|
2025-05-07 22:06:55 +00:00
|
|
|
}
|
2025-05-07 23:04:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set up SMTP forwarding with SmartProxy
|
|
|
|
*/
|
|
|
|
private async setupSmtpForwarding() {
|
|
|
|
if (!this.options.smtpForwarding) {
|
|
|
|
return;
|
2025-05-04 10:10:07 +00:00
|
|
|
}
|
2025-05-07 22:06:55 +00:00
|
|
|
|
2025-05-07 23:04:54 +00:00
|
|
|
const forwarding = this.options.smtpForwarding;
|
|
|
|
console.log('Setting up SMTP forwarding');
|
2025-05-07 22:06:55 +00:00
|
|
|
|
2025-05-07 23:04:54 +00:00
|
|
|
// Determine which ports to listen on
|
|
|
|
const smtpPorts = forwarding.ports || [25, 587, 465];
|
2025-05-07 22:06:55 +00:00
|
|
|
|
2025-05-07 23:04:54 +00:00
|
|
|
// Create SmartProxy instance for SMTP forwarding
|
2025-05-07 23:45:19 +00:00
|
|
|
const smtpProxyConfig: plugins.smartproxy.ISmartProxyOptions = {
|
2025-05-07 23:04:54 +00:00
|
|
|
// Listen on the first SMTP port
|
|
|
|
fromPort: smtpPorts[0],
|
|
|
|
// Forward to the default server
|
|
|
|
toPort: forwarding.defaultPort || 25,
|
|
|
|
targetIP: forwarding.defaultServer,
|
|
|
|
// Enable SNI if port 465 is included (implicit TLS)
|
|
|
|
sniEnabled: smtpPorts.includes(465),
|
|
|
|
// Preserve source IP if requested
|
|
|
|
preserveSourceIP: forwarding.preserveSourceIp || false,
|
|
|
|
// Create domain configs for SMTP routing
|
|
|
|
domainConfigs: forwarding.domainRoutes?.map(route => ({
|
|
|
|
domains: [route.domain],
|
|
|
|
allowedIPs: ['0.0.0.0/0'], // Allow from anywhere by default
|
|
|
|
targetIPs: [route.server]
|
|
|
|
})) || [],
|
|
|
|
// Include all SMTP ports in the global port ranges
|
|
|
|
globalPortRanges: smtpPorts.map(port => ({ from: port, to: port }))
|
2025-05-07 23:45:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Create a separate SmartProxy instance for SMTP
|
|
|
|
const smtpProxy = new plugins.smartproxy.SmartProxy(smtpProxyConfig);
|
2025-05-07 23:04:54 +00:00
|
|
|
|
|
|
|
// Start the SMTP proxy
|
2025-05-07 23:45:19 +00:00
|
|
|
await smtpProxy.start();
|
|
|
|
|
|
|
|
// Store the SMTP proxy reference
|
|
|
|
this.smartProxy = smtpProxy;
|
2025-05-07 23:04:54 +00:00
|
|
|
|
|
|
|
console.log(`SMTP forwarding configured on ports ${smtpPorts.join(', ')}`);
|
2025-05-04 10:10:07 +00:00
|
|
|
}
|
|
|
|
|
2025-05-07 22:06:55 +00:00
|
|
|
/**
|
2025-05-07 23:04:54 +00:00
|
|
|
* Check if a domain matches a pattern (including wildcard support)
|
|
|
|
* @param domain The domain to check
|
|
|
|
* @param pattern The pattern to match against (e.g., "*.example.com")
|
|
|
|
* @returns Whether the domain matches the pattern
|
2025-05-07 22:06:55 +00:00
|
|
|
*/
|
2025-05-07 23:04:54 +00:00
|
|
|
private isDomainMatch(domain: string, pattern: string): boolean {
|
|
|
|
// Normalize inputs
|
|
|
|
domain = domain.toLowerCase();
|
|
|
|
pattern = pattern.toLowerCase();
|
|
|
|
|
|
|
|
// Check for exact match
|
|
|
|
if (domain === pattern) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for wildcard match (*.example.com)
|
|
|
|
if (pattern.startsWith('*.')) {
|
|
|
|
const patternSuffix = pattern.slice(2); // Remove the "*." prefix
|
|
|
|
|
|
|
|
// Check if domain ends with the pattern suffix and has at least one character before it
|
|
|
|
return domain.endsWith(patternSuffix) && domain.length > patternSuffix.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
// No match
|
|
|
|
return false;
|
|
|
|
}
|
2025-05-07 22:06:55 +00:00
|
|
|
|
2025-05-07 23:04:54 +00:00
|
|
|
public async stop() {
|
|
|
|
console.log('Stopping DcRouter services...');
|
|
|
|
|
2025-05-07 22:06:55 +00:00
|
|
|
try {
|
2025-05-07 23:04:54 +00:00
|
|
|
// Stop all services in parallel for faster shutdown
|
|
|
|
await Promise.all([
|
2025-05-07 23:45:19 +00:00
|
|
|
// Stop SMTP components
|
|
|
|
this.stopSmtpComponents().catch(err => console.error('Error stopping SMTP components:', err)),
|
2025-05-07 23:04:54 +00:00
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
// Stop HTTP SmartProxy if running
|
|
|
|
this.smartProxy ? this.smartProxy.stop().catch(err => console.error('Error stopping SmartProxy:', err)) : Promise.resolve(),
|
2025-05-07 23:04:54 +00:00
|
|
|
|
|
|
|
// Stop MTA service if it's our own (not an external instance)
|
|
|
|
(this.mta && !this.options.mtaServiceInstance) ?
|
|
|
|
this.mta.stop().catch(err => console.error('Error stopping MTA service:', err)) :
|
|
|
|
Promise.resolve(),
|
|
|
|
|
|
|
|
// Stop DNS server if running
|
|
|
|
this.dnsServer ?
|
|
|
|
this.dnsServer.stop().catch(err => console.error('Error stopping DNS server:', err)) :
|
|
|
|
Promise.resolve()
|
|
|
|
]);
|
|
|
|
|
|
|
|
console.log('All DcRouter services stopped');
|
2025-05-07 22:06:55 +00:00
|
|
|
} catch (error) {
|
2025-05-07 23:04:54 +00:00
|
|
|
console.error('Error during DcRouter shutdown:', error);
|
|
|
|
throw error;
|
2025-05-07 22:06:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-07 23:04:54 +00:00
|
|
|
/**
|
2025-05-07 23:45:19 +00:00
|
|
|
* Update SmartProxy configuration
|
|
|
|
* @param config New SmartProxy configuration
|
2025-05-07 23:04:54 +00:00
|
|
|
*/
|
2025-05-07 23:45:19 +00:00
|
|
|
public async updateSmartProxyConfig(config: plugins.smartproxy.ISmartProxyOptions): Promise<void> {
|
|
|
|
// Stop existing SmartProxy if running
|
2025-05-04 10:10:07 +00:00
|
|
|
if (this.smartProxy) {
|
|
|
|
await this.smartProxy.stop();
|
2025-05-07 23:04:54 +00:00
|
|
|
this.smartProxy = undefined;
|
2025-05-04 10:10:07 +00:00
|
|
|
}
|
2025-05-07 22:06:55 +00:00
|
|
|
|
2025-05-07 23:45:19 +00:00
|
|
|
// Update configuration
|
|
|
|
this.options.smartProxyConfig = config;
|
|
|
|
|
|
|
|
// Start new SmartProxy with updated configuration
|
|
|
|
await this.setupSmartProxy();
|
|
|
|
|
|
|
|
console.log('SmartProxy configuration updated');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set up SMTP store-and-forward processing
|
|
|
|
*/
|
|
|
|
private async setupSmtpProcessing(): Promise<void> {
|
|
|
|
if (!this.options.smtpConfig) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('Setting up SMTP store-and-forward processing');
|
|
|
|
|
|
|
|
try {
|
|
|
|
// 1. Create SMTP server
|
|
|
|
this.smtpServer = new SmtpServer(this.options.smtpConfig);
|
|
|
|
|
|
|
|
// 2. Create email processor
|
|
|
|
this.emailProcessor = new EmailProcessor(this.options.smtpConfig);
|
|
|
|
|
|
|
|
// 3. Create delivery queue
|
|
|
|
this.deliveryQueue = new DeliveryQueue(this.options.smtpConfig.queue || {});
|
|
|
|
await this.deliveryQueue.initialize();
|
|
|
|
|
|
|
|
// 4. Create delivery system
|
|
|
|
this.deliverySystem = new DeliverySystem(this.deliveryQueue);
|
|
|
|
|
|
|
|
// 5. Connect components
|
|
|
|
|
|
|
|
// When a message is received by the SMTP server, process it
|
|
|
|
this.smtpServer.on('message', async ({ session, mail, rawData }) => {
|
|
|
|
try {
|
|
|
|
// Process the message
|
|
|
|
const processingResult = await this.emailProcessor.processEmail(mail, rawData, session);
|
|
|
|
|
|
|
|
// If action is queue, add to delivery queue
|
|
|
|
if (processingResult.action === 'queue') {
|
|
|
|
await this.deliveryQueue.enqueue(processingResult);
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error processing message:', error);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// 6. Start components
|
|
|
|
await this.smtpServer.start();
|
|
|
|
await this.deliverySystem.start();
|
|
|
|
|
|
|
|
console.log(`SMTP processing started on ports ${this.options.smtpConfig.ports.join(', ')}`);
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error setting up SMTP processing:', error);
|
|
|
|
|
|
|
|
// Clean up any components that were started
|
|
|
|
if (this.deliverySystem) {
|
|
|
|
await this.deliverySystem.stop().catch(e => console.error('Error stopping delivery system:', e));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.deliveryQueue) {
|
|
|
|
await this.deliveryQueue.shutdown().catch(e => console.error('Error shutting down delivery queue:', e));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.smtpServer) {
|
|
|
|
await this.smtpServer.stop().catch(e => console.error('Error stopping SMTP server:', e));
|
|
|
|
}
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
}
|
2025-05-07 14:33:20 +00:00
|
|
|
}
|
2025-05-07 23:04:54 +00:00
|
|
|
|
2025-05-07 14:33:20 +00:00
|
|
|
/**
|
2025-05-07 23:04:54 +00:00
|
|
|
* Update SMTP forwarding configuration
|
|
|
|
* @param config New SMTP forwarding configuration
|
2025-05-07 14:33:20 +00:00
|
|
|
*/
|
2025-05-07 23:04:54 +00:00
|
|
|
public async updateSmtpForwarding(config: ISmtpForwardingConfig): Promise<void> {
|
2025-05-07 23:45:19 +00:00
|
|
|
// Stop existing SMTP components
|
|
|
|
await this.stopSmtpComponents();
|
2025-05-07 23:04:54 +00:00
|
|
|
|
|
|
|
// Update configuration
|
|
|
|
this.options.smtpForwarding = config;
|
2025-05-07 23:45:19 +00:00
|
|
|
this.options.smtpConfig = undefined; // Clear any store-and-forward config
|
2025-05-07 23:04:54 +00:00
|
|
|
|
|
|
|
// Restart SMTP forwarding if enabled
|
|
|
|
if (config.enabled) {
|
|
|
|
await this.setupSmtpForwarding();
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('SMTP forwarding configuration updated');
|
2025-05-04 10:10:07 +00:00
|
|
|
}
|
2025-05-07 23:45:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Update SMTP processing configuration
|
|
|
|
* @param config New SMTP config
|
|
|
|
*/
|
|
|
|
public async updateSmtpConfig(config: ISmtpConfig): Promise<void> {
|
|
|
|
// Stop existing SMTP components
|
|
|
|
await this.stopSmtpComponents();
|
|
|
|
|
|
|
|
// Update configuration
|
|
|
|
this.options.smtpConfig = config;
|
|
|
|
this.options.smtpForwarding = undefined; // Clear any forwarding config
|
|
|
|
|
|
|
|
// Start SMTP processing
|
|
|
|
await this.setupSmtpProcessing();
|
|
|
|
|
|
|
|
console.log('SMTP processing configuration updated');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stop all SMTP components
|
|
|
|
*/
|
|
|
|
private async stopSmtpComponents(): Promise<void> {
|
|
|
|
// Stop delivery system
|
|
|
|
if (this.deliverySystem) {
|
|
|
|
await this.deliverySystem.stop().catch(e => console.error('Error stopping delivery system:', e));
|
|
|
|
this.deliverySystem = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop delivery queue
|
|
|
|
if (this.deliveryQueue) {
|
|
|
|
await this.deliveryQueue.shutdown().catch(e => console.error('Error shutting down delivery queue:', e));
|
|
|
|
this.deliveryQueue = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop SMTP server
|
|
|
|
if (this.smtpServer) {
|
|
|
|
await this.smtpServer.stop().catch(e => console.error('Error stopping SMTP server:', e));
|
|
|
|
this.smtpServer = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
// For backward compatibility: legacy SMTP proxy implementation
|
|
|
|
// This is no longer used with the new implementation
|
|
|
|
}
|
2025-05-04 10:10:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export default DcRouter;
|