This commit is contained in:
2025-05-22 23:02:37 +00:00
parent f065a9c952
commit 50350bd78d
10 changed files with 633 additions and 779 deletions

View File

@ -1,61 +1,61 @@
/**
* SMTP Server Module Interfaces
* This file contains all interfaces for the refactored SMTP server implementation
* SMTP Server Interfaces
* Defines all the interfaces used by the SMTP server implementation
*/
import * as plugins from '../../../plugins.js';
import type { Email } from '../../core/classes.email.js';
import type { UnifiedEmailServer } from '../../routing/classes.unified.email.server.js';
import { SmtpState } from '../interfaces.js';
// Define all needed types/interfaces directly in this file
export { SmtpState };
// Define EmailProcessingMode directly in this file
export type EmailProcessingMode = 'forward' | 'mta' | 'process';
import type { SmtpState, SmtpCommand } from './constants.js';
/**
* Envelope recipient information
* Interface for components that need cleanup
*/
export interface IEnvelopeRecipient {
export interface IDestroyable {
/**
* Email address of the recipient
* Clean up all resources (timers, listeners, etc)
*/
address: string;
/**
* Additional SMTP command arguments
*/
args: Record<string, string>;
destroy(): void | Promise<void>;
}
/**
* SMTP session envelope information
* SMTP authentication credentials
*/
export interface ISmtpAuth {
/**
* Username for authentication
*/
username: string;
/**
* Password for authentication
*/
password: string;
}
/**
* SMTP envelope (sender and recipients)
*/
export interface ISmtpEnvelope {
/**
* Envelope sender (MAIL FROM) information
* Mail from address
*/
mailFrom: {
/**
* Email address of the sender
*/
address: string;
/**
* Additional SMTP command arguments
*/
args: Record<string, string>;
args?: Record<string, string>;
};
/**
* Envelope recipients (RCPT TO) information
* Recipients list
*/
rcptTo: IEnvelopeRecipient[];
rcptTo: Array<{
address: string;
args?: Record<string, string>;
}>;
}
/**
* SMTP Session interface - represents an active SMTP connection
* SMTP session representing a client connection
*/
export interface ISmtpSession {
/**
@ -64,104 +64,264 @@ export interface ISmtpSession {
id: string;
/**
* Current session state in the SMTP conversation
* Current state of the SMTP session
*/
state: SmtpState;
/**
* Hostname provided by the client in EHLO/HELO command
* Client's hostname from EHLO/HELO
*/
clientHostname: string;
clientHostname: string | null;
/**
* MAIL FROM email address (legacy format)
*/
mailFrom: string;
/**
* RCPT TO email addresses (legacy format)
*/
rcptTo: string[];
/**
* Raw email data being received
*/
emailData: string;
/**
* Chunks of email data for more efficient buffer management
*/
emailDataChunks?: string[];
/**
* Total size of email data chunks (tracked incrementally for performance)
*/
emailDataSize?: number;
/**
* Whether the connection is using TLS
*/
useTLS: boolean;
/**
* Whether the connection has ended
*/
connectionEnded: boolean;
/**
* Remote IP address of the client
*/
remoteAddress: string;
/**
* Whether the connection is secure (TLS)
* Whether TLS is active for this session
*/
secure: boolean;
/**
* Whether the client has been authenticated
* Authentication status
*/
authenticated: boolean;
/**
* SMTP envelope information (structured format)
* Authentication username if authenticated
*/
username?: string;
/**
* Transaction envelope
*/
envelope: ISmtpEnvelope;
/**
* Email processing mode to use for this session
* When the session was created
*/
processingMode?: EmailProcessingMode;
createdAt: Date;
/**
* Timestamp of last activity for session timeout tracking
* Last activity timestamp
*/
lastActivity?: number;
lastActivity: Date;
/**
* Timeout ID for DATA command timeout
* Client's IP address
*/
dataTimeoutId?: NodeJS.Timeout;
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;
}
/**
* SMTP authentication data
* Session manager interface
*/
export interface ISmtpAuth {
export interface ISessionManager extends IDestroyable {
/**
* Authentication method used
* Create a new session for a socket
*/
method: 'PLAIN' | 'LOGIN' | 'OAUTH2' | string;
createSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): ISmtpSession;
/**
* Username for authentication
* Get session by socket
*/
username: string;
getSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): ISmtpSession | undefined;
/**
* Password or token for authentication
* Update session state
*/
password: string;
updateSessionState(socket: plugins.net.Socket | plugins.tls.TLSSocket, 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[];
}
/**
* 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;
}
/**
* 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[];
}
/**
* 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>;
}
/**
* 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;
}
/**
* 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>;
}
/**
@ -174,29 +334,19 @@ export interface ISmtpServerOptions {
port: number;
/**
* TLS private key (PEM format)
* Hostname of the server
*/
key: string;
hostname: string;
/**
* TLS certificate (PEM format)
* TLS/SSL private key (PEM format)
*/
cert: string;
key?: string;
/**
* Server hostname for SMTP banner
* TLS/SSL certificate (PEM format)
*/
hostname?: string;
/**
* Host address to bind to (defaults to all interfaces)
*/
host?: string;
/**
* Secure port for dedicated TLS connections
*/
securePort?: number;
cert?: string;
/**
* CA certificates for TLS (PEM format)
@ -300,229 +450,9 @@ export interface ISessionEvents {
}
/**
* Interface for the session manager component
* SMTP Server interface
*/
export interface ISessionManager {
/**
* Creates a new session for a socket connection
*/
createSession(socket: plugins.net.Socket | plugins.tls.TLSSocket, secure: boolean): ISmtpSession;
/**
* Updates the session state
*/
updateSessionState(session: ISmtpSession, newState: SmtpState): void;
/**
* Updates the session's last activity timestamp
*/
updateSessionActivity(session: ISmtpSession): void;
/**
* Removes a session
*/
removeSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
/**
* Gets a session for a socket
*/
getSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): ISmtpSession | undefined;
/**
* Cleans up idle sessions
*/
cleanupIdleSessions(): void;
/**
* Gets the current number of active sessions
*/
getSessionCount(): number;
/**
* Clears all sessions (used when shutting down)
*/
clearAllSessions(): void;
/**
* Register an event listener
*/
on<K extends keyof ISessionEvents>(event: K, listener: ISessionEvents[K]): void;
/**
* Remove an event listener
*/
off<K extends keyof ISessionEvents>(event: K, listener: ISessionEvents[K]): void;
}
/**
* Interface for the connection manager component
*/
export interface IConnectionManager {
/**
* Handle a new connection
*/
handleNewConnection(socket: plugins.net.Socket): void;
/**
* Handle a new secure TLS connection
*/
handleNewSecureConnection(socket: plugins.tls.TLSSocket): void;
/**
* Set up event handlers for a socket
*/
setupSocketEventHandlers(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
/**
* Get the current connection count
*/
getConnectionCount(): number;
/**
* Check if the server has reached the maximum number of connections
*/
hasReachedMaxConnections(): boolean;
/**
* Close all active connections
*/
closeAllConnections(): void;
}
/**
* Interface for the command handler component
*/
export interface ICommandHandler {
/**
* Process a command from the client
*/
processCommand(socket: plugins.net.Socket | plugins.tls.TLSSocket, commandLine: string): void;
/**
* Send a response to the client
*/
sendResponse(socket: plugins.net.Socket | plugins.tls.TLSSocket, response: string): void;
/**
* Handle EHLO command
*/
handleEhlo(socket: plugins.net.Socket | plugins.tls.TLSSocket, clientHostname: string): void;
/**
* Handle MAIL FROM command
*/
handleMailFrom(socket: plugins.net.Socket | plugins.tls.TLSSocket, args: string): void;
/**
* Handle RCPT TO command
*/
handleRcptTo(socket: plugins.net.Socket | plugins.tls.TLSSocket, args: string): void;
/**
* Handle DATA command
*/
handleData(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
/**
* Handle RSET command
*/
handleRset(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
/**
* Handle NOOP command
*/
handleNoop(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
/**
* Handle QUIT command
*/
handleQuit(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
}
/**
* Interface for the data handler component
*/
export interface IDataHandler {
/**
* Process incoming email data (legacy line-based)
*/
processEmailData(socket: plugins.net.Socket | plugins.tls.TLSSocket, data: string): Promise<void>;
/**
* Handle raw data chunks during DATA mode (optimized for large messages)
*/
handleDataReceived(socket: plugins.net.Socket | plugins.tls.TLSSocket, data: string): Promise<void>;
/**
* Process a complete email
*/
processEmail(session: ISmtpSession): Promise<ISmtpTransactionResult>;
/**
* Save an email to disk
*/
saveEmail(session: ISmtpSession): void;
/**
* Parse an email into an Email object
*/
parseEmail(session: ISmtpSession): Promise<Email>;
}
/**
* Interface for the TLS handler component
*/
export interface ITlsHandler {
/**
* Handle STARTTLS command
*/
handleStartTls(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
/**
* Upgrade a connection to TLS
*/
startTLS(socket: plugins.net.Socket): void;
/**
* Create a secure server
*/
createSecureServer(): plugins.tls.Server | undefined;
/**
* Check if TLS is enabled
*/
isTlsEnabled(): boolean;
}
/**
* Interface for the security handler component
*/
export interface ISecurityHandler {
/**
* Check IP reputation for a connection
*/
checkIpReputation(socket: plugins.net.Socket | plugins.tls.TLSSocket): Promise<boolean>;
/**
* Validate an email address
*/
isValidEmail(email: string): boolean;
/**
* Validate authentication credentials
*/
authenticate(session: ISmtpSession, username: string, password: string, method: string): Promise<boolean>;
/**
* Log a security event
*/
logSecurityEvent(event: string, level: string, message: string, details: Record<string, any>): void;
}
/**
* Interface for the SMTP server component
*/
export interface ISmtpServer {
export interface ISmtpServer extends IDestroyable {
/**
* Start the SMTP server
*/
@ -575,46 +505,46 @@ export interface ISmtpServer {
}
/**
* Configuration for creating an SMTP server
* Configuration for creating SMTP server
*/
export interface ISmtpServerConfig {
/**
* Email server reference
* Email server instance
*/
emailServer: UnifiedEmailServer;
/**
* SMTP server options
* Server options
*/
options: ISmtpServerOptions;
/**
* Optional session manager
* Optional custom session manager
*/
sessionManager?: ISessionManager;
/**
* Optional connection manager
* Optional custom connection manager
*/
connectionManager?: IConnectionManager;
/**
* Optional command handler
* Optional custom command handler
*/
commandHandler?: ICommandHandler;
/**
* Optional data handler
* Optional custom data handler
*/
dataHandler?: IDataHandler;
/**
* Optional TLS handler
* Optional custom TLS handler
*/
tlsHandler?: ITlsHandler;
/**
* Optional security handler
* Optional custom security handler
*/
securityHandler?: ISecurityHandler;
}