139 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			139 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | import type { IEmailDomainConfig } from './interfaces.ts'; | ||
|  | import { logger } from '../../logger.ts'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Registry for email domain configurations | ||
|  |  * Provides fast lookups and validation for domains | ||
|  |  */ | ||
|  | export class DomainRegistry { | ||
|  |   private domains: Map<string, IEmailDomainConfig> = new Map(); | ||
|  |   private defaults: IEmailDomainConfig['dkim'] & { | ||
|  |     dnsMode?: 'forward' | 'internal-dns' | 'external-dns'; | ||
|  |     rateLimits?: IEmailDomainConfig['rateLimits']; | ||
|  |   }; | ||
|  |    | ||
|  |   constructor( | ||
|  |     domainConfigs: IEmailDomainConfig[], | ||
|  |     defaults?: { | ||
|  |       dnsMode?: 'forward' | 'internal-dns' | 'external-dns'; | ||
|  |       dkim?: IEmailDomainConfig['dkim']; | ||
|  |       rateLimits?: IEmailDomainConfig['rateLimits']; | ||
|  |     } | ||
|  |   ) { | ||
|  |     // 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 | ||
|  |    */ | ||
|  |   private getDefaultDkimConfig(): IEmailDomainConfig['dkim'] { | ||
|  |     return { | ||
|  |       selector: 'default', | ||
|  |       keySize: 2048, | ||
|  |       rotateKeys: false, | ||
|  |       rotationInterval: 90 | ||
|  |     }; | ||
|  |   } | ||
|  |    | ||
|  |   /** | ||
|  |    * Apply defaults to a domain configuration | ||
|  |    */ | ||
|  |   private applyDefaults(config: IEmailDomainConfig): IEmailDomainConfig { | ||
|  |     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: string): boolean { | ||
|  |     return this.domains.has(domain.toLowerCase()); | ||
|  |   } | ||
|  |    | ||
|  |   /** | ||
|  |    * Check if an email address belongs to a registered domain | ||
|  |    */ | ||
|  |   isEmailRegistered(email: string): boolean { | ||
|  |     const domain = this.extractDomain(email); | ||
|  |     if (!domain) return false; | ||
|  |     return this.isDomainRegistered(domain); | ||
|  |   } | ||
|  |    | ||
|  |   /** | ||
|  |    * Get domain configuration | ||
|  |    */ | ||
|  |   getDomainConfig(domain: string): IEmailDomainConfig | undefined { | ||
|  |     return this.domains.get(domain.toLowerCase()); | ||
|  |   } | ||
|  |    | ||
|  |   /** | ||
|  |    * Get domain configuration for an email address | ||
|  |    */ | ||
|  |   getEmailDomainConfig(email: string): IEmailDomainConfig | undefined { | ||
|  |     const domain = this.extractDomain(email); | ||
|  |     if (!domain) return undefined; | ||
|  |     return this.getDomainConfig(domain); | ||
|  |   } | ||
|  |    | ||
|  |   /** | ||
|  |    * Extract domain from email address | ||
|  |    */ | ||
|  |   private extractDomain(email: string): string | null { | ||
|  |     const parts = email.toLowerCase().split('@'); | ||
|  |     if (parts.length !== 2) return null; | ||
|  |     return parts[1]; | ||
|  |   } | ||
|  |    | ||
|  |   /** | ||
|  |    * Get all registered domains | ||
|  |    */ | ||
|  |   getAllDomains(): string[] { | ||
|  |     return Array.from(this.domains.keys()); | ||
|  |   } | ||
|  |    | ||
|  |   /** | ||
|  |    * Get all domain configurations | ||
|  |    */ | ||
|  |   getAllConfigs(): IEmailDomainConfig[] { | ||
|  |     return Array.from(this.domains.values()); | ||
|  |   } | ||
|  |    | ||
|  |   /** | ||
|  |    * Get domains by DNS mode | ||
|  |    */ | ||
|  |   getDomainsByMode(mode: 'forward' | 'internal-dns' | 'external-dns'): IEmailDomainConfig[] { | ||
|  |     return Array.from(this.domains.values()).filter(config => config.dnsMode === mode); | ||
|  |   } | ||
|  | } |