import * as plugins from '../../plugins.js';
import * as paths from '../../paths.js';
import { EventEmitter } from 'events';
import { logger } from '../../logger.js';
import { 
  SecurityLogger, 
  SecurityLogLevel, 
  SecurityEventType 
} from '../../security/index.js';
import { DKIMCreator } from '../security/classes.dkimcreator.js';
import { IPReputationChecker } from '../../security/classes.ipreputationchecker.js';
import { 
  IPWarmupManager, 
  type IIPWarmupConfig,
  SenderReputationMonitor,
  type IReputationMonitorConfig
} from '../../deliverability/index.js';
import { EmailRouter } from './classes.email.router.js';
import type { IEmailRoute, IEmailAction, IEmailContext, IEmailDomainConfig } from './interfaces.js';
import { Email } from '../core/classes.email.js';
import { DomainRegistry } from './classes.domain.registry.js';
import { DnsManager } from './classes.dns.manager.js';
import { BounceManager, BounceType, BounceCategory } from '../core/classes.bouncemanager.js';
import { createSmtpServer } from '../delivery/smtpserver/index.js';
import { createPooledSmtpClient } from '../delivery/smtpclient/create-client.js';
import type { SmtpClient } from '../delivery/smtpclient/smtp-client.js';
import { MultiModeDeliverySystem, type IMultiModeDeliveryOptions } from '../delivery/classes.delivery.system.js';
import { UnifiedDeliveryQueue, type IQueueOptions } from '../delivery/classes.delivery.queue.js';
import { UnifiedRateLimiter, type IHierarchicalRateLimits } from '../delivery/classes.unified.rate.limiter.js';
import { SmtpState } from '../delivery/interfaces.js';
import type { EmailProcessingMode, ISmtpSession as IBaseSmtpSession } from '../delivery/interfaces.js';
import type { DcRouter } from '../../classes.dcrouter.js';

