BREAKING CHANGE(smtp-client): Replace the legacy TypeScript SMTP client with a new Rust-based SMTP client and IPC bridge for outbound delivery

This commit is contained in:
2026-02-11 07:17:05 +00:00
parent fc4877e06b
commit 27bab5f345
50 changed files with 2268 additions and 6737 deletions

View File

@@ -67,6 +67,71 @@ interface IContentScanResult {
scannedElements: string[];
}
// --- SMTP Client types ---
interface IOutboundEmail {
from: string;
to: string[];
cc?: string[];
bcc?: string[];
subject?: string;
text?: string;
html?: string;
headers?: Record<string, string>;
}
interface ISmtpSendResult {
accepted: string[];
rejected: string[];
messageId?: string;
response: string;
envelope: { from: string; to: string[] };
}
interface ISmtpSendOptions {
host: string;
port: number;
secure?: boolean;
domain?: string;
auth?: { user: string; pass: string; method?: string };
email: IOutboundEmail;
dkim?: { domain: string; selector: string; privateKey: string };
connectionTimeoutSecs?: number;
socketTimeoutSecs?: number;
poolKey?: string;
maxPoolConnections?: number;
}
interface ISmtpSendRawOptions {
host: string;
port: number;
secure?: boolean;
domain?: string;
auth?: { user: string; pass: string; method?: string };
envelopeFrom: string;
envelopeTo: string[];
rawMessageBase64: string;
poolKey?: string;
}
interface ISmtpVerifyOptions {
host: string;
port: number;
secure?: boolean;
domain?: string;
auth?: { user: string; pass: string; method?: string };
}
interface ISmtpVerifyResult {
reachable: boolean;
greeting?: string;
capabilities?: string[];
}
interface ISmtpPoolStatus {
pools: Record<string, { total: number; active: number; idle: number }>;
}
interface IVersionInfo {
bin: string;
core: string;
@@ -212,6 +277,26 @@ type TMailerCommands = {
params: IRateLimitConfig;
result: { configured: boolean };
};
sendEmail: {
params: ISmtpSendOptions;
result: ISmtpSendResult;
};
sendRawEmail: {
params: ISmtpSendRawOptions;
result: ISmtpSendResult;
};
verifySmtpConnection: {
params: ISmtpVerifyOptions;
result: ISmtpVerifyResult;
};
closeSmtpPool: {
params: { poolKey?: string };
result: { closed: boolean };
};
getSmtpPoolStatus: {
params: Record<string, never>;
result: ISmtpPoolStatus;
};
};
// ---------------------------------------------------------------------------
@@ -660,6 +745,40 @@ export class RustSecurityBridge extends EventEmitter {
return this.bridge.sendCommand('verifyEmail', opts);
}
// -----------------------------------------------------------------------
// SMTP Client — outbound email delivery via Rust
// -----------------------------------------------------------------------
/** Send a structured email via the Rust SMTP client. */
public async sendOutboundEmail(opts: ISmtpSendOptions): Promise<ISmtpSendResult> {
this.ensureRunning();
return this.bridge.sendCommand('sendEmail', opts);
}
/** Send a pre-formatted raw email via the Rust SMTP client. */
public async sendRawEmail(opts: ISmtpSendRawOptions): Promise<ISmtpSendResult> {
this.ensureRunning();
return this.bridge.sendCommand('sendRawEmail', opts);
}
/** Verify connectivity to an SMTP server. */
public async verifySmtpConnection(opts: ISmtpVerifyOptions): Promise<ISmtpVerifyResult> {
this.ensureRunning();
return this.bridge.sendCommand('verifySmtpConnection', opts);
}
/** Close a specific connection pool (or all pools if no key is given). */
public async closeSmtpPool(poolKey?: string): Promise<void> {
this.ensureRunning();
await this.bridge.sendCommand('closeSmtpPool', poolKey ? { poolKey } : ({} as any));
}
/** Get status of all SMTP client connection pools. */
public async getSmtpPoolStatus(): Promise<ISmtpPoolStatus> {
this.ensureRunning();
return this.bridge.sendCommand('getSmtpPoolStatus', {} as any);
}
// -----------------------------------------------------------------------
// SMTP Server lifecycle
// -----------------------------------------------------------------------
@@ -763,4 +882,11 @@ export type {
IEmailData,
IEmailReceivedEvent,
IAuthRequestEvent,
IOutboundEmail,
ISmtpSendResult,
ISmtpSendOptions,
ISmtpSendRawOptions,
ISmtpVerifyOptions,
ISmtpVerifyResult,
ISmtpPoolStatus,
};