feat(mailer-smtp): implement in-process SMTP server and management IPC integration
This commit is contained in:
@@ -73,6 +73,60 @@ interface IVersionInfo {
|
||||
smtp: string;
|
||||
}
|
||||
|
||||
// --- SMTP Server types ---
|
||||
|
||||
interface ISmtpServerConfig {
|
||||
hostname: string;
|
||||
ports: number[];
|
||||
securePort?: number;
|
||||
tlsCertPem?: string;
|
||||
tlsKeyPem?: string;
|
||||
maxMessageSize?: number;
|
||||
maxConnections?: number;
|
||||
maxRecipients?: number;
|
||||
connectionTimeoutSecs?: number;
|
||||
dataTimeoutSecs?: number;
|
||||
authEnabled?: boolean;
|
||||
maxAuthFailures?: number;
|
||||
socketTimeoutSecs?: number;
|
||||
processingTimeoutSecs?: number;
|
||||
rateLimits?: IRateLimitConfig;
|
||||
}
|
||||
|
||||
interface IRateLimitConfig {
|
||||
maxConnectionsPerIp?: number;
|
||||
maxMessagesPerSender?: number;
|
||||
maxAuthFailuresPerIp?: number;
|
||||
windowSecs?: number;
|
||||
}
|
||||
|
||||
interface IEmailData {
|
||||
type: 'inline' | 'file';
|
||||
base64?: string;
|
||||
path?: string;
|
||||
}
|
||||
|
||||
interface IEmailReceivedEvent {
|
||||
correlationId: string;
|
||||
sessionId: string;
|
||||
mailFrom: string;
|
||||
rcptTo: string[];
|
||||
data: IEmailData;
|
||||
remoteAddr: string;
|
||||
clientHostname: string | null;
|
||||
secure: boolean;
|
||||
authenticatedUser: string | null;
|
||||
securityResults: any | null;
|
||||
}
|
||||
|
||||
interface IAuthRequestEvent {
|
||||
correlationId: string;
|
||||
sessionId: string;
|
||||
username: string;
|
||||
password: string;
|
||||
remoteAddr: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-safe command map for the mailer-bin IPC bridge.
|
||||
*/
|
||||
@@ -128,6 +182,35 @@ type TMailerCommands = {
|
||||
};
|
||||
result: IEmailSecurityResult;
|
||||
};
|
||||
startSmtpServer: {
|
||||
params: ISmtpServerConfig;
|
||||
result: { started: boolean };
|
||||
};
|
||||
stopSmtpServer: {
|
||||
params: Record<string, never>;
|
||||
result: { stopped: boolean; wasRunning?: boolean };
|
||||
};
|
||||
emailProcessingResult: {
|
||||
params: {
|
||||
correlationId: string;
|
||||
accepted: boolean;
|
||||
smtpCode?: number;
|
||||
smtpMessage?: string;
|
||||
};
|
||||
result: { resolved: boolean };
|
||||
};
|
||||
authResult: {
|
||||
params: {
|
||||
correlationId: string;
|
||||
success: boolean;
|
||||
message?: string;
|
||||
};
|
||||
result: { resolved: boolean };
|
||||
};
|
||||
configureRateLimits: {
|
||||
params: IRateLimitConfig;
|
||||
result: { configured: boolean };
|
||||
};
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -314,6 +397,85 @@ export class RustSecurityBridge {
|
||||
}): Promise<IEmailSecurityResult> {
|
||||
return this.bridge.sendCommand('verifyEmail', opts);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// SMTP Server lifecycle
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Start the Rust SMTP server.
|
||||
* The server will listen on the configured ports and emit events for
|
||||
* emailReceived and authRequest that must be handled by the caller.
|
||||
*/
|
||||
public async startSmtpServer(config: ISmtpServerConfig): Promise<boolean> {
|
||||
const result = await this.bridge.sendCommand('startSmtpServer', config);
|
||||
return result?.started === true;
|
||||
}
|
||||
|
||||
/** Stop the Rust SMTP server. */
|
||||
public async stopSmtpServer(): Promise<void> {
|
||||
await this.bridge.sendCommand('stopSmtpServer', {} as any);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the result of email processing back to the Rust SMTP server.
|
||||
* This resolves a pending correlation-ID callback, allowing the Rust
|
||||
* server to send the SMTP response to the client.
|
||||
*/
|
||||
public async sendEmailProcessingResult(opts: {
|
||||
correlationId: string;
|
||||
accepted: boolean;
|
||||
smtpCode?: number;
|
||||
smtpMessage?: string;
|
||||
}): Promise<void> {
|
||||
await this.bridge.sendCommand('emailProcessingResult', opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the result of authentication validation back to the Rust SMTP server.
|
||||
*/
|
||||
public async sendAuthResult(opts: {
|
||||
correlationId: string;
|
||||
success: boolean;
|
||||
message?: string;
|
||||
}): Promise<void> {
|
||||
await this.bridge.sendCommand('authResult', opts);
|
||||
}
|
||||
|
||||
/** Update rate limit configuration at runtime. */
|
||||
public async configureRateLimits(config: IRateLimitConfig): Promise<void> {
|
||||
await this.bridge.sendCommand('configureRateLimits', config);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Event registration — delegates to the underlying bridge EventEmitter
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Register a handler for emailReceived events from the Rust SMTP server.
|
||||
* These events fire when a complete email has been received and needs processing.
|
||||
*/
|
||||
public onEmailReceived(handler: (data: IEmailReceivedEvent) => void): void {
|
||||
this.bridge.on('management:emailReceived', handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a handler for authRequest events from the Rust SMTP server.
|
||||
* The handler must call sendAuthResult() with the correlationId.
|
||||
*/
|
||||
public onAuthRequest(handler: (data: IAuthRequestEvent) => void): void {
|
||||
this.bridge.on('management:authRequest', handler);
|
||||
}
|
||||
|
||||
/** Remove an emailReceived event handler. */
|
||||
public offEmailReceived(handler: (data: IEmailReceivedEvent) => void): void {
|
||||
this.bridge.off('management:emailReceived', handler);
|
||||
}
|
||||
|
||||
/** Remove an authRequest event handler. */
|
||||
public offAuthRequest(handler: (data: IAuthRequestEvent) => void): void {
|
||||
this.bridge.off('management:authRequest', handler);
|
||||
}
|
||||
}
|
||||
|
||||
// Re-export interfaces for consumers
|
||||
@@ -327,4 +489,9 @@ export type {
|
||||
IContentScanResult,
|
||||
IReputationResult as IRustReputationResult,
|
||||
IVersionInfo,
|
||||
ISmtpServerConfig,
|
||||
IRateLimitConfig,
|
||||
IEmailData,
|
||||
IEmailReceivedEvent,
|
||||
IAuthRequestEvent,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user