/**
 * 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 {
  // Base server options
  ports: number[];
  hostname: string;
  domains: IEmailDomainConfig[];  // Domain configurations
  banner?: string;
  debug?: boolean;
  useSocketHandler?: boolean;  // Use socket-handler mode instead of port listening
  
  // Authentication options
  auth?: {
    required?: boolean;
    methods?: ('PLAIN' | 'LOGIN' | 'OAUTH2')[];
    users?: Array<{username: string, password: string}>;
  };
  
  // TLS options
  tls?: {
    certPath?: string;
    keyPath?: string;
    caPath?: string;
    minVersion?: string;
    ciphers?: string;
  };
  
  // Limits
  maxMessageSize?: number;
  maxClients?: number;
  maxConnections?: number;
  
  // Connection options
  connectionTimeout?: number;
  socketTimeout?: number;
  
  // Email routing rules
  routes: IEmailRoute[];
  
  // Global defaults for all domains
  defaults?: {
    dnsMode?: 'forward' | 'internal-dns' | 'external-dns';
    dkim?: IEmailDomainConfig['dkim'];
    rateLimits?: IEmailDomainConfig['rateLimits'];
  };
  
  // Outbound settings
  outbound?: {
    maxConnections?: number;
    connectionTimeout?: number;
    socketTimeout?: number;
    retryAttempts?: number;
    defaultFrom?: string;
  };
  
  // Rate limiting (global limits, can be overridden per domain)
  rateLimits?: IHierarchicalRateLimits;
  
  // Deliverability options
  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 class UnifiedEmailServer extends EventEmitter {
  private dcRouter: DcRouter;
  private options: IUnifiedEmailServerOptions;
  private emailRouter: EmailRouter;
  private domainRegistry: DomainRegistry;
  private servers: any[] = [];
  private stats: IServerStats;
  
  // Add components needed for sending and securing emails
  public dkimCreator: DKIMCreator;
  private ipReputationChecker: IPReputationChecker; // TODO: Implement IP reputation checks in processEmailByMode
  private bounceManager: BounceManager;
  private ipWarmupManager: IPWarmupManager;
  private senderReputationMonitor: SenderReputationMonitor;
  public deliveryQueue: UnifiedDeliveryQueue;
  public deliverySystem: MultiModeDeliverySystem;
  private rateLimiter: UnifiedRateLimiter; // TODO: Implement rate limiting in SMTP server handlers
  private dkimKeys: Map<string, string> = new Map(); // domain -> private key
  private smtpClients: Map<string, SmtpClient> = new Map(); // host:port -> client
  
  constructor(dcRouter: DcRouter, options: IUnifiedEmailServerOptions) {
    super();
    this.dcRouter = dcRouter;
    
    // Set default options
    this.options = {
      ...options,
      banner: options.banner || `${options.hostname} ESMTP UnifiedEmailServer`,
      maxMessageSize: options.maxMessageSize || 10 * 1024 * 1024, // 10MB
      maxClients: options.maxClients || 100,
      maxConnections: options.maxConnections || 1000,
      connectionTimeout: options.connectionTimeout || 60000, // 1 minute
      socketTimeout: options.socketTimeout || 60000 // 1 minute
    };
    
    // Initialize DKIM creator with storage manager
    this.dkimCreator = new DKIMCreator(paths.keysDir, dcRouter.storageManager);
    
    // Initialize IP reputation checker with storage manager
    this.ipReputationChecker = IPReputationChecker.getInstance({
      enableLocalCache: true,
      enableDNSBL: true,
      enableIPInfo: true
    }, dcRouter.storageManager);
    
    // Initialize bounce manager with storage manager
    this.bounceManager = new BounceManager({
      maxCacheSize: 10000,
      cacheTTL: 30 * 24 * 60 * 60 * 1000, // 30 days
      storageManager: dcRouter.storageManager
    });
    
    // Initialize IP warmup manager
    this.ipWarmupManager = IPWarmupManager.getInstance(options.ipWarmupConfig || {
      enabled: true,
      ipAddresses: [],
      targetDomains: []
    });
    
    // Initialize sender reputation monitor with storage manager
    this.senderReputationMonitor = SenderReputationMonitor.getInstance(
      options.reputationMonitorConfig || {
        enabled: true,
        domains: []
      },
      dcRouter.storageManager
    );
    
    // Initialize domain registry
    this.domainRegistry = new DomainRegistry(options.domains, options.defaults);
    
    // Initialize email router with routes and storage manager
    this.emailRouter = new EmailRouter(options.routes || [], {
      storageManager: dcRouter.storageManager,
      persistChanges: true
    });
    
    // Initialize rate limiter
    this.rateLimiter = new UnifiedRateLimiter(options.rateLimits || {
      global: {
        maxConnectionsPerIP: 10,
        maxMessagesPerMinute: 100,
        maxRecipientsPerMessage: 50,
        maxErrorsPerIP: 10,
        maxAuthFailuresPerIP: 5,
        blockDuration: 300000 // 5 minutes
      }
    });
    
    // Initialize delivery components
    const queueOptions: IQueueOptions = {
      storageType: 'memory', // Default to memory storage
      maxRetries: 3,
      baseRetryDelay: 300000, // 5 minutes
      maxRetryDelay: 3600000 // 1 hour
    };
    
    this.deliveryQueue = new UnifiedDeliveryQueue(queueOptions);
    
    const deliveryOptions: IMultiModeDeliveryOptions = {
      globalRateLimit: 100, // Default to 100 emails per minute
      concurrentDeliveries: 10,
      processBounces: true,
      bounceHandler: {
        processSmtpFailure: this.processSmtpFailure.bind(this)
      },
      onDeliverySuccess: async (item, _result) => {
        // Record delivery success event for reputation monitoring
        const email = item.processingResult as Email;
        const senderDomain = email.from.split('@')[1];
        
        if (senderDomain) {
          this.recordReputationEvent(senderDomain, {
            type: 'delivered',
            count: email.to.length
          });
        }
      }
    };
    
    this.deliverySystem = new MultiModeDeliverySystem(this.deliveryQueue, deliveryOptions, this);
    
    // Initialize statistics
    this.stats = {
      startTime: new Date(),
      connections: {
        current: 0,
        total: 0
      },
      messages: {
        processed: 0,
        delivered: 0,
        failed: 0
      },
      processingTime: {
        avg: 0,
        max: 0,
        min: 0
      }
    };
    
    // We'll create the SMTP servers during the start() method
  }
  
  /**
   * Get or create an SMTP client for the given host and port
   * Uses connection pooling for efficiency
   */
  public getSmtpClient(host: string, port: number = 25): SmtpClient {
    const clientKey = `${host}:${port}`;
    
    // Check if we already have a client for this destination
    let client = this.smtpClients.get(clientKey);
    
    if (!client) {
      // Create a new pooled SMTP client
      client = createPooledSmtpClient({
        host,
        port,
        secure: port === 465,
        connectionTimeout: this.options.outbound?.connectionTimeout || 30000,
        socketTimeout: this.options.outbound?.socketTimeout || 120000,
        maxConnections: this.options.outbound?.maxConnections || 10,
        maxMessages: 1000, // Messages per connection before reconnect
        pool: true,
        debug: false
      });
      
      this.smtpClients.set(clientKey, client);
      logger.log('info', `Created new SMTP client pool for ${clientKey}`);
    }
    
    return client;
  }
  
  /**
   * Start the unified email server
   */
  public async start(): Promise<void> {
    logger.log('info', `Starting UnifiedEmailServer on ports: ${(this.options.ports as number[]).join(', ')}`);
    
    try {
      // Initialize the delivery queue
      await this.deliveryQueue.initialize();
      logger.log('info', 'Email delivery queue initialized');
      
      // Start the delivery system
      await this.deliverySystem.start();
      logger.log('info', 'Email delivery system started');
      
      // Set up DKIM for all domains
      await this.setupDkimForDomains();
      logger.log('info', 'DKIM configuration completed for all domains');
      
      // Create DNS manager and ensure all DNS records are created
      const dnsManager = new DnsManager(this.dcRouter);
      await dnsManager.ensureDnsRecords(this.domainRegistry.getAllConfigs(), this.dkimCreator);
      logger.log('info', 'DNS records ensured for all configured domains');
      
      // Apply per-domain rate limits
      this.applyDomainRateLimits();
      logger.log('info', 'Per-domain rate limits configured');
      
      // Check and rotate DKIM keys if needed
      await this.checkAndRotateDkimKeys();
      logger.log('info', 'DKIM key rotation check completed');
      
      // Skip server creation in socket-handler mode
      if (this.options.useSocketHandler) {
        logger.log('info', 'UnifiedEmailServer started in socket-handler mode (no port listening)');
        this.emit('started');
        return;
      }
      
      // Ensure we have the necessary TLS options
      const hasTlsConfig = this.options.tls?.keyPath && this.options.tls?.certPath;
      
      // Prepare the certificate and key if available
      let key: string | undefined;
      let cert: string | undefined;
      
      if (hasTlsConfig) {
        try {
          key = plugins.fs.readFileSync(this.options.tls.keyPath!, 'utf8');
          cert = plugins.fs.readFileSync(this.options.tls.certPath!, 'utf8');
          logger.log('info', 'TLS certificates loaded successfully');
        } catch (error) {
          logger.log('warn', `Failed to load TLS certificates: ${error.message}`);
        }
      }
      
      // Create a SMTP server for each port
      for (const port of this.options.ports as number[]) {
        // Create a reference object to hold the MTA service during setup
        const mtaRef = {
          config: {
            smtp: {
              hostname: this.options.hostname
            },
            security: {
              checkIPReputation: false,
              verifyDkim: true,
              verifySpf: true,
              verifyDmarc: true
            }
          },
          // These will be implemented in the real integration:
          dkimVerifier: {
            verify: async () => ({ isValid: true, domain: '' })
          },
          spfVerifier: {
            verifyAndApply: async () => true
          },
          dmarcVerifier: {
            verify: async () => ({}),
            applyPolicy: () => true
          },
          processIncomingEmail: async (email: Email) => {
            // Process email using the new route-based system
            await this.processEmailByMode(email, { 
              id: 'session-' + Math.random().toString(36).substring(2),
              state: SmtpState.FINISHED,
              mailFrom: email.from,
              rcptTo: email.to,
              emailData: email.toRFC822String(), // Use the proper method to get the full email content
              useTLS: false,
              connectionEnded: true,
              remoteAddress: '127.0.0.1',
              clientHostname: '',
              secure: false,
              authenticated: false,
              envelope: {
                mailFrom: { address: email.from, args: {} },
                rcptTo: email.to.map(recipient => ({ address: recipient, args: {} }))
              }
            });
            
            return true;
          }
        };
        
        // Create server options
        const serverOptions = {
          port,
          hostname: this.options.hostname,
          key,
          cert
        };
        
        // Create and start the SMTP server
        const smtpServer = createSmtpServer(mtaRef as any, serverOptions);
        this.servers.push(smtpServer);
        
        // Start the server
        await new Promise<void>((resolve, reject) => {
          try {
            // Leave this empty for now, smtpServer.start() is handled by the SMTPServer class internally
            // The server is started when it's created
            logger.log('info', `UnifiedEmailServer listening on port ${port}`);
            
            // Event handlers are managed internally by the SmtpServer class
            // No need to access the private server property
            
            resolve();
          } catch (err) {
            if ((err as any).code === 'EADDRINUSE') {
              logger.log('error', `Port ${port} is already in use`);
              reject(new Error(`Port ${port} is already in use`));
            } else {
              logger.log('error', `Error starting server on port ${port}: ${err.message}`);
              reject(err);
            }
          }
        });
      }
      
      logger.log('info', 'UnifiedEmailServer started successfully');
      this.emit('started');
    } catch (error) {
      logger.log('error', `Failed to start UnifiedEmailServer: ${error.message}`);
      throw error;
    }
  }
  
  /**
   * 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)
   */
  public async handleSocket(socket: plugins.net.Socket | plugins.tls.TLSSocket, port: number): Promise<void> {
    if (!this.options.useSocketHandler) {
      logger.log('error', 'handleSocket called but useSocketHandler is not enabled');
      socket.destroy();
      return;
    }
    
    logger.log('info', `Handling socket for port ${port}`);
    
    // Create a temporary SMTP server instance for this connection
    // We need a full server instance because the SMTP protocol handler needs all components
    const smtpServerOptions = {
      port,
      hostname: this.options.hostname,
      key: this.options.tls?.keyPath ? plugins.fs.readFileSync(this.options.tls.keyPath, 'utf8') : undefined,
      cert: this.options.tls?.certPath ? plugins.fs.readFileSync(this.options.tls.certPath, 'utf8') : undefined
    };
    
    // Create the SMTP server instance
    const smtpServer = createSmtpServer(this, smtpServerOptions);
    
    // Get the connection manager from the server
    const connectionManager = (smtpServer as any).connectionManager;
    
    if (!connectionManager) {
      logger.log('error', 'Could not get connection manager from SMTP server');
      socket.destroy();
      return;
    }
    
    // Determine if this is a secure connection
    // Port 465 uses implicit TLS, so the socket is already secure
    const isSecure = port === 465 || socket instanceof plugins.tls.TLSSocket;
    
    // Pass the socket to the connection manager
    try {
      await connectionManager.handleConnection(socket, isSecure);
    } catch (error) {
      logger.log('error', `Error handling socket connection: ${error.message}`);
      socket.destroy();
    }
  }
  
  /**
   * Stop the unified email server
   */
  public async stop(): Promise<void> {
    logger.log('info', 'Stopping UnifiedEmailServer');
    
    try {
      // Clear the servers array - servers will be garbage collected
      this.servers = [];
      
      // Stop the delivery system
      if (this.deliverySystem) {
        await this.deliverySystem.stop();
        logger.log('info', 'Email delivery system stopped');
      }
      
      // Shut down the delivery queue
      if (this.deliveryQueue) {
        await this.deliveryQueue.shutdown();
        logger.log('info', 'Email delivery queue shut down');
      }
      
      // Close all SMTP client connections
      for (const [clientKey, client] of this.smtpClients) {
        try {
          await client.close();
          logger.log('info', `Closed SMTP client pool for ${clientKey}`);
        } catch (error) {
          logger.log('warn', `Error closing SMTP client for ${clientKey}: ${error.message}`);
        }
      }
      this.smtpClients.clear();
      
      logger.log('info', 'UnifiedEmailServer stopped successfully');
      this.emit('stopped');
    } catch (error) {
      logger.log('error', `Error stopping UnifiedEmailServer: ${error.message}`);
      throw error;
    }
  }
  
  
  
  
  
  /**
   * Process email based on routing rules
   */
  public async processEmailByMode(emailData: Email | Buffer, session: IExtendedSmtpSession): Promise<Email> {
    // Convert Buffer to Email if needed
    let email: Email;
    if (Buffer.isBuffer(emailData)) {
      // Parse the email data buffer into an Email object
      try {
        const parsed = await plugins.mailparser.simpleParser(emailData);
        email = new Email({
          from: parsed.from?.value[0]?.address || session.envelope.mailFrom.address,
          to: session.envelope.rcptTo[0]?.address || '',
          subject: parsed.subject || '',
          text: parsed.text || '',
          html: parsed.html || undefined,
          attachments: parsed.attachments?.map(att => ({
            filename: att.filename || '',
            content: att.content,
            contentType: att.contentType
          })) || []
        });
      } catch (error) {
        logger.log('error', `Error parsing email data: ${error.message}`);
        throw new Error(`Error parsing email data: ${error.message}`);
      }
    } else {
      email = emailData;
    }
    
    // First check if this is a bounce notification email
    // Look for common bounce notification subject patterns
    const subject = email.subject || '';
    const isBounceLike = /mail delivery|delivery (failed|status|notification)|failure notice|returned mail|undeliverable|delivery problem/i.test(subject);
    
    if (isBounceLike) {
      logger.log('info', `Email subject matches bounce notification pattern: "${subject}"`);
      
      // Try to process as a bounce
      const isBounce = await this.processBounceNotification(email);
      
      if (isBounce) {
        logger.log('info', 'Successfully processed as bounce notification, skipping regular processing');
        return email;
      }
      
      logger.log('info', 'Not a valid bounce notification, continuing with regular processing');
    }

    // Find matching route
    const context: IEmailContext = { email, session };
    const route = await this.emailRouter.evaluateRoutes(context);
    
    if (!route) {
      // No matching route - reject
      throw new Error('No matching route for email');
    }
    
    // Store matched route in session
    session.matchedRoute = route;
    
    // Execute action based on route
    await this.executeAction(route.action, email, context);
    
    // Return the processed email
    return email;
  }
  
  /**
   * Execute action based on route configuration
   */
  private async executeAction(action: IEmailAction, email: Email, context: IEmailContext): Promise<void> {
    switch (action.type) {
      case 'forward':
        await this.handleForwardAction(action, email, context);
        break;
        
      case 'process':
        await this.handleProcessAction(action, email, context);
        break;
        
      case 'deliver':
        await this.handleDeliverAction(action, email, context);
        break;
        
      case 'reject':
        await this.handleRejectAction(action, email, context);
        break;
        
      default:
        throw new Error(`Unknown action type: ${(action as any).type}`);
    }
  }
  
  /**
   * Handle forward action
   */
  private async handleForwardAction(_action: IEmailAction, email: Email, context: IEmailContext): Promise<void> {
    if (!_action.forward) {
      throw new Error('Forward action requires forward configuration');
    }
    
    const { host, port = 25, auth, addHeaders } = _action.forward;
    
    logger.log('info', `Forwarding email to ${host}:${port}`);
    
    // Add forwarding headers
    if (addHeaders) {
      for (const [key, value] of Object.entries(addHeaders)) {
        email.headers[key] = value;
      }
    }
    
    // Add standard forwarding headers
    email.headers['X-Forwarded-For'] = context.session.remoteAddress || 'unknown';
    email.headers['X-Forwarded-To'] = email.to.join(', ');
    email.headers['X-Forwarded-Date'] = new Date().toISOString();
    
    // Get SMTP client
    const client = this.getSmtpClient(host, port);
    
    try {
      // Send email
      await client.sendMail(email);
      
      logger.log('info', `Successfully forwarded email to ${host}:${port}`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.INFO,
        type: SecurityEventType.EMAIL_FORWARDING,
        message: 'Email forwarded successfully',
        ipAddress: context.session.remoteAddress,
        details: {
          sessionId: context.session.id,
          routeName: context.session.matchedRoute?.name,
          targetHost: host,
          targetPort: port,
          recipients: email.to
        },
        success: true
      });
    } catch (error) {
      logger.log('error', `Failed to forward email: ${error.message}`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.ERROR,
        type: SecurityEventType.EMAIL_FORWARDING,
        message: 'Email forwarding failed',
        ipAddress: context.session.remoteAddress,
        details: {
          sessionId: context.session.id,
          routeName: context.session.matchedRoute?.name,
          targetHost: host,
          targetPort: port,
          error: error.message
        },
        success: false
      });
      
      // Handle as bounce
      for (const recipient of email.getAllRecipients()) {
        await this.bounceManager.processSmtpFailure(recipient, error.message, {
          sender: email.from,
          originalEmailId: email.headers['Message-ID'] as string
        });
      }
      throw error;
    }
  }
  
  /**
   * Handle process action
   */
  private async handleProcessAction(action: IEmailAction, email: Email, context: IEmailContext): Promise<void> {
    logger.log('info', `Processing email with action options`);
    
    // Apply scanning if requested
    if (action.process?.scan) {
      // Use existing content scanner
      // Note: ContentScanner integration would go here
      logger.log('info', 'Content scanning requested');
    }
    
    // Note: DKIM signing will be applied at delivery time to ensure signature validity
    
    // Queue for delivery
    const queue = action.process?.queue || 'normal';
    await this.deliveryQueue.enqueue(email, 'process', context.session.matchedRoute!);
    
    logger.log('info', `Email queued for delivery in ${queue} queue`);
  }
  
  /**
   * Handle deliver action
   */
  private async handleDeliverAction(_action: IEmailAction, email: Email, context: IEmailContext): Promise<void> {
    logger.log('info', `Delivering email locally`);
    
    // Queue for local delivery
    await this.deliveryQueue.enqueue(email, 'mta', context.session.matchedRoute!);
    
    logger.log('info', 'Email queued for local delivery');
  }
  
  /**
   * Handle reject action
   */
  private async handleRejectAction(action: IEmailAction, email: Email, context: IEmailContext): Promise<void> {
    const code = action.reject?.code || 550;
    const message = action.reject?.message || 'Message rejected';
    
    logger.log('info', `Rejecting email with code ${code}: ${message}`);
    
    SecurityLogger.getInstance().logEvent({
      level: SecurityLogLevel.WARN,
      type: SecurityEventType.EMAIL_PROCESSING,
      message: 'Email rejected by routing rule',
      ipAddress: context.session.remoteAddress,
      details: {
        sessionId: context.session.id,
        routeName: context.session.matchedRoute?.name,
        rejectCode: code,
        rejectMessage: message,
        from: email.from,
        to: email.to
      },
      success: false
    });
    
    // Throw error with SMTP code and message
    const error = new Error(message);
    (error as any).responseCode = code;
    throw error;
  }
  
  /**
   * Handle email in MTA mode (programmatic processing)
   */
  private async _handleMtaMode(email: Email, session: IExtendedSmtpSession): Promise<void> {
    logger.log('info', `Handling email in MTA mode for session ${session.id}`);
    
    try {
      // Apply MTA rule options if provided
      if (session.matchedRoute?.action.options?.mtaOptions) {
        const options = session.matchedRoute.action.options.mtaOptions;
        
        // Apply DKIM signing if enabled
        if (options.dkimSign && options.dkimOptions) {
          // Sign the email with DKIM
          logger.log('info', `Signing email with DKIM for domain ${options.dkimOptions.domainName}`);
          
          try {
            // Ensure DKIM keys exist for the domain
            await this.dkimCreator.handleDKIMKeysForDomain(options.dkimOptions.domainName);
            
            // Convert Email to raw format for signing
            const rawEmail = email.toRFC822String();
            
            // Create headers object
            const headers = {};
            for (const [key, value] of Object.entries(email.headers)) {
              headers[key] = value;
            }
            
            // Sign the email
            const signResult = await plugins.dkimSign(rawEmail, {
              canonicalization: 'relaxed/relaxed',
              algorithm: 'rsa-sha256',
              signTime: new Date(),
              signatureData: [
                {
                  signingDomain: options.dkimOptions.domainName,
                  selector: options.dkimOptions.keySelector || 'mta',
                  privateKey: (await this.dkimCreator.readDKIMKeys(options.dkimOptions.domainName)).privateKey,
                  algorithm: 'rsa-sha256',
                  canonicalization: 'relaxed/relaxed'
                }
              ]
            });
            
            // Add the DKIM-Signature header to the email
            if (signResult.signatures) {
              email.addHeader('DKIM-Signature', signResult.signatures);
              logger.log('info', `Successfully added DKIM signature for ${options.dkimOptions.domainName}`);
            }
          } catch (error) {
            logger.log('error', `Failed to sign email with DKIM: ${error.message}`);
          }
        }
      }
      
      // Get email content for logging/processing
      const subject = email.subject;
      const recipients = email.getAllRecipients().join(', ');
      
      logger.log('info', `Email processed by MTA: ${subject} to ${recipients}`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.INFO,
        type: SecurityEventType.EMAIL_PROCESSING,
        message: 'Email processed by MTA',
        ipAddress: session.remoteAddress,
        details: {
          sessionId: session.id,
          ruleName: session.matchedRoute?.name || 'default',
          subject,
          recipients
        },
        success: true
      });
    } catch (error) {
      logger.log('error', `Failed to process email in MTA mode: ${error.message}`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.ERROR,
        type: SecurityEventType.EMAIL_PROCESSING,
        message: 'MTA processing failed',
        ipAddress: session.remoteAddress,
        details: {
          sessionId: session.id,
          ruleName: session.matchedRoute?.name || 'default',
          error: error.message
        },
        success: false
      });
      
      throw error;
    }
  }
  
  /**
   * Handle email in process mode (store-and-forward with scanning)
   */
  private async _handleProcessMode(email: Email, session: IExtendedSmtpSession): Promise<void> {
    logger.log('info', `Handling email in process mode for session ${session.id}`);
    
    try {
      const route = session.matchedRoute;
      
      // Apply content scanning if enabled
      if (route?.action.options?.contentScanning && route.action.options.scanners && route.action.options.scanners.length > 0) {
        logger.log('info', 'Performing content scanning');
        
        // Apply each scanner
        for (const scanner of route.action.options.scanners) {
          switch (scanner.type) {
            case 'spam':
              logger.log('info', 'Scanning for spam content');
              // Implement spam scanning
              break;
              
            case 'virus':
              logger.log('info', 'Scanning for virus content');
              // Implement virus scanning
              break;
              
            case 'attachment':
              logger.log('info', 'Scanning attachments');
              
              // Check for blocked extensions
              if (scanner.blockedExtensions && scanner.blockedExtensions.length > 0) {
                for (const attachment of email.attachments) {
                  const ext = this.getFileExtension(attachment.filename);
                  if (scanner.blockedExtensions.includes(ext)) {
                    if (scanner.action === 'reject') {
                      throw new Error(`Blocked attachment type: ${ext}`);
                    } else { // tag
                      email.addHeader('X-Attachment-Warning', `Potentially unsafe attachment: ${attachment.filename}`);
                    }
                  }
                }
              }
              break;
          }
        }
      }
      
      // Apply transformations if defined
      if (route?.action.options?.transformations && route.action.options.transformations.length > 0) {
        logger.log('info', 'Applying email transformations');
        
        for (const transform of route.action.options.transformations) {
          switch (transform.type) {
            case 'addHeader':
              if (transform.header && transform.value) {
                email.addHeader(transform.header, transform.value);
              }
              break;
          }
        }
      }
      
      logger.log('info', `Email successfully processed in store-and-forward mode`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.INFO,
        type: SecurityEventType.EMAIL_PROCESSING,
        message: 'Email processed and queued',
        ipAddress: session.remoteAddress,
        details: {
          sessionId: session.id,
          ruleName: route?.name || 'default',
          contentScanning: route?.action.options?.contentScanning || false,
          subject: email.subject
        },
        success: true
      });
    } catch (error) {
      logger.log('error', `Failed to process email: ${error.message}`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.ERROR,
        type: SecurityEventType.EMAIL_PROCESSING,
        message: 'Email processing failed',
        ipAddress: session.remoteAddress,
        details: {
          sessionId: session.id,
          ruleName: session.matchedRoute?.name || 'default',
          error: error.message
        },
        success: false
      });
      
      throw error;
    }
  }
  
  /**
   * Get file extension from filename
   */
  private getFileExtension(filename: string): string {
    return filename.substring(filename.lastIndexOf('.')).toLowerCase();
  }
  
  
  
  /**
   * Set up DKIM configuration for all domains
   */
  private async setupDkimForDomains(): Promise<void> {
    const domainConfigs = this.domainRegistry.getAllConfigs();
    
    if (domainConfigs.length === 0) {
      logger.log('warn', 'No domains configured for DKIM');
      return;
    }
    
    for (const domainConfig of domainConfigs) {
      const domain = domainConfig.domain;
      const selector = domainConfig.dkim?.selector || 'default';
      
      try {
        // Check if DKIM keys already exist for this domain
        let keyPair: { privateKey: string; publicKey: string };
        
        try {
          // Try to read existing keys
          keyPair = await this.dkimCreator.readDKIMKeys(domain);
          logger.log('info', `Using existing DKIM keys for domain: ${domain}`);
        } catch (error) {
          // Generate new keys if they don't exist
          keyPair = await this.dkimCreator.createDKIMKeys();
          // Store them for future use
          await this.dkimCreator.createAndStoreDKIMKeys(domain);
          logger.log('info', `Generated new DKIM keys for domain: ${domain}`);
        }
        
        // Store the private key for signing
        this.dkimKeys.set(domain, keyPair.privateKey);
        
        // DNS record creation is now handled by DnsManager
        logger.log('info', `DKIM keys loaded for domain: ${domain} with selector: ${selector}`);
      } catch (error) {
        logger.log('error', `Failed to set up DKIM for domain ${domain}: ${error.message}`);
      }
    }
  }
  
  
  /**
   * Apply per-domain rate limits from domain configurations
   */
  private applyDomainRateLimits(): void {
    const domainConfigs = this.domainRegistry.getAllConfigs();
    
    for (const domainConfig of domainConfigs) {
      if (domainConfig.rateLimits) {
        const domain = domainConfig.domain;
        const rateLimitConfig: any = {};
        
        // Convert domain-specific rate limits to the format expected by UnifiedRateLimiter
        if (domainConfig.rateLimits.outbound) {
          if (domainConfig.rateLimits.outbound.messagesPerMinute) {
            rateLimitConfig.maxMessagesPerMinute = domainConfig.rateLimits.outbound.messagesPerMinute;
          }
          // Note: messagesPerHour and messagesPerDay would need additional implementation in rate limiter
        }
        
        if (domainConfig.rateLimits.inbound) {
          if (domainConfig.rateLimits.inbound.messagesPerMinute) {
            rateLimitConfig.maxMessagesPerMinute = domainConfig.rateLimits.inbound.messagesPerMinute;
          }
          if (domainConfig.rateLimits.inbound.connectionsPerIp) {
            rateLimitConfig.maxConnectionsPerIP = domainConfig.rateLimits.inbound.connectionsPerIp;
          }
          if (domainConfig.rateLimits.inbound.recipientsPerMessage) {
            rateLimitConfig.maxRecipientsPerMessage = domainConfig.rateLimits.inbound.recipientsPerMessage;
          }
        }
        
        // Apply the rate limits if we have any
        if (Object.keys(rateLimitConfig).length > 0) {
          this.rateLimiter.applyDomainLimits(domain, rateLimitConfig);
          logger.log('info', `Applied rate limits for domain ${domain}:`, rateLimitConfig);
        }
      }
    }
  }
  
  /**
   * Check and rotate DKIM keys if needed
   */
  private async checkAndRotateDkimKeys(): Promise<void> {
    const domainConfigs = this.domainRegistry.getAllConfigs();
    
    for (const domainConfig of domainConfigs) {
      const domain = domainConfig.domain;
      const selector = domainConfig.dkim?.selector || 'default';
      const rotateKeys = domainConfig.dkim?.rotateKeys || false;
      const rotationInterval = domainConfig.dkim?.rotationInterval || 90;
      const keySize = domainConfig.dkim?.keySize || 2048;
      
      if (!rotateKeys) {
        logger.log('debug', `DKIM key rotation disabled for ${domain}`);
        continue;
      }
      
      try {
        // Check if keys need rotation
        const needsRotation = await this.dkimCreator.needsRotation(domain, selector, rotationInterval);
        
        if (needsRotation) {
          logger.log('info', `DKIM keys need rotation for ${domain} (selector: ${selector})`);
          
          // Rotate the keys
          const newSelector = await this.dkimCreator.rotateDkimKeys(domain, selector, keySize);
          
          // Update the domain config with new selector
          domainConfig.dkim = {
            ...domainConfig.dkim,
            selector: newSelector
          };
          
          // Re-register DNS handler for new selector if internal-dns mode
          if (domainConfig.dnsMode === 'internal-dns' && this.dcRouter.dnsServer) {
            // Get new public key
            const keyPair = await this.dkimCreator.readDKIMKeysForSelector(domain, newSelector);
            const publicKeyBase64 = keyPair.publicKey
              .replace(/-----BEGIN PUBLIC KEY-----/g, '')
              .replace(/-----END PUBLIC KEY-----/g, '')
              .replace(/\s/g, '');
            
            const ttl = domainConfig.dns?.internal?.ttl || 3600;
            
            // Register new selector
            this.dcRouter.dnsServer.registerHandler(
              `${newSelector}._domainkey.${domain}`,
              ['TXT'],
              () => ({
                name: `${newSelector}._domainkey.${domain}`,
                type: 'TXT',
                class: 'IN',
                ttl: ttl,
                data: `v=DKIM1; k=rsa; p=${publicKeyBase64}`
              })
            );
            
            logger.log('info', `DKIM DNS handler registered for new selector: ${newSelector}._domainkey.${domain}`);
            
            // Store the updated public key in storage
            await this.dcRouter.storageManager.set(
              `/email/dkim/${domain}/public.key`,
              keyPair.publicKey
            );
          }
          
          // Clean up old keys after grace period (async, don't wait)
          this.dkimCreator.cleanupOldKeys(domain, 30).catch(error => {
            logger.log('warn', `Failed to cleanup old DKIM keys for ${domain}: ${error.message}`);
          });
          
        } else {
          logger.log('debug', `DKIM keys for ${domain} are up to date`);
        }
      } catch (error) {
        logger.log('error', `Failed to check/rotate DKIM keys for ${domain}: ${error.message}`);
      }
    }
  }
  
  
  /**
   * Generate SmartProxy routes for email ports
   */
  public generateProxyRoutes(portMapping?: Record<number, number>): any[] {
    const routes: any[] = [];
    const defaultPortMapping = {
      25: 10025,
      587: 10587,
      465: 10465
    };
    
    const actualPortMapping = portMapping || defaultPortMapping;
    
    // Generate routes for each configured port
    for (const externalPort of this.options.ports) {
      const internalPort = actualPortMapping[externalPort] || externalPort + 10000;
      
      let routeName = 'email-route';
      let tlsMode = 'passthrough';
      
      // Configure based on port
      switch (externalPort) {
        case 25:
          routeName = 'smtp-route';
          tlsMode = 'passthrough'; // STARTTLS
          break;
        case 587:
          routeName = 'submission-route';
          tlsMode = 'passthrough'; // STARTTLS
          break;
        case 465:
          routeName = 'smtps-route';
          tlsMode = 'terminate'; // Implicit TLS
          break;
        default:
          routeName = `email-port-${externalPort}-route`;
      }
      
      routes.push({
        name: routeName,
        match: {
          ports: [externalPort]
        },
        action: {
          type: 'forward',
          target: {
            host: 'localhost',
            port: internalPort
          },
          tls: {
            mode: tlsMode
          }
        }
      });
    }
    
    return routes;
  }
  
  /**
   * Update server configuration
   */
  public updateOptions(options: Partial<IUnifiedEmailServerOptions>): void {
    // Stop the server if changing ports
    const portsChanged = options.ports && 
      (!this.options.ports || 
       JSON.stringify(options.ports) !== JSON.stringify(this.options.ports));
    
    if (portsChanged) {
      this.stop().then(() => {
        this.options = { ...this.options, ...options };
        this.start();
      });
    } else {
      // Update options without restart
      this.options = { ...this.options, ...options };
      
      // Update domain registry if domains changed
      if (options.domains) {
        this.domainRegistry = new DomainRegistry(options.domains, options.defaults || this.options.defaults);
      }
      
      // Update email router if routes changed
      if (options.routes) {
        this.emailRouter.updateRoutes(options.routes);
      }
    }
  }
  
  /**
   * Update email routes
   */
  public updateEmailRoutes(routes: IEmailRoute[]): void {
    this.options.routes = routes;
    this.emailRouter.updateRoutes(routes);
  }
  
  /**
   * Get server statistics
   */
  public getStats(): IServerStats {
    return { ...this.stats };
  }
  
  /**
   * Get domain registry
   */
  public getDomainRegistry(): DomainRegistry {
    return this.domainRegistry;
  }
  
  /**
   * Update email routes dynamically
   */
  public updateRoutes(routes: IEmailRoute[]): void {
    this.emailRouter.setRoutes(routes);
    logger.log('info', `Updated email routes with ${routes.length} routes`);
  }
  
  /**
   * 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
   */
  public async sendEmail(
    email: Email, 
    mode: EmailProcessingMode = 'mta', 
    route?: IEmailRoute, 
    options?: {
      skipSuppressionCheck?: boolean;
      ipAddress?: string;
      isTransactional?: boolean;
    }
  ): Promise<string> {
    logger.log('info', `Sending email: ${email.subject} to ${email.to.join(', ')}`);
    
    try {
      // Validate the email
      if (!email.from) {
        throw new Error('Email must have a sender address');
      }
      
      if (!email.to || email.to.length === 0) {
        throw new Error('Email must have at least one recipient');
      }
      
      // Check if any recipients are on the suppression list (unless explicitly skipped)
      if (!options?.skipSuppressionCheck) {
        const suppressedRecipients = email.to.filter(recipient => this.isEmailSuppressed(recipient));
        
        if (suppressedRecipients.length > 0) {
          // Filter out suppressed recipients
          const originalCount = email.to.length;
          const suppressed = suppressedRecipients.map(recipient => {
            const info = this.getSuppressionInfo(recipient);
            return {
              email: recipient,
              reason: info?.reason || 'Unknown',
              until: info?.expiresAt ? new Date(info.expiresAt).toISOString() : 'permanent'
            };
          });
          
          logger.log('warn', `Filtering out ${suppressedRecipients.length} suppressed recipient(s)`, { suppressed });
          
          // If all recipients are suppressed, throw an error
          if (suppressedRecipients.length === originalCount) {
            throw new Error('All recipients are on the suppression list');
          }
          
          // Filter the recipients list to only include non-suppressed addresses
          email.to = email.to.filter(recipient => !this.isEmailSuppressed(recipient));
        }
      }
      
      // IP warmup handling
      let ipAddress = options?.ipAddress;
      
      // If no specific IP was provided, use IP warmup manager to find the best IP
      if (!ipAddress) {
        const domain = email.from.split('@')[1];
        
        ipAddress = this.getBestIPForSending({
          from: email.from,
          to: email.to,
          domain,
          isTransactional: options?.isTransactional
        });
        
        if (ipAddress) {
          logger.log('info', `Selected IP ${ipAddress} for sending based on warmup status`);
        }
      }
      
      // If an IP is provided or selected by warmup manager, check its capacity
      if (ipAddress) {
        // Check if the IP can send more today
        if (!this.canIPSendMoreToday(ipAddress)) {
          logger.log('warn', `IP ${ipAddress} has reached its daily sending limit, email will be queued for later delivery`);
        }
        
        // Check if the IP can send more this hour
        if (!this.canIPSendMoreThisHour(ipAddress)) {
          logger.log('warn', `IP ${ipAddress} has reached its hourly sending limit, email will be queued for later delivery`);
        }
        
        // Record the send for IP warmup tracking
        this.recordIPSend(ipAddress);
        
        // Add IP header to the email
        email.addHeader('X-Sending-IP', ipAddress);
      }
      
      // Check if the sender domain has DKIM keys and sign the email if needed
      if (mode === 'mta' && route?.action.options?.mtaOptions?.dkimSign) {
        const domain = email.from.split('@')[1];
        await this.handleDkimSigning(email, domain, route.action.options.mtaOptions.dkimOptions?.keySelector || 'mta');
      }
      
      // Generate a unique ID for this email
      const id = plugins.uuid.v4();
      
      // Queue the email for delivery
      await this.deliveryQueue.enqueue(email, mode, route);
      
      // Record 'sent' event for domain reputation monitoring
      const senderDomain = email.from.split('@')[1];
      if (senderDomain) {
        this.recordReputationEvent(senderDomain, {
          type: 'sent',
          count: email.to.length
        });
      }
      
      logger.log('info', `Email queued with ID: ${id}`);
      return id;
    } catch (error) {
      logger.log('error', `Failed to send email: ${error.message}`);
      throw error;
    }
  }
  
  /**
   * 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 async handleDkimSigning(email: Email, domain: string, selector: string): Promise<void> {
    try {
      // Ensure we have DKIM keys for this domain
      await this.dkimCreator.handleDKIMKeysForDomain(domain);
      
      // Get the private key
      const { privateKey } = await this.dkimCreator.readDKIMKeys(domain);
      
      // Convert Email to raw format for signing
      const rawEmail = email.toRFC822String();
      
      // Sign the email
      const signResult = await plugins.dkimSign(rawEmail, {
        canonicalization: 'relaxed/relaxed',
        algorithm: 'rsa-sha256',
        signTime: new Date(),
        signatureData: [
          {
            signingDomain: domain,
            selector: selector,
            privateKey: privateKey,
            algorithm: 'rsa-sha256',
            canonicalization: 'relaxed/relaxed'
          }
        ]
      });
      
      // Add the DKIM-Signature header to the email
      if (signResult.signatures) {
        email.addHeader('DKIM-Signature', signResult.signatures);
        logger.log('info', `Successfully added DKIM signature for ${domain}`);
      }
    } catch (error) {
      logger.log('error', `Failed to sign email with DKIM: ${error.message}`);
      // Continue without DKIM rather than failing the send
    }
  }
  
  /**
   * Process a bounce notification email
   * @param bounceEmail The email containing bounce notification information
   * @returns Processed bounce record or null if not a bounce
   */
  public async processBounceNotification(bounceEmail: Email): Promise<boolean> {
    logger.log('info', 'Processing potential bounce notification email');
    
    try {
      // Process as a bounce notification (no conversion needed anymore)
      const bounceRecord = await this.bounceManager.processBounceEmail(bounceEmail);
      
      if (bounceRecord) {
        logger.log('info', `Successfully processed bounce notification for ${bounceRecord.recipient}`, {
          bounceType: bounceRecord.bounceType,
          bounceCategory: bounceRecord.bounceCategory
        });
        
        // Notify any registered listeners about the bounce
        this.emit('bounceProcessed', bounceRecord);
        
        // Record bounce event for domain reputation tracking
        if (bounceRecord.domain) {
          this.recordReputationEvent(bounceRecord.domain, {
            type: 'bounce',
            hardBounce: bounceRecord.bounceCategory === BounceCategory.HARD,
            receivingDomain: bounceRecord.recipient.split('@')[1]
          });
        }
        
        // Log security event
        SecurityLogger.getInstance().logEvent({
          level: SecurityLogLevel.INFO,
          type: SecurityEventType.EMAIL_VALIDATION,
          message: `Bounce notification processed for recipient`,
          domain: bounceRecord.domain,
          details: {
            recipient: bounceRecord.recipient,
            bounceType: bounceRecord.bounceType,
            bounceCategory: bounceRecord.bounceCategory
          },
          success: true
        });
        
        return true;
      } else {
        logger.log('info', 'Email not recognized as a bounce notification');
        return false;
      }
    } catch (error) {
      logger.log('error', `Error processing bounce notification: ${error.message}`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.ERROR,
        type: SecurityEventType.EMAIL_VALIDATION,
        message: 'Failed to process bounce notification',
        details: {
          error: error.message,
          subject: bounceEmail.subject
        },
        success: false
      });
      
      return false;
    }
  }
  
  /**
   * 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
   */
  public async processSmtpFailure(
    recipient: string,
    smtpResponse: string,
    options: {
      sender?: string;
      originalEmailId?: string;
      statusCode?: string;
      headers?: Record<string, string>;
    } = {}
  ): Promise<boolean> {
    logger.log('info', `Processing SMTP failure for ${recipient}: ${smtpResponse}`);
    
    try {
      // Process the SMTP failure through the bounce manager
      const bounceRecord = await this.bounceManager.processSmtpFailure(
        recipient,
        smtpResponse,
        options
      );
      
      logger.log('info', `Successfully processed SMTP failure for ${recipient} as ${bounceRecord.bounceCategory} bounce`, {
        bounceType: bounceRecord.bounceType
      });
      
      // Notify any registered listeners about the bounce
      this.emit('bounceProcessed', bounceRecord);
      
      // Record bounce event for domain reputation tracking
      if (bounceRecord.domain) {
        this.recordReputationEvent(bounceRecord.domain, {
          type: 'bounce',
          hardBounce: bounceRecord.bounceCategory === BounceCategory.HARD,
          receivingDomain: bounceRecord.recipient.split('@')[1]
        });
      }
      
      // Log security event
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.INFO,
        type: SecurityEventType.EMAIL_VALIDATION,
        message: `SMTP failure processed for recipient`,
        domain: bounceRecord.domain,
        details: {
          recipient: bounceRecord.recipient,
          bounceType: bounceRecord.bounceType,
          bounceCategory: bounceRecord.bounceCategory,
          smtpResponse
        },
        success: true
      });
      
      return true;
    } catch (error) {
      logger.log('error', `Error processing SMTP failure: ${error.message}`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.ERROR, 
        type: SecurityEventType.EMAIL_VALIDATION,
        message: 'Failed to process SMTP failure',
        details: {
          recipient,
          smtpResponse,
          error: error.message
        },
        success: false
      });
      
      return false;
    }
  }
  
  /**
   * Check if an email address is suppressed (has bounced previously)
   * @param email Email address to check
   * @returns Whether the email is suppressed
   */
  public isEmailSuppressed(email: string): boolean {
    return this.bounceManager.isEmailSuppressed(email);
  }
  
  /**
   * Get suppression information for an email
   * @param email Email address to check
   * @returns Suppression information or null if not suppressed
   */
  public getSuppressionInfo(email: string): {
    reason: string;
    timestamp: number;
    expiresAt?: number;
  } | null {
    return this.bounceManager.getSuppressionInfo(email);
  }
  
  /**
   * Get bounce history information for an email
   * @param email Email address to check
   * @returns Bounce history or null if no bounces
   */
  public getBounceHistory(email: string): {
    lastBounce: number;
    count: number;
    type: BounceType;
    category: BounceCategory;
  } | null {
    return this.bounceManager.getBounceInfo(email);
  }
  
  /**
   * Get all suppressed email addresses
   * @returns Array of suppressed email addresses
   */
  public getSuppressionList(): string[] {
    return this.bounceManager.getSuppressionList();
  }
  
  /**
   * Get all hard bounced email addresses
   * @returns Array of hard bounced email addresses
   */
  public getHardBouncedAddresses(): string[] {
    return this.bounceManager.getHardBouncedAddresses();
  }
  
  /**
   * 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)
   */
  public addToSuppressionList(email: string, reason: string, expiresAt?: number): void {
    this.bounceManager.addToSuppressionList(email, reason, expiresAt);
    logger.log('info', `Added ${email} to suppression list: ${reason}`);
  }
  
  /**
   * Remove an email from the suppression list
   * @param email Email address to remove from suppression
   */
  public removeFromSuppressionList(email: string): void {
    this.bounceManager.removeFromSuppressionList(email);
    logger.log('info', `Removed ${email} from suppression list`);
  }
  
  /**
   * Get the status of IP warmup process
   * @param ipAddress Optional specific IP to check
   * @returns Status of IP warmup
   */
  public getIPWarmupStatus(ipAddress?: string): any {
    return this.ipWarmupManager.getWarmupStatus(ipAddress);
  }
  
  /**
   * Add a new IP address to the warmup process
   * @param ipAddress IP address to add
   */
  public addIPToWarmup(ipAddress: string): void {
    this.ipWarmupManager.addIPToWarmup(ipAddress);
  }
  
  /**
   * Remove an IP address from the warmup process
   * @param ipAddress IP address to remove
   */
  public removeIPFromWarmup(ipAddress: string): void {
    this.ipWarmupManager.removeIPFromWarmup(ipAddress);
  }
  
  /**
   * Update metrics for an IP in the warmup process
   * @param ipAddress IP address
   * @param metrics Metrics to update
   */
  public updateIPWarmupMetrics(
    ipAddress: string,
    metrics: { openRate?: number; bounceRate?: number; complaintRate?: number }
  ): void {
    this.ipWarmupManager.updateMetrics(ipAddress, metrics);
  }
  
  /**
   * Check if an IP can send more emails today
   * @param ipAddress IP address to check
   * @returns Whether the IP can send more today
   */
  public canIPSendMoreToday(ipAddress: string): boolean {
    return this.ipWarmupManager.canSendMoreToday(ipAddress);
  }
  
  /**
   * 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
   */
  public canIPSendMoreThisHour(ipAddress: string): boolean {
    return this.ipWarmupManager.canSendMoreThisHour(ipAddress);
  }
  
  /**
   * 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
   */
  public getBestIPForSending(emailInfo: {
    from: string;
    to: string[];
    domain: string;
    isTransactional?: boolean;
  }): string | null {
    return this.ipWarmupManager.getBestIPForSending(emailInfo);
  }
  
  /**
   * Set the active IP allocation policy for warmup
   * @param policyName Name of the policy to set
   */
  public setIPAllocationPolicy(policyName: string): void {
    this.ipWarmupManager.setActiveAllocationPolicy(policyName);
  }
  
  /**
   * Record that an email was sent using a specific IP
   * @param ipAddress IP address used for sending
   */
  public recordIPSend(ipAddress: string): void {
    this.ipWarmupManager.recordSend(ipAddress);
  }
  
  /**
   * Get reputation data for a domain
   * @param domain Domain to get reputation for
   * @returns Domain reputation metrics
   */
  public getDomainReputationData(domain: string): any {
    return this.senderReputationMonitor.getReputationData(domain);
  }
  
  /**
   * Get summary reputation data for all monitored domains
   * @returns Summary data for all domains
   */
  public getReputationSummary(): any {
    return this.senderReputationMonitor.getReputationSummary();
  }
  
  /**
   * Add a domain to the reputation monitoring system
   * @param domain Domain to add
   */
  public addDomainToMonitoring(domain: string): void {
    this.senderReputationMonitor.addDomain(domain);
  }
  
  /**
   * Remove a domain from the reputation monitoring system
   * @param domain Domain to remove
   */
  public removeDomainFromMonitoring(domain: string): void {
    this.senderReputationMonitor.removeDomain(domain);
  }
  
  /**
   * Record an email event for domain reputation tracking
   * @param domain Domain sending the email
   * @param event Event details
   */
  public recordReputationEvent(domain: string, event: {
    type: 'sent' | 'delivered' | 'bounce' | 'complaint' | 'open' | 'click';
    count?: number;
    hardBounce?: boolean;
    receivingDomain?: string;
  }): void {
    this.senderReputationMonitor.recordSendEvent(domain, event);
  }
  
  /**
   * Check if DKIM key exists for a domain
   * @param domain Domain to check
   */
  public hasDkimKey(domain: string): boolean {
    return this.dkimKeys.has(domain);
  }
  
  /**
   * Record successful email delivery
   * @param domain Sending domain
   */
  public recordDelivery(domain: string): void {
    this.recordReputationEvent(domain, {
      type: 'delivered',
      count: 1
    });
  }
  
  /**
   * Record email bounce
   * @param domain Sending domain
   * @param receivingDomain Receiving domain that bounced
   * @param bounceType Type of bounce (hard/soft)
   * @param reason Bounce reason
   */
  public recordBounce(domain: string, receivingDomain: string, bounceType: 'hard' | 'soft', reason: string): void {
    // Record bounce in bounce manager
    const bounceRecord = {
      id: `bounce_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
      recipient: `user@${receivingDomain}`,
      sender: `user@${domain}`,
      domain: domain,
      bounceType: bounceType === 'hard' ? BounceType.INVALID_RECIPIENT : BounceType.TEMPORARY_FAILURE,
      bounceCategory: bounceType === 'hard' ? BounceCategory.HARD : BounceCategory.SOFT,
      timestamp: Date.now(),
      smtpResponse: reason,
      diagnosticCode: reason,
      statusCode: bounceType === 'hard' ? '550' : '450',
      processed: false
    };
    
    // Process the bounce
    this.bounceManager.processBounce(bounceRecord);
    
    // Record reputation event
    this.recordReputationEvent(domain, {
      type: 'bounce',
      count: 1,
      hardBounce: bounceType === 'hard',
      receivingDomain
    });
  }
  
  /**
   * Get the rate limiter instance
   * @returns The unified rate limiter
   */
  public getRateLimiter(): UnifiedRateLimiter {
    return this.rateLimiter;
  }
}