655 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			655 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * SMTP Server Interfaces
 | |
|  * Defines all the interfaces used by the SMTP server implementation
 | |
|  */
 | |
| 
 | |
| import * as plugins from '../../../plugins.ts';
 | |
| import type { Email } from '../../core/classes.email.ts';
 | |
| import type { UnifiedEmailServer } from '../../routing/classes.unified.email.server.ts';
 | |
| 
 | |
| // Re-export types from other modules  
 | |
| import { SmtpState } from '../interfaces.ts';
 | |
| import { SmtpCommand } from './constants.ts';
 | |
| export { SmtpState, SmtpCommand };
 | |
| export type { IEnvelopeRecipient } from '../interfaces.ts';
 | |
| 
 | |
| /**
 | |
|  * Interface for components that need cleanup
 | |
|  */
 | |
| export interface IDestroyable {
 | |
|   /**
 | |
|    * Clean up all resources (timers, listeners, etc)
 | |
|    */
 | |
|   destroy(): void | Promise<void>;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * SMTP authentication credentials
 | |
|  */
 | |
| export interface ISmtpAuth {
 | |
|   /**
 | |
|    * Username for authentication
 | |
|    */
 | |
|   username: string;
 | |
|   
 | |
|   /**
 | |
|    * Password for authentication
 | |
|    */
 | |
|   password: string;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * SMTP envelope (sender and recipients)
 | |
|  */
 | |
| export interface ISmtpEnvelope {
 | |
|   /**
 | |
|    * Mail from address
 | |
|    */
 | |
|   mailFrom: {
 | |
|     address: string;
 | |
|     args?: Record<string, string>;
 | |
|   };
 | |
|   
 | |
|   /**
 | |
|    * Recipients list
 | |
|    */
 | |
|   rcptTo: Array<{
 | |
|     address: string;
 | |
|     args?: Record<string, string>;
 | |
|   }>;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * SMTP session representing a client connection
 | |
|  */
 | |
| export interface ISmtpSession {
 | |
|   /**
 | |
|    * Unique session identifier
 | |
|    */
 | |
|   id: string;
 | |
|   
 | |
|   /**
 | |
|    * Current state of the SMTP session
 | |
|    */
 | |
|   state: SmtpState;
 | |
|   
 | |
|   /**
 | |
|    * Client's hostname from EHLO/HELO
 | |
|    */
 | |
|   clientHostname: string | null;
 | |
|   
 | |
|   /**
 | |
|    * Whether TLS is active for this session
 | |
|    */
 | |
|   secure: boolean;
 | |
|   
 | |
|   /**
 | |
|    * Authentication status
 | |
|    */
 | |
|   authenticated: boolean;
 | |
|   
 | |
|   /**
 | |
|    * Authentication username if authenticated
 | |
|    */
 | |
|   username?: string;
 | |
|   
 | |
|   /**
 | |
|    * Transaction envelope
 | |
|    */
 | |
|   envelope: ISmtpEnvelope;
 | |
|   
 | |
|   /**
 | |
|    * When the session was created
 | |
|    */
 | |
|   createdAt: Date;
 | |
|   
 | |
|   /**
 | |
|    * Last activity timestamp
 | |
|    */
 | |
|   lastActivity: number;
 | |
|   
 | |
|   /**
 | |
|    * Client's IP address
 | |
|    */
 | |
|   remoteAddress: string;
 | |
|   
 | |
|   /**
 | |
|    * Client's port
 | |
|    */
 | |
|   remotePort: number;
 | |
|   
 | |
|   /**
 | |
|    * Additional session data
 | |
|    */
 | |
|   data?: Record<string, any>;
 | |
|   
 | |
|   /**
 | |
|    * Message size if SIZE extension is used
 | |
|    */
 | |
|   messageSize?: number;
 | |
|   
 | |
|   /**
 | |
|    * Server capabilities advertised to client
 | |
|    */
 | |
|   capabilities?: string[];
 | |
|   
 | |
|   /**
 | |
|    * Buffer for incomplete data
 | |
|    */
 | |
|   dataBuffer?: string;
 | |
|   
 | |
|   /**
 | |
|    * Flag to track if we're currently receiving DATA
 | |
|    */
 | |
|   receivingData?: boolean;
 | |
|   
 | |
|   /**
 | |
|    * The raw email data being received
 | |
|    */
 | |
|   rawData?: string;
 | |
|   
 | |
|   /**
 | |
|    * Greeting sent to client
 | |
|    */
 | |
|   greeting?: string;
 | |
|   
 | |
|   /**
 | |
|    * Whether EHLO has been sent
 | |
|    */
 | |
|   ehloSent?: boolean;
 | |
|   
 | |
|   /**
 | |
|    * Whether HELO has been sent
 | |
|    */
 | |
|   heloSent?: boolean;
 | |
|   
 | |
|   /**
 | |
|    * TLS options for this session
 | |
|    */
 | |
|   tlsOptions?: any;
 | |
|   
 | |
|   /**
 | |
|    * Whether TLS is being used
 | |
|    */
 | |
|   useTLS?: boolean;
 | |
|   
 | |
|   /**
 | |
|    * Mail from address for this transaction
 | |
|    */
 | |
|   mailFrom?: string;
 | |
|   
 | |
|   /**
 | |
|    * Recipients for this transaction
 | |
|    */
 | |
|   rcptTo?: string[];
 | |
|   
 | |
|   /**
 | |
|    * Email data being received
 | |
|    */
 | |
|   emailData?: string;
 | |
|   
 | |
|   /**
 | |
|    * Chunks of email data
 | |
|    */
 | |
|   emailDataChunks?: string[];
 | |
|   
 | |
|   /**
 | |
|    * Timeout ID for data reception
 | |
|    */
 | |
|   dataTimeoutId?: NodeJS.Timeout;
 | |
|   
 | |
|   /**
 | |
|    * Whether connection has ended
 | |
|    */
 | |
|   connectionEnded?: boolean;
 | |
|   
 | |
|   /**
 | |
|    * Size of email data being received
 | |
|    */
 | |
|   emailDataSize?: number;
 | |
|   
 | |
|   /**
 | |
|    * Processing mode for this session
 | |
|    */
 | |
|   processingMode?: string;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Session manager interface
 | |
|  */
 | |
| export interface ISessionManager extends IDestroyable {
 | |
|   /**
 | |
|    * Create a new session for a socket
 | |
|    */
 | |
|   createSession(socket: plugins.net.Socket | plugins.tls.TLSSocket, secure?: boolean): ISmtpSession;
 | |
|   
 | |
|   /**
 | |
|    * Get session by socket
 | |
|    */
 | |
|   getSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): ISmtpSession | undefined;
 | |
|   
 | |
|   /**
 | |
|    * Update session state
 | |
|    */
 | |
|   updateSessionState(session: ISmtpSession, newState: SmtpState): void;
 | |
|   
 | |
|   /**
 | |
|    * Remove a session
 | |
|    */
 | |
|   removeSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
 | |
|   
 | |
|   /**
 | |
|    * Clear all sessions
 | |
|    */
 | |
|   clearAllSessions(): void;
 | |
|   
 | |
|   /**
 | |
|    * Get all active sessions
 | |
|    */
 | |
|   getAllSessions(): ISmtpSession[];
 | |
|   
 | |
|   /**
 | |
|    * Get session count
 | |
|    */
 | |
|   getSessionCount(): number;
 | |
|   
 | |
|   /**
 | |
|    * Update last activity for a session
 | |
|    */
 | |
|   updateLastActivity(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
 | |
|   
 | |
|   /**
 | |
|    * Check for timed out sessions
 | |
|    */
 | |
|   checkTimeouts(timeoutMs: number): ISmtpSession[];
 | |
|   
 | |
|   /**
 | |
|    * Update session activity timestamp
 | |
|    */
 | |
|   updateSessionActivity(session: ISmtpSession): void;
 | |
|   
 | |
|   /**
 | |
|    * Replace socket in session (for TLS upgrade)
 | |
|    */
 | |
|   replaceSocket(oldSocket: plugins.net.Socket | plugins.tls.TLSSocket, newSocket: plugins.net.Socket | plugins.tls.TLSSocket): boolean;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Connection manager interface
 | |
|  */
 | |
| export interface IConnectionManager extends IDestroyable {
 | |
|   /**
 | |
|    * Handle a new connection
 | |
|    */
 | |
|   handleConnection(socket: plugins.net.Socket | plugins.tls.TLSSocket, secure: boolean): Promise<void>;
 | |
|   
 | |
|   /**
 | |
|    * Close all active connections
 | |
|    */
 | |
|   closeAllConnections(): void;
 | |
|   
 | |
|   /**
 | |
|    * Get active connection count
 | |
|    */
 | |
|   getConnectionCount(): number;
 | |
|   
 | |
|   /**
 | |
|    * Check if accepting new connections
 | |
|    */
 | |
|   canAcceptConnection(): boolean;
 | |
|   
 | |
|   /**
 | |
|    * Handle new connection (legacy method name)
 | |
|    */
 | |
|   handleNewConnection(socket: plugins.net.Socket): Promise<void>;
 | |
|   
 | |
|   /**
 | |
|    * Handle new secure connection (legacy method name)
 | |
|    */
 | |
|   handleNewSecureConnection(socket: plugins.tls.TLSSocket): Promise<void>;
 | |
|   
 | |
|   /**
 | |
|    * Setup socket event handlers
 | |
|    */
 | |
|   setupSocketEventHandlers(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Command handler interface
 | |
|  */
 | |
| export interface ICommandHandler extends IDestroyable {
 | |
|   /**
 | |
|    * Handle an SMTP command
 | |
|    */
 | |
|   handleCommand(
 | |
|     socket: plugins.net.Socket | plugins.tls.TLSSocket,
 | |
|     command: SmtpCommand,
 | |
|     args: string,
 | |
|     session: ISmtpSession
 | |
|   ): Promise<void>;
 | |
|   
 | |
|   /**
 | |
|    * Get supported commands for current session state
 | |
|    */
 | |
|   getSupportedCommands(session: ISmtpSession): SmtpCommand[];
 | |
|   
 | |
|   /**
 | |
|    * Process command (legacy method name)
 | |
|    */
 | |
|   processCommand(socket: plugins.net.Socket | plugins.tls.TLSSocket, command: string): Promise<void>;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Data handler interface
 | |
|  */
 | |
| export interface IDataHandler extends IDestroyable {
 | |
|   /**
 | |
|    * Handle email data
 | |
|    */
 | |
|   handleData(
 | |
|     socket: plugins.net.Socket | plugins.tls.TLSSocket,
 | |
|     data: string,
 | |
|     session: ISmtpSession
 | |
|   ): Promise<void>;
 | |
|   
 | |
|   /**
 | |
|    * Process a complete email
 | |
|    */
 | |
|   processEmail(
 | |
|     rawData: string,
 | |
|     session: ISmtpSession
 | |
|   ): Promise<Email>;
 | |
|   
 | |
|   /**
 | |
|    * Handle data received (legacy method name)
 | |
|    */
 | |
|   handleDataReceived(socket: plugins.net.Socket | plugins.tls.TLSSocket, data: string): Promise<void>;
 | |
|   
 | |
|   /**
 | |
|    * Process email data (legacy method name)
 | |
|    */
 | |
|   processEmailData(socket: plugins.net.Socket | plugins.tls.TLSSocket, data: string): Promise<void>;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * TLS handler interface
 | |
|  */
 | |
| export interface ITlsHandler extends IDestroyable {
 | |
|   /**
 | |
|    * Handle STARTTLS command
 | |
|    */
 | |
|   handleStartTls(
 | |
|     socket: plugins.net.Socket,
 | |
|     session: ISmtpSession
 | |
|   ): Promise<plugins.tls.TLSSocket | null>;
 | |
|   
 | |
|   /**
 | |
|    * Check if TLS is available
 | |
|    */
 | |
|   isTlsAvailable(): boolean;
 | |
|   
 | |
|   /**
 | |
|    * Get TLS options
 | |
|    */
 | |
|   getTlsOptions(): plugins.tls.TlsOptions;
 | |
|   
 | |
|   /**
 | |
|    * Check if TLS is enabled
 | |
|    */
 | |
|   isTlsEnabled(): boolean;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Security handler interface
 | |
|  */
 | |
| export interface ISecurityHandler extends IDestroyable {
 | |
|   /**
 | |
|    * Check IP reputation
 | |
|    */
 | |
|   checkIpReputation(socket: plugins.net.Socket | plugins.tls.TLSSocket): Promise<boolean>;
 | |
|   
 | |
|   /**
 | |
|    * Validate email address
 | |
|    */
 | |
|   isValidEmail(email: string): boolean;
 | |
|   
 | |
|   /**
 | |
|    * Authenticate user
 | |
|    */
 | |
|   authenticate(auth: ISmtpAuth): Promise<boolean>;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * SMTP server options
 | |
|  */
 | |
| export interface ISmtpServerOptions {
 | |
|   /**
 | |
|    * Port to listen on
 | |
|    */
 | |
|   port: number;
 | |
|   
 | |
|   /**
 | |
|    * Hostname of the server
 | |
|    */
 | |
|   hostname: string;
 | |
|   
 | |
|   /**
 | |
|    * Host to bind to (optional, defaults to 0.0.0.0)
 | |
|    */
 | |
|   host?: string;
 | |
|   
 | |
|   /**
 | |
|    * Secure port for TLS connections
 | |
|    */
 | |
|   securePort?: number;
 | |
|   
 | |
|   /**
 | |
|    * TLS/SSL private key (PEM format)
 | |
|    */
 | |
|   key?: string;
 | |
|   
 | |
|   /**
 | |
|    * TLS/SSL certificate (PEM format)
 | |
|    */
 | |
|   cert?: string;
 | |
|   
 | |
|   /**
 | |
|    * CA certificates for TLS (PEM format)
 | |
|    */
 | |
|   ca?: string;
 | |
|   
 | |
|   /**
 | |
|    * Maximum size of messages in bytes
 | |
|    */
 | |
|   maxSize?: number;
 | |
|   
 | |
|   /**
 | |
|    * Maximum number of concurrent connections
 | |
|    */
 | |
|   maxConnections?: number;
 | |
|   
 | |
|   /**
 | |
|    * Authentication options
 | |
|    */
 | |
|   auth?: {
 | |
|     /**
 | |
|      * Whether authentication is required
 | |
|      */
 | |
|     required: boolean;
 | |
|     
 | |
|     /**
 | |
|      * Allowed authentication methods
 | |
|      */
 | |
|     methods: ('PLAIN' | 'LOGIN' | 'OAUTH2')[];
 | |
|   };
 | |
|   
 | |
|   /**
 | |
|    * Socket timeout in milliseconds (default: 5 minutes / 300000ms)
 | |
|    */
 | |
|   socketTimeout?: number;
 | |
|   
 | |
|   /**
 | |
|    * Initial connection timeout in milliseconds (default: 30 seconds / 30000ms)
 | |
|    */
 | |
|   connectionTimeout?: number;
 | |
|   
 | |
|   /**
 | |
|    * Interval for checking idle sessions in milliseconds (default: 5 seconds / 5000ms)
 | |
|    * For testing, can be set lower (e.g. 1000ms) to detect timeouts more quickly
 | |
|    */
 | |
|   cleanupInterval?: number;
 | |
|   
 | |
|   /**
 | |
|    * Maximum number of recipients allowed per message (default: 100)
 | |
|    */
 | |
|   maxRecipients?: number;
 | |
|   
 | |
|   /**
 | |
|    * Maximum message size in bytes (default: 10MB / 10485760 bytes)
 | |
|    * This is advertised in the EHLO SIZE extension
 | |
|    */
 | |
|   size?: number;
 | |
|   
 | |
|   /**
 | |
|    * Timeout for the DATA command in milliseconds (default: 60000ms / 1 minute)
 | |
|    * This controls how long to wait for the complete email data
 | |
|    */
 | |
|   dataTimeout?: number;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Result of SMTP transaction
 | |
|  */
 | |
| export interface ISmtpTransactionResult {
 | |
|   /**
 | |
|    * Whether the transaction was successful
 | |
|    */
 | |
|   success: boolean;
 | |
|   
 | |
|   /**
 | |
|    * Error message if failed
 | |
|    */
 | |
|   error?: string;
 | |
|   
 | |
|   /**
 | |
|    * Message ID if successful
 | |
|    */
 | |
|   messageId?: string;
 | |
|   
 | |
|   /**
 | |
|    * Resulting email if successful
 | |
|    */
 | |
|   email?: Email;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Interface for SMTP session events
 | |
|  * These events are emitted by the session manager
 | |
|  */
 | |
| export interface ISessionEvents {
 | |
|   created: (session: ISmtpSession, socket: plugins.net.Socket | plugins.tls.TLSSocket) => void;
 | |
|   stateChanged: (session: ISmtpSession, previousState: SmtpState, newState: SmtpState) => void;
 | |
|   timeout: (session: ISmtpSession, socket: plugins.net.Socket | plugins.tls.TLSSocket) => void;
 | |
|   completed: (session: ISmtpSession, socket: plugins.net.Socket | plugins.tls.TLSSocket) => void;
 | |
|   error: (session: ISmtpSession, error: Error) => void;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * SMTP Server interface
 | |
|  */
 | |
| export interface ISmtpServer extends IDestroyable {
 | |
|   /**
 | |
|    * Start the SMTP server
 | |
|    */
 | |
|   listen(): Promise<void>;
 | |
|   
 | |
|   /**
 | |
|    * Stop the SMTP server
 | |
|    */
 | |
|   close(): Promise<void>;
 | |
|   
 | |
|   /**
 | |
|    * Get the session manager
 | |
|    */
 | |
|   getSessionManager(): ISessionManager;
 | |
|   
 | |
|   /**
 | |
|    * Get the connection manager
 | |
|    */
 | |
|   getConnectionManager(): IConnectionManager;
 | |
|   
 | |
|   /**
 | |
|    * Get the command handler
 | |
|    */
 | |
|   getCommandHandler(): ICommandHandler;
 | |
|   
 | |
|   /**
 | |
|    * Get the data handler
 | |
|    */
 | |
|   getDataHandler(): IDataHandler;
 | |
|   
 | |
|   /**
 | |
|    * Get the TLS handler
 | |
|    */
 | |
|   getTlsHandler(): ITlsHandler;
 | |
|   
 | |
|   /**
 | |
|    * Get the security handler
 | |
|    */
 | |
|   getSecurityHandler(): ISecurityHandler;
 | |
|   
 | |
|   /**
 | |
|    * Get the server options
 | |
|    */
 | |
|   getOptions(): ISmtpServerOptions;
 | |
|   
 | |
|   /**
 | |
|    * Get the email server reference
 | |
|    */
 | |
|   getEmailServer(): UnifiedEmailServer;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Configuration for creating SMTP server
 | |
|  */
 | |
| export interface ISmtpServerConfig {
 | |
|   /**
 | |
|    * Email server instance
 | |
|    */
 | |
|   emailServer: UnifiedEmailServer;
 | |
|   
 | |
|   /**
 | |
|    * Server options
 | |
|    */
 | |
|   options: ISmtpServerOptions;
 | |
|   
 | |
|   /**
 | |
|    * Optional custom session manager
 | |
|    */
 | |
|   sessionManager?: ISessionManager;
 | |
|   
 | |
|   /**
 | |
|    * Optional custom connection manager
 | |
|    */
 | |
|   connectionManager?: IConnectionManager;
 | |
|   
 | |
|   /**
 | |
|    * Optional custom command handler
 | |
|    */
 | |
|   commandHandler?: ICommandHandler;
 | |
|   
 | |
|   /**
 | |
|    * Optional custom data handler
 | |
|    */
 | |
|   dataHandler?: IDataHandler;
 | |
|   
 | |
|   /**
 | |
|    * Optional custom TLS handler
 | |
|    */
 | |
|   tlsHandler?: ITlsHandler;
 | |
|   
 | |
|   /**
 | |
|    * Optional custom security handler
 | |
|    */
 | |
|   securityHandler?: ISecurityHandler;
 | |
| } |