| 
									
										
										
										
											2025-05-08 01:13:54 +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'; | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-08 00:12:36 +00:00
										 |  |  | // Import the consolidated email config
 | 
					
						
							| 
									
										
										
										
											2025-05-08 01:13:54 +00:00
										 |  |  | import type { IEmailConfig, IDomainRule } from './mail/routing/classes.email.config.js'; | 
					
						
							|  |  |  | import { DomainRouter } from './mail/routing/classes.domain.router.js'; | 
					
						
							|  |  |  | import { UnifiedEmailServer } from './mail/routing/classes.unified.email.server.js'; | 
					
						
							|  |  |  | import { UnifiedDeliveryQueue, type IQueueOptions } from './mail/delivery/classes.delivery.queue.js'; | 
					
						
							|  |  |  | import { MultiModeDeliverySystem, type IMultiModeDeliveryOptions } from './mail/delivery/classes.delivery.system.js'; | 
					
						
							|  |  |  | import { UnifiedRateLimiter, type IHierarchicalRateLimits } from './mail/delivery/classes.unified.rate.limiter.js'; | 
					
						
							|  |  |  | import { logger } from './logger.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; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |    * Consolidated email configuration | 
					
						
							|  |  |  |    * This enables all email handling with pattern-based routing | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |   emailConfig?: IEmailConfig; | 
					
						
							| 
									
										
										
										
											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 dnsServer?: plugins.smartdns.DnsServer; | 
					
						
							| 
									
										
										
										
											2025-05-07 23:04:54 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |   // Unified email components
 | 
					
						
							|  |  |  |   public domainRouter?: DomainRouter; | 
					
						
							| 
									
										
										
										
											2025-05-08 00:39:43 +00:00
										 |  |  |   public unifiedEmailServer?: UnifiedEmailServer; | 
					
						
							|  |  |  |   public deliveryQueue?: UnifiedDeliveryQueue; | 
					
						
							|  |  |  |   public deliverySystem?: MultiModeDeliverySystem; | 
					
						
							|  |  |  |   public rateLimiter?: UnifiedRateLimiter; | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											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-08 00:12:36 +00:00
										 |  |  |       // Set up unified email handling if configured
 | 
					
						
							|  |  |  |       if (this.options.emailConfig) { | 
					
						
							|  |  |  |         await this.setupUnifiedEmailHandling(); | 
					
						
							| 
									
										
										
										
											2025-05-07 23:04:54 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // 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-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-08 00:12:36 +00:00
										 |  |  |         // Stop unified email components if running
 | 
					
						
							|  |  |  |         this.domainRouter ? this.stopUnifiedEmailComponents().catch(err => console.error('Error stopping unified email components:', err)) : Promise.resolve(), | 
					
						
							| 
									
										
										
										
											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 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'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |    * Set up unified email handling with pattern-based routing | 
					
						
							|  |  |  |    * This implements the consolidated emailConfig approach | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |   private async setupUnifiedEmailHandling(): Promise<void> { | 
					
						
							| 
									
										
										
										
											2025-05-08 00:39:43 +00:00
										 |  |  |     logger.log('info', 'Setting up unified email handling with pattern-based routing'); | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |     if (!this.options.emailConfig) { | 
					
						
							|  |  |  |       throw new Error('Email configuration is required for unified email handling'); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |      | 
					
						
							|  |  |  |     try { | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |       // Create domain router for pattern matching
 | 
					
						
							|  |  |  |       this.domainRouter = new DomainRouter({ | 
					
						
							|  |  |  |         domainRules: this.options.emailConfig.domainRules, | 
					
						
							|  |  |  |         defaultMode: this.options.emailConfig.defaultMode, | 
					
						
							|  |  |  |         defaultServer: this.options.emailConfig.defaultServer, | 
					
						
							|  |  |  |         defaultPort: this.options.emailConfig.defaultPort, | 
					
						
							|  |  |  |         defaultTls: this.options.emailConfig.defaultTls | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |       }); | 
					
						
							|  |  |  |        | 
					
						
							| 
									
										
										
										
											2025-05-08 00:39:43 +00:00
										 |  |  |       // Initialize the rate limiter
 | 
					
						
							|  |  |  |       this.rateLimiter = new UnifiedRateLimiter({ | 
					
						
							|  |  |  |         global: { | 
					
						
							|  |  |  |           maxMessagesPerMinute: 100, | 
					
						
							|  |  |  |           maxRecipientsPerMessage: 100, | 
					
						
							|  |  |  |           maxConnectionsPerIP: 20, | 
					
						
							|  |  |  |           maxErrorsPerIP: 10, | 
					
						
							|  |  |  |           maxAuthFailuresPerIP: 5 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // Initialize the unified delivery queue
 | 
					
						
							|  |  |  |       const queueOptions: IQueueOptions = { | 
					
						
							|  |  |  |         storageType: this.options.emailConfig.queue?.storageType || 'memory', | 
					
						
							|  |  |  |         persistentPath: this.options.emailConfig.queue?.persistentPath, | 
					
						
							|  |  |  |         maxRetries: this.options.emailConfig.queue?.maxRetries, | 
					
						
							|  |  |  |         baseRetryDelay: this.options.emailConfig.queue?.baseRetryDelay, | 
					
						
							|  |  |  |         maxRetryDelay: this.options.emailConfig.queue?.maxRetryDelay | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       this.deliveryQueue = new UnifiedDeliveryQueue(queueOptions); | 
					
						
							|  |  |  |       await this.deliveryQueue.initialize(); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // Initialize the delivery system
 | 
					
						
							|  |  |  |       const deliveryOptions: IMultiModeDeliveryOptions = { | 
					
						
							|  |  |  |         globalRateLimit: 100, // Default to 100 emails per minute
 | 
					
						
							|  |  |  |         concurrentDeliveries: 10 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       this.deliverySystem = new MultiModeDeliverySystem(this.deliveryQueue, deliveryOptions); | 
					
						
							|  |  |  |       await this.deliverySystem.start(); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // Initialize the unified email server
 | 
					
						
							|  |  |  |       this.unifiedEmailServer = new UnifiedEmailServer({ | 
					
						
							|  |  |  |         ports: this.options.emailConfig.ports, | 
					
						
							|  |  |  |         hostname: this.options.emailConfig.hostname, | 
					
						
							|  |  |  |         maxMessageSize: this.options.emailConfig.maxMessageSize, | 
					
						
							|  |  |  |         auth: this.options.emailConfig.auth, | 
					
						
							|  |  |  |         tls: this.options.emailConfig.tls, | 
					
						
							|  |  |  |         domainRules: this.options.emailConfig.domainRules, | 
					
						
							|  |  |  |         defaultMode: this.options.emailConfig.defaultMode, | 
					
						
							|  |  |  |         defaultServer: this.options.emailConfig.defaultServer, | 
					
						
							|  |  |  |         defaultPort: this.options.emailConfig.defaultPort, | 
					
						
							|  |  |  |         defaultTls: this.options.emailConfig.defaultTls | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |        | 
					
						
							| 
									
										
										
										
											2025-05-08 00:39:43 +00:00
										 |  |  |       // Set up event listeners
 | 
					
						
							|  |  |  |       this.unifiedEmailServer.on('error', (err) => { | 
					
						
							|  |  |  |         logger.log('error', `UnifiedEmailServer error: ${err.message}`); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // Connect the unified email server with the delivery queue
 | 
					
						
							|  |  |  |       this.unifiedEmailServer.on('emailProcessed', (email, mode, rule) => { | 
					
						
							|  |  |  |         this.deliveryQueue!.enqueue(email, mode, rule).catch(err => { | 
					
						
							|  |  |  |           logger.log('error', `Failed to enqueue email: ${err.message}`); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // Start the unified email server
 | 
					
						
							|  |  |  |       await this.unifiedEmailServer.start(); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       logger.log('info', `Unified email handling configured with ${this.options.emailConfig.domainRules.length} domain rules`); | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |     } catch (error) { | 
					
						
							| 
									
										
										
										
											2025-05-08 00:39:43 +00:00
										 |  |  |       logger.log('error', `Error setting up unified email handling: ${error.message}`); | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |       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-08 00:12:36 +00:00
										 |  |  |    * Update the unified email configuration | 
					
						
							|  |  |  |    * @param config New email configuration | 
					
						
							| 
									
										
										
										
											2025-05-07 14:33:20 +00:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |   public async updateEmailConfig(config: IEmailConfig): Promise<void> { | 
					
						
							|  |  |  |     // Stop existing email components
 | 
					
						
							|  |  |  |     await this.stopUnifiedEmailComponents(); | 
					
						
							| 
									
										
										
										
											2025-05-07 23:04:54 +00:00
										 |  |  |      | 
					
						
							|  |  |  |     // Update configuration
 | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |     this.options.emailConfig = config; | 
					
						
							| 
									
										
										
										
											2025-05-07 23:04:54 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |     // Start email handling with new configuration
 | 
					
						
							|  |  |  |     await this.setupUnifiedEmailHandling(); | 
					
						
							| 
									
										
										
										
											2025-05-07 23:04:54 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |     console.log('Unified email configuration updated'); | 
					
						
							| 
									
										
										
										
											2025-05-04 10:10:07 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |    * Stop all unified email components | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2025-05-08 00:12:36 +00:00
										 |  |  |   private async stopUnifiedEmailComponents(): Promise<void> { | 
					
						
							| 
									
										
										
										
											2025-05-08 00:39:43 +00:00
										 |  |  |     try { | 
					
						
							|  |  |  |       // Stop all components in the correct order
 | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // 1. Stop the unified email server first
 | 
					
						
							|  |  |  |       if (this.unifiedEmailServer) { | 
					
						
							|  |  |  |         await this.unifiedEmailServer.stop(); | 
					
						
							|  |  |  |         logger.log('info', 'Unified email server stopped'); | 
					
						
							|  |  |  |         this.unifiedEmailServer = undefined; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // 2. Stop the delivery system
 | 
					
						
							|  |  |  |       if (this.deliverySystem) { | 
					
						
							|  |  |  |         await this.deliverySystem.stop(); | 
					
						
							|  |  |  |         logger.log('info', 'Delivery system stopped'); | 
					
						
							|  |  |  |         this.deliverySystem = undefined; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // 3. Stop the delivery queue
 | 
					
						
							|  |  |  |       if (this.deliveryQueue) { | 
					
						
							|  |  |  |         await this.deliveryQueue.shutdown(); | 
					
						
							|  |  |  |         logger.log('info', 'Delivery queue shut down'); | 
					
						
							|  |  |  |         this.deliveryQueue = undefined; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // 4. Stop the rate limiter
 | 
					
						
							|  |  |  |       if (this.rateLimiter) { | 
					
						
							|  |  |  |         this.rateLimiter.stop(); | 
					
						
							|  |  |  |         logger.log('info', 'Rate limiter stopped'); | 
					
						
							|  |  |  |         this.rateLimiter = undefined; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // 5. Clear the domain router
 | 
					
						
							|  |  |  |       this.domainRouter = undefined; | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       logger.log('info', 'All unified email components stopped'); | 
					
						
							|  |  |  |     } catch (error) { | 
					
						
							|  |  |  |       logger.log('error', `Error stopping unified email components: ${error.message}`); | 
					
						
							|  |  |  |       throw error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Update domain rules for email routing | 
					
						
							|  |  |  |    * @param rules New domain rules to apply | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   public async updateDomainRules(rules: IDomainRule[]): Promise<void> { | 
					
						
							|  |  |  |     // Validate that email config exists
 | 
					
						
							|  |  |  |     if (!this.options.emailConfig) { | 
					
						
							|  |  |  |       throw new Error('Email configuration is required before updating domain rules'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Update the configuration
 | 
					
						
							|  |  |  |     this.options.emailConfig.domainRules = rules; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Update the domain router if it exists
 | 
					
						
							|  |  |  |     if (this.domainRouter) { | 
					
						
							|  |  |  |       this.domainRouter.updateRules(rules); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Update the unified email server if it exists
 | 
					
						
							|  |  |  |     if (this.unifiedEmailServer) { | 
					
						
							|  |  |  |       this.unifiedEmailServer.updateDomainRules(rules); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2025-05-08 00:39:43 +00:00
										 |  |  |     console.log(`Domain rules updated with ${rules.length} rules`); | 
					
						
							| 
									
										
										
										
											2025-05-07 23:45:19 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2025-05-08 00:39:43 +00:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Get statistics from all components | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   public getStats(): any { | 
					
						
							|  |  |  |     const stats: any = { | 
					
						
							|  |  |  |       unifiedEmailServer: this.unifiedEmailServer?.getStats(), | 
					
						
							|  |  |  |       deliveryQueue: this.deliveryQueue?.getStats(), | 
					
						
							|  |  |  |       deliverySystem: this.deliverySystem?.getStats(), | 
					
						
							|  |  |  |       rateLimiter: this.rateLimiter?.getStats() | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     return stats; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2025-05-04 10:10:07 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default DcRouter; |