Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d43fc15d8e | |||
| 248bfcfe78 | |||
| 1e7c9f6822 | |||
| f3a74a7660 | |||
| 399f5fa418 | |||
| cd4584ec26 | |||
| f601859f8b | |||
| eb2643de93 | |||
| 595634fb0f | |||
| cee8a51081 |
29
.gitignore
vendored
29
.gitignore
vendored
@@ -1,9 +1,24 @@
|
||||
node_modules/
|
||||
.nogit/
|
||||
|
||||
# artifacts
|
||||
coverage/
|
||||
public/
|
||||
|
||||
# installs
|
||||
node_modules/
|
||||
|
||||
# caches
|
||||
.yarn/
|
||||
.cache/
|
||||
.rpt2_cache
|
||||
|
||||
# builds
|
||||
dist/
|
||||
dist_rust/
|
||||
rust/target/
|
||||
deno.lock
|
||||
*.log
|
||||
.env
|
||||
.DS_Store
|
||||
dist_*/
|
||||
|
||||
# AI
|
||||
.claude/
|
||||
.serena/
|
||||
|
||||
#------# custom
|
||||
rust/target
|
||||
41
changelog.md
41
changelog.md
@@ -1,5 +1,46 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-02-10 - 2.4.0 - feat(docs)
|
||||
document Rust-side in-process security pipeline and update README to reflect SMTP server behavior and crate/test counts
|
||||
|
||||
- Clarifies that the Rust SMTP server accepts the full SMTP protocol and runs the security pipeline in-process (DKIM/SPF/DMARC verification, content scanning, IP reputation/DNSBL) to avoid IPC round-trips
|
||||
- Notes that Rust now emits an emailReceived IPC event with pre-computed security results attached for TypeScript to use in routing/delivery decisions
|
||||
- Updates mailer-smtp crate description to include the in-process security pipeline and increments its test count from 72 to 77
|
||||
- Adjusts TypeScript directory comments to reflect removal/relocation of the legacy TS SMTP server and the smtpclient path
|
||||
|
||||
## 2026-02-10 - 2.3.2 - fix(tests)
|
||||
remove large SMTP client test suites and update SmartFile API usage
|
||||
|
||||
- Deleted ~80 test files under test/suite/ (multiple smtpclient command, connection, edge-cases, email-composition, error-handling and performance test suites)
|
||||
- Updated SmartFile usage in test/test.smartmail.ts: replaced plugins.smartfile.SmartFile.fromString(...) with plugins.smartfile.SmartFileFactory.nodeFs().fromString(...)
|
||||
- Removes a large set of tests to reduce test surface / simplify test runtime
|
||||
|
||||
## 2026-02-10 - 2.3.1 - fix(npmextra)
|
||||
update .gitignore and npmextra.json to add ignore patterns, registries, and module metadata
|
||||
|
||||
- .gitignore: expanded ignore list for artifacts, installs, caches, builds, AI dirs, and rust target path
|
||||
- npmextra.json: added npmjs registry alongside internal Verdaccio registry for @git.zone/cli release settings
|
||||
- npmextra.json: added projectType and module metadata (githost, gitscope, gitrepo, description, npmPackagename, license) for @git.zone/cli and added empty @ship.zone/szci entry
|
||||
|
||||
## 2026-02-10 - 2.3.0 - feat(mailer-smtp)
|
||||
add in-process security pipeline for SMTP delivery (DKIM/SPF/DMARC, content scanning, IP reputation)
|
||||
|
||||
- Integrate mailer_security verification (DKIM/SPF/DMARC) and IP reputation checks into the Rust SMTP server; run concurrently and wrapped with a 30s timeout.
|
||||
- Add MIME parsing using mailparse and an extract_mime_parts helper to extract subject, text/html bodies and attachment filenames for content scanning.
|
||||
- Wire MessageAuthenticator and TokioResolver into server and connection startup; pass them into the delivery pipeline and connection handlers.
|
||||
- Run content scanning (mailer_security::content_scanner), combine results (dkim/spf/dmarc, contentScan, ipReputation) into a JSON object and attach as security_results on EmailReceived events.
|
||||
- Update Rust crates (Cargo.toml/Cargo.lock) to include mailparse and resolver usage and add serde::Deserialize where required; add unit tests for MIME extraction.
|
||||
- Remove the TypeScript SMTP server implementation and many TS tests; replace test helper (server.loader.ts) with a stub that points tests to use the Rust SMTP server and provide small utilities (getAvailablePort/isPortFree).
|
||||
|
||||
## 2026-02-10 - 2.2.1 - fix(readme)
|
||||
Clarify Rust-powered architecture and mandatory Rust bridge; expand README with Rust workspace details and project structure updates
|
||||
|
||||
- Emphasizes that the SMTP server is Rust-powered (high-performance) and not a nodemailer-based TS server.
|
||||
- Documents that the Rust binary (mailer-bin) is required — if unavailable UnifiedEmailServer.start() will throw an error.
|
||||
- Adds installation/build note: run `pnpm build` to compile the Rust binary.
|
||||
- Adds a new Rust Acceleration Layer section listing workspace crates and responsibilities (mailer-core, mailer-security, mailer-smtp, mailer-bin, mailer-napi).
|
||||
- Updates project structure: marks legacy TS SMTP server as fallback/legacy, adds dist_rust output, and clarifies which operations run in Rust vs TypeScript.
|
||||
|
||||
## 2026-02-10 - 2.2.0 - feat(mailer-smtp)
|
||||
implement in-process SMTP server and management IPC integration
|
||||
|
||||
|
||||
8
dist_ts/00_commitinfo_data.d.ts
vendored
8
dist_ts/00_commitinfo_data.d.ts
vendored
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* autocreated commitinfo by @push.rocks/commitinfo
|
||||
*/
|
||||
export declare const commitinfo: {
|
||||
name: string;
|
||||
version: string;
|
||||
description: string;
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
/**
|
||||
* autocreated commitinfo by @push.rocks/commitinfo
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartmta',
|
||||
version: '2.1.0',
|
||||
description: 'A high-performance, enterprise-grade Mail Transfer Agent (MTA) built from scratch in TypeScript with Rust acceleration.'
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHlIQUF5SDtDQUN2SSxDQUFBIn0=
|
||||
41
dist_ts/errors/index.d.ts
vendored
41
dist_ts/errors/index.d.ts
vendored
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* MTA error classes for SMTP client operations
|
||||
*/
|
||||
export declare class MtaConnectionError extends Error {
|
||||
code: string;
|
||||
details?: any;
|
||||
constructor(message: string, detailsOrCode?: any);
|
||||
static timeout(host: string, port: number, timeoutMs?: number): MtaConnectionError;
|
||||
static refused(host: string, port: number): MtaConnectionError;
|
||||
static dnsError(host: string, err?: any): MtaConnectionError;
|
||||
}
|
||||
export declare class MtaAuthenticationError extends Error {
|
||||
code: string;
|
||||
details?: any;
|
||||
constructor(message: string, detailsOrCode?: any);
|
||||
static invalidCredentials(host?: string, user?: string): MtaAuthenticationError;
|
||||
}
|
||||
export declare class MtaDeliveryError extends Error {
|
||||
code: string;
|
||||
responseCode?: number;
|
||||
details?: any;
|
||||
constructor(message: string, detailsOrCode?: any, responseCode?: number);
|
||||
static temporary(message: string, ...args: any[]): MtaDeliveryError;
|
||||
static permanent(message: string, ...args: any[]): MtaDeliveryError;
|
||||
}
|
||||
export declare class MtaConfigurationError extends Error {
|
||||
code: string;
|
||||
details?: any;
|
||||
constructor(message: string, detailsOrCode?: any);
|
||||
}
|
||||
export declare class MtaTimeoutError extends Error {
|
||||
code: string;
|
||||
details?: any;
|
||||
constructor(message: string, detailsOrCode?: any);
|
||||
static commandTimeout(command: string, hostOrTimeout?: any, timeoutMs?: number): MtaTimeoutError;
|
||||
}
|
||||
export declare class MtaProtocolError extends Error {
|
||||
code: string;
|
||||
details?: any;
|
||||
constructor(message: string, detailsOrCode?: any);
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/**
|
||||
* MTA error classes for SMTP client operations
|
||||
*/
|
||||
export class MtaConnectionError extends Error {
|
||||
code;
|
||||
details;
|
||||
constructor(message, detailsOrCode) {
|
||||
super(message);
|
||||
this.name = 'MtaConnectionError';
|
||||
if (typeof detailsOrCode === 'string') {
|
||||
this.code = detailsOrCode;
|
||||
}
|
||||
else {
|
||||
this.code = 'CONNECTION_ERROR';
|
||||
this.details = detailsOrCode;
|
||||
}
|
||||
}
|
||||
static timeout(host, port, timeoutMs) {
|
||||
return new MtaConnectionError(`Connection to ${host}:${port} timed out${timeoutMs ? ` after ${timeoutMs}ms` : ''}`, 'TIMEOUT');
|
||||
}
|
||||
static refused(host, port) {
|
||||
return new MtaConnectionError(`Connection to ${host}:${port} refused`, 'REFUSED');
|
||||
}
|
||||
static dnsError(host, err) {
|
||||
const errMsg = typeof err === 'string' ? err : err?.message || '';
|
||||
return new MtaConnectionError(`DNS resolution failed for ${host}${errMsg ? `: ${errMsg}` : ''}`, 'DNS_ERROR');
|
||||
}
|
||||
}
|
||||
export class MtaAuthenticationError extends Error {
|
||||
code;
|
||||
details;
|
||||
constructor(message, detailsOrCode) {
|
||||
super(message);
|
||||
this.name = 'MtaAuthenticationError';
|
||||
if (typeof detailsOrCode === 'string') {
|
||||
this.code = detailsOrCode;
|
||||
}
|
||||
else {
|
||||
this.code = 'AUTH_ERROR';
|
||||
this.details = detailsOrCode;
|
||||
}
|
||||
}
|
||||
static invalidCredentials(host, user) {
|
||||
const detail = host && user ? `${user}@${host}` : host || user || '';
|
||||
return new MtaAuthenticationError(`Authentication failed${detail ? `: ${detail}` : ''}`, 'INVALID_CREDENTIALS');
|
||||
}
|
||||
}
|
||||
export class MtaDeliveryError extends Error {
|
||||
code;
|
||||
responseCode;
|
||||
details;
|
||||
constructor(message, detailsOrCode, responseCode) {
|
||||
super(message);
|
||||
this.name = 'MtaDeliveryError';
|
||||
if (typeof detailsOrCode === 'string') {
|
||||
this.code = detailsOrCode;
|
||||
this.responseCode = responseCode;
|
||||
}
|
||||
else {
|
||||
this.code = 'DELIVERY_ERROR';
|
||||
this.details = detailsOrCode;
|
||||
}
|
||||
}
|
||||
static temporary(message, ...args) {
|
||||
return new MtaDeliveryError(message, 'TEMPORARY');
|
||||
}
|
||||
static permanent(message, ...args) {
|
||||
return new MtaDeliveryError(message, 'PERMANENT');
|
||||
}
|
||||
}
|
||||
export class MtaConfigurationError extends Error {
|
||||
code;
|
||||
details;
|
||||
constructor(message, detailsOrCode) {
|
||||
super(message);
|
||||
this.name = 'MtaConfigurationError';
|
||||
if (typeof detailsOrCode === 'string') {
|
||||
this.code = detailsOrCode;
|
||||
}
|
||||
else {
|
||||
this.code = 'CONFIG_ERROR';
|
||||
this.details = detailsOrCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
export class MtaTimeoutError extends Error {
|
||||
code;
|
||||
details;
|
||||
constructor(message, detailsOrCode) {
|
||||
super(message);
|
||||
this.name = 'MtaTimeoutError';
|
||||
if (typeof detailsOrCode === 'string') {
|
||||
this.code = detailsOrCode;
|
||||
}
|
||||
else {
|
||||
this.code = 'TIMEOUT';
|
||||
this.details = detailsOrCode;
|
||||
}
|
||||
}
|
||||
static commandTimeout(command, hostOrTimeout, timeoutMs) {
|
||||
const timeout = typeof hostOrTimeout === 'number' ? hostOrTimeout : timeoutMs;
|
||||
return new MtaTimeoutError(`Command '${command}' timed out${timeout ? ` after ${timeout}ms` : ''}`, 'COMMAND_TIMEOUT');
|
||||
}
|
||||
}
|
||||
export class MtaProtocolError extends Error {
|
||||
code;
|
||||
details;
|
||||
constructor(message, detailsOrCode) {
|
||||
super(message);
|
||||
this.name = 'MtaProtocolError';
|
||||
if (typeof detailsOrCode === 'string') {
|
||||
this.code = detailsOrCode;
|
||||
}
|
||||
else {
|
||||
this.code = 'PROTOCOL_ERROR';
|
||||
this.details = detailsOrCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9lcnJvcnMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxNQUFNLE9BQU8sa0JBQW1CLFNBQVEsS0FBSztJQUNwQyxJQUFJLENBQVM7SUFDYixPQUFPLENBQU87SUFDckIsWUFBWSxPQUFlLEVBQUUsYUFBbUI7UUFDOUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxvQkFBb0IsQ0FBQztRQUNqQyxJQUFJLE9BQU8sYUFBYSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxJQUFJLEdBQUcsYUFBYSxDQUFDO1FBQzVCLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLElBQUksR0FBRyxrQkFBa0IsQ0FBQztZQUMvQixJQUFJLENBQUMsT0FBTyxHQUFHLGFBQWEsQ0FBQztRQUMvQixDQUFDO0lBQ0gsQ0FBQztJQUNELE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBWSxFQUFFLElBQVksRUFBRSxTQUFrQjtRQUMzRCxPQUFPLElBQUksa0JBQWtCLENBQUMsaUJBQWlCLElBQUksSUFBSSxJQUFJLGFBQWEsU0FBUyxDQUFDLENBQUMsQ0FBQyxVQUFVLFNBQVMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUNqSSxDQUFDO0lBQ0QsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFZLEVBQUUsSUFBWTtRQUN2QyxPQUFPLElBQUksa0JBQWtCLENBQUMsaUJBQWlCLElBQUksSUFBSSxJQUFJLFVBQVUsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUNwRixDQUFDO0lBQ0QsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFZLEVBQUUsR0FBUztRQUNyQyxNQUFNLE1BQU0sR0FBRyxPQUFPLEdBQUcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxD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
|
||||
17
dist_ts/logger.d.ts
vendored
17
dist_ts/logger.d.ts
vendored
@@ -1,17 +0,0 @@
|
||||
declare class StandardLogger {
|
||||
private defaultContext;
|
||||
private correlationId;
|
||||
constructor();
|
||||
log(level: 'error' | 'warn' | 'info' | 'success' | 'debug', message: string, context?: Record<string, any>): void;
|
||||
error(message: string, context?: Record<string, any>): void;
|
||||
warn(message: string, context?: Record<string, any>): void;
|
||||
info(message: string, context?: Record<string, any>): void;
|
||||
success(message: string, context?: Record<string, any>): void;
|
||||
debug(message: string, context?: Record<string, any>): void;
|
||||
setContext(context: Record<string, any>, overwrite?: boolean): void;
|
||||
setCorrelationId(id?: string | null): string;
|
||||
getCorrelationId(): string | null;
|
||||
clearCorrelationId(): void;
|
||||
}
|
||||
export declare const logger: StandardLogger;
|
||||
export {};
|
||||
@@ -1,76 +0,0 @@
|
||||
import * as plugins from './plugins.js';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
// Map NODE_ENV to valid TEnvironment
|
||||
const nodeEnv = process.env.NODE_ENV || 'production';
|
||||
const envMap = {
|
||||
'development': 'local',
|
||||
'test': 'test',
|
||||
'staging': 'staging',
|
||||
'production': 'production'
|
||||
};
|
||||
// Default Smartlog instance
|
||||
const baseLogger = new plugins.smartlog.Smartlog({
|
||||
logContext: {
|
||||
environment: envMap[nodeEnv] || 'production',
|
||||
runtime: 'node',
|
||||
zone: 'serve.zone',
|
||||
}
|
||||
});
|
||||
// Extended logger compatible with the original enhanced logger API
|
||||
class StandardLogger {
|
||||
defaultContext = {};
|
||||
correlationId = null;
|
||||
constructor() { }
|
||||
// Log methods
|
||||
log(level, message, context = {}) {
|
||||
const combinedContext = {
|
||||
...this.defaultContext,
|
||||
...context
|
||||
};
|
||||
if (this.correlationId) {
|
||||
combinedContext.correlation_id = this.correlationId;
|
||||
}
|
||||
baseLogger.log(level, message, combinedContext);
|
||||
}
|
||||
error(message, context = {}) {
|
||||
this.log('error', message, context);
|
||||
}
|
||||
warn(message, context = {}) {
|
||||
this.log('warn', message, context);
|
||||
}
|
||||
info(message, context = {}) {
|
||||
this.log('info', message, context);
|
||||
}
|
||||
success(message, context = {}) {
|
||||
this.log('success', message, context);
|
||||
}
|
||||
debug(message, context = {}) {
|
||||
this.log('debug', message, context);
|
||||
}
|
||||
// Context management
|
||||
setContext(context, overwrite = false) {
|
||||
if (overwrite) {
|
||||
this.defaultContext = context;
|
||||
}
|
||||
else {
|
||||
this.defaultContext = {
|
||||
...this.defaultContext,
|
||||
...context
|
||||
};
|
||||
}
|
||||
}
|
||||
// Correlation ID management
|
||||
setCorrelationId(id = null) {
|
||||
this.correlationId = id || randomUUID();
|
||||
return this.correlationId;
|
||||
}
|
||||
getCorrelationId() {
|
||||
return this.correlationId;
|
||||
}
|
||||
clearCorrelationId() {
|
||||
this.correlationId = null;
|
||||
}
|
||||
}
|
||||
// Export a singleton instance
|
||||
export const logger = new StandardLogger();
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvbG9nZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFekMscUNBQXFDO0FBQ3JDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxJQUFJLFlBQVksQ0FBQztBQUNyRCxNQUFNLE1BQU0sR0FBZ0U7SUFDMUUsYUFBYSxFQUFFLE9BQU87SUFDdEIsTUFBTSxFQUFFLE1BQU07SUFDZCxTQUFTLEVBQUUsU0FBUztJQUNwQixZQUFZLEVBQUUsWUFBWTtDQUMzQixDQUFDO0FBRUYsNEJBQTRCO0FBQzVCLE1BQU0sVUFBVSxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7SUFDL0MsVUFBVSxFQUFFO1FBQ1YsV0FBVyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxZQUFZO1FBQzVDLE9BQU8sRUFBRSxNQUFNO1FBQ2YsSUFBSSxFQUFFLFlBQVk7S0FDbkI7Q0FDRixDQUFDLENBQUM7QUFFSCxtRUFBbUU7QUFDbkUsTUFBTSxjQUFjO0lBQ1YsY0FBYyxHQUF3QixFQUFFLENBQUM7SUFDekMsYUFBYSxHQUFrQixJQUFJLENBQUM7SUFFNUMsZ0JBQWUsQ0FBQztJQUVoQixjQUFjO0lBQ1AsR0FBRyxDQUFDLEtBQXNELEVBQUUsT0FBZSxFQUFFLFVBQStCLEVBQUU7UUFDbkgsTUFBTSxlQUFlLEdBQUc7WUFDdEIsR0FBRyxJQUFJLENBQUMsY0FBYztZQUN0QixHQUFHLE9BQU87U0FDWCxDQUFDO1FBRUYsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkIsZUFBZSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1FBQ3RELENBQUM7UUFFRCxVQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVNLEtBQUssQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUM3RCxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVNLElBQUksQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUM1RCxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVNLElBQUksQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUM1RCxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVNLE9BQU8sQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUMvRCxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVNLEtBQUssQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUM3RCxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELHFCQUFxQjtJQUNkLFVBQVUsQ0FBQyxPQUE0QixFQUFFLFlBQXFCLEtBQUs7UUFDeEUsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNkLElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDO1FBQ2hDLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLGNBQWMsR0FBRztnQkFDcEIsR0FBRyxJQUFJLENBQUMsY0FBYztnQkFDdEIsR0FBRyxPQUFPO2FBQ1gsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsNEJBQTRCO0lBQ3JCLGdCQUFnQixDQUFDLEtBQW9CLElBQUk7UUFDOUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxFQUFFLElBQUksVUFBVSxFQUFFLENBQUM7UUFDeEMsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFFTSxnQkFBZ0I7UUFDckIsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFFTSxrQkFBa0I7UUFDdkIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBRUQsOEJBQThCO0FBQzlCLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDIn0=
|
||||
185
dist_ts/mail/core/classes.bouncemanager.d.ts
vendored
185
dist_ts/mail/core/classes.bouncemanager.d.ts
vendored
@@ -1,185 +0,0 @@
|
||||
import type { Email } from './classes.email.js';
|
||||
/**
|
||||
* Bounce types for categorizing the reasons for bounces
|
||||
*/
|
||||
export declare enum BounceType {
|
||||
INVALID_RECIPIENT = "invalid_recipient",
|
||||
DOMAIN_NOT_FOUND = "domain_not_found",
|
||||
MAILBOX_FULL = "mailbox_full",
|
||||
MAILBOX_INACTIVE = "mailbox_inactive",
|
||||
BLOCKED = "blocked",
|
||||
SPAM_RELATED = "spam_related",
|
||||
POLICY_RELATED = "policy_related",
|
||||
SERVER_UNAVAILABLE = "server_unavailable",
|
||||
TEMPORARY_FAILURE = "temporary_failure",
|
||||
QUOTA_EXCEEDED = "quota_exceeded",
|
||||
NETWORK_ERROR = "network_error",
|
||||
TIMEOUT = "timeout",
|
||||
AUTO_RESPONSE = "auto_response",
|
||||
CHALLENGE_RESPONSE = "challenge_response",
|
||||
UNKNOWN = "unknown"
|
||||
}
|
||||
/**
|
||||
* Hard vs soft bounce classification
|
||||
*/
|
||||
export declare enum BounceCategory {
|
||||
HARD = "hard",
|
||||
SOFT = "soft",
|
||||
AUTO_RESPONSE = "auto_response",
|
||||
UNKNOWN = "unknown"
|
||||
}
|
||||
/**
|
||||
* Bounce data structure
|
||||
*/
|
||||
export interface BounceRecord {
|
||||
id: string;
|
||||
originalEmailId?: string;
|
||||
recipient: string;
|
||||
sender: string;
|
||||
domain: string;
|
||||
subject?: string;
|
||||
bounceType: BounceType;
|
||||
bounceCategory: BounceCategory;
|
||||
timestamp: number;
|
||||
smtpResponse?: string;
|
||||
diagnosticCode?: string;
|
||||
statusCode?: string;
|
||||
headers?: Record<string, string>;
|
||||
processed: boolean;
|
||||
retryCount?: number;
|
||||
nextRetryTime?: number;
|
||||
}
|
||||
/**
|
||||
* Retry strategy configuration for soft bounces
|
||||
*/
|
||||
interface RetryStrategy {
|
||||
maxRetries: number;
|
||||
initialDelay: number;
|
||||
maxDelay: number;
|
||||
backoffFactor: number;
|
||||
}
|
||||
/**
|
||||
* Manager for handling email bounces
|
||||
*/
|
||||
export declare class BounceManager {
|
||||
private retryStrategy;
|
||||
private bounceStore;
|
||||
private bounceCache;
|
||||
private suppressionList;
|
||||
private storageManager?;
|
||||
constructor(options?: {
|
||||
retryStrategy?: Partial<RetryStrategy>;
|
||||
maxCacheSize?: number;
|
||||
cacheTTL?: number;
|
||||
storageManager?: any;
|
||||
});
|
||||
/**
|
||||
* Process a bounce notification
|
||||
* @param bounceData Bounce data to process
|
||||
* @returns Processed bounce record
|
||||
*/
|
||||
processBounce(bounceData: Partial<BounceRecord>): Promise<BounceRecord>;
|
||||
/**
|
||||
* Process an SMTP failure as a bounce
|
||||
* @param recipient Recipient email
|
||||
* @param smtpResponse SMTP error response
|
||||
* @param options Additional options
|
||||
* @returns Processed bounce record
|
||||
*/
|
||||
processSmtpFailure(recipient: string, smtpResponse: string, options?: {
|
||||
sender?: string;
|
||||
originalEmailId?: string;
|
||||
statusCode?: string;
|
||||
headers?: Record<string, string>;
|
||||
}): Promise<BounceRecord>;
|
||||
/**
|
||||
* Process a bounce notification email
|
||||
* @param bounceEmail The email containing bounce information
|
||||
* @returns Processed bounce record or null if not a bounce
|
||||
*/
|
||||
processBounceEmail(bounceEmail: Email): Promise<BounceRecord | null>;
|
||||
/**
|
||||
* Handle a hard bounce by adding to suppression list
|
||||
* @param bounce The bounce record
|
||||
*/
|
||||
private handleHardBounce;
|
||||
/**
|
||||
* Handle a soft bounce by scheduling a retry if eligible
|
||||
* @param bounce The bounce record
|
||||
*/
|
||||
private handleSoftBounce;
|
||||
/**
|
||||
* Add an email address to the suppression list
|
||||
* @param email Email address to suppress
|
||||
* @param reason Reason for suppression
|
||||
* @param expiresAt Expiration timestamp (undefined for permanent)
|
||||
*/
|
||||
addToSuppressionList(email: string, reason: string, expiresAt?: number): void;
|
||||
/**
|
||||
* Remove an email address from the suppression list
|
||||
* @param email Email address to remove
|
||||
*/
|
||||
removeFromSuppressionList(email: string): void;
|
||||
/**
|
||||
* Check if an email is on the suppression list
|
||||
* @param email Email address to check
|
||||
* @returns Whether the email is suppressed
|
||||
*/
|
||||
isEmailSuppressed(email: string): boolean;
|
||||
/**
|
||||
* Get suppression information for an email
|
||||
* @param email Email address to check
|
||||
* @returns Suppression information or null if not suppressed
|
||||
*/
|
||||
getSuppressionInfo(email: string): {
|
||||
reason: string;
|
||||
timestamp: number;
|
||||
expiresAt?: number;
|
||||
} | null;
|
||||
/**
|
||||
* Save suppression list to disk
|
||||
*/
|
||||
private saveSuppressionList;
|
||||
/**
|
||||
* Load suppression list from disk
|
||||
*/
|
||||
private loadSuppressionList;
|
||||
/**
|
||||
* Save bounce record to disk
|
||||
* @param bounce Bounce record to save
|
||||
*/
|
||||
private saveBounceRecord;
|
||||
/**
|
||||
* Update bounce cache with new bounce information
|
||||
* @param bounce Bounce record to update cache with
|
||||
*/
|
||||
private updateBounceCache;
|
||||
/**
|
||||
* Check bounce history for an email address
|
||||
* @param email Email address to check
|
||||
* @returns Bounce information or null if no bounces
|
||||
*/
|
||||
getBounceInfo(email: string): {
|
||||
lastBounce: number;
|
||||
count: number;
|
||||
type: BounceType;
|
||||
category: BounceCategory;
|
||||
} | null;
|
||||
/**
|
||||
* Get all known hard bounced addresses
|
||||
* @returns Array of hard bounced email addresses
|
||||
*/
|
||||
getHardBouncedAddresses(): string[];
|
||||
/**
|
||||
* Get suppression list
|
||||
* @returns Array of suppressed email addresses
|
||||
*/
|
||||
getSuppressionList(): string[];
|
||||
/**
|
||||
* Clear old bounce records (for maintenance)
|
||||
* @param olderThan Timestamp to remove records older than
|
||||
* @returns Number of records removed
|
||||
*/
|
||||
clearOldBounceRecords(olderThan: number): number;
|
||||
}
|
||||
export {};
|
||||
File diff suppressed because one or more lines are too long
291
dist_ts/mail/core/classes.email.d.ts
vendored
291
dist_ts/mail/core/classes.email.d.ts
vendored
@@ -1,291 +0,0 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
export interface IAttachment {
|
||||
filename: string;
|
||||
content: Buffer;
|
||||
contentType: string;
|
||||
contentId?: string;
|
||||
encoding?: string;
|
||||
}
|
||||
export interface IEmailOptions {
|
||||
from: string;
|
||||
to?: string | string[];
|
||||
cc?: string | string[];
|
||||
bcc?: string | string[];
|
||||
subject: string;
|
||||
text: string;
|
||||
html?: string;
|
||||
attachments?: IAttachment[];
|
||||
headers?: Record<string, string>;
|
||||
mightBeSpam?: boolean;
|
||||
priority?: 'high' | 'normal' | 'low';
|
||||
skipAdvancedValidation?: boolean;
|
||||
variables?: Record<string, any>;
|
||||
}
|
||||
/**
|
||||
* Email class represents a complete email message.
|
||||
*
|
||||
* This class takes IEmailOptions in the constructor and normalizes the data:
|
||||
* - 'to', 'cc', 'bcc' are always converted to arrays
|
||||
* - Optional properties get default values
|
||||
* - Additional properties like messageId and envelopeFrom are generated
|
||||
*/
|
||||
export declare class Email {
|
||||
from: string;
|
||||
to: string[];
|
||||
cc: string[];
|
||||
bcc: string[];
|
||||
subject: string;
|
||||
text: string;
|
||||
html?: string;
|
||||
attachments: IAttachment[];
|
||||
headers: Record<string, string>;
|
||||
mightBeSpam: boolean;
|
||||
priority: 'high' | 'normal' | 'low';
|
||||
variables: Record<string, any>;
|
||||
private envelopeFrom;
|
||||
private messageId;
|
||||
private static emailValidator;
|
||||
constructor(options: IEmailOptions);
|
||||
/**
|
||||
* Validates an email address using smartmail's EmailAddressValidator
|
||||
* For constructor validation, we only check syntax to avoid delays
|
||||
* Supports RFC-compliant addresses including display names and bounce addresses.
|
||||
*
|
||||
* @param email The email address to validate
|
||||
* @returns boolean indicating if the email is valid
|
||||
*/
|
||||
private isValidEmail;
|
||||
/**
|
||||
* Extracts the email address from a string that may contain a display name.
|
||||
* Handles formats like:
|
||||
* - simple@example.com
|
||||
* - "John Doe" <john@example.com>
|
||||
* - John Doe <john@example.com>
|
||||
*
|
||||
* @param emailString The email string to parse
|
||||
* @returns The extracted email address or null
|
||||
*/
|
||||
private extractEmailAddress;
|
||||
/**
|
||||
* Parses and validates recipient email addresses
|
||||
* @param recipients A string or array of recipient emails
|
||||
* @returns Array of validated email addresses
|
||||
*/
|
||||
private parseRecipients;
|
||||
/**
|
||||
* Basic sanitization for strings to prevent header injection
|
||||
* @param input The string to sanitize
|
||||
* @returns Sanitized string
|
||||
*/
|
||||
private sanitizeString;
|
||||
/**
|
||||
* Gets the domain part of the from email address
|
||||
* @returns The domain part of the from email or null if invalid
|
||||
*/
|
||||
getFromDomain(): string | null;
|
||||
/**
|
||||
* Gets the clean from email address without display name
|
||||
* @returns The email address without display name
|
||||
*/
|
||||
getFromAddress(): string;
|
||||
/**
|
||||
* Converts IDN (International Domain Names) to ASCII
|
||||
* @param email The email address to convert
|
||||
* @returns The email with ASCII-converted domain
|
||||
*/
|
||||
private convertIDNToASCII;
|
||||
/**
|
||||
* Gets clean to email addresses without display names
|
||||
* @returns Array of email addresses without display names
|
||||
*/
|
||||
getToAddresses(): string[];
|
||||
/**
|
||||
* Gets clean cc email addresses without display names
|
||||
* @returns Array of email addresses without display names
|
||||
*/
|
||||
getCcAddresses(): string[];
|
||||
/**
|
||||
* Gets clean bcc email addresses without display names
|
||||
* @returns Array of email addresses without display names
|
||||
*/
|
||||
getBccAddresses(): string[];
|
||||
/**
|
||||
* Gets all recipients (to, cc, bcc) as a unique array
|
||||
* @returns Array of all unique recipient email addresses
|
||||
*/
|
||||
getAllRecipients(): string[];
|
||||
/**
|
||||
* Gets primary recipient (first in the to field)
|
||||
* @returns The primary recipient email or null if none exists
|
||||
*/
|
||||
getPrimaryRecipient(): string | null;
|
||||
/**
|
||||
* Checks if the email has attachments
|
||||
* @returns Boolean indicating if the email has attachments
|
||||
*/
|
||||
hasAttachments(): boolean;
|
||||
/**
|
||||
* Add a recipient to the email
|
||||
* @param email The recipient email address
|
||||
* @param type The recipient type (to, cc, bcc)
|
||||
* @returns This instance for method chaining
|
||||
*/
|
||||
addRecipient(email: string, type?: 'to' | 'cc' | 'bcc'): this;
|
||||
/**
|
||||
* Add an attachment to the email
|
||||
* @param attachment The attachment to add
|
||||
* @returns This instance for method chaining
|
||||
*/
|
||||
addAttachment(attachment: IAttachment): this;
|
||||
/**
|
||||
* Add a custom header to the email
|
||||
* @param name The header name
|
||||
* @param value The header value
|
||||
* @returns This instance for method chaining
|
||||
*/
|
||||
addHeader(name: string, value: string): this;
|
||||
/**
|
||||
* Set the email priority
|
||||
* @param priority The priority level
|
||||
* @returns This instance for method chaining
|
||||
*/
|
||||
setPriority(priority: 'high' | 'normal' | 'low'): this;
|
||||
/**
|
||||
* Set a template variable
|
||||
* @param key The variable key
|
||||
* @param value The variable value
|
||||
* @returns This instance for method chaining
|
||||
*/
|
||||
setVariable(key: string, value: any): this;
|
||||
/**
|
||||
* Set multiple template variables at once
|
||||
* @param variables The variables object
|
||||
* @returns This instance for method chaining
|
||||
*/
|
||||
setVariables(variables: Record<string, any>): this;
|
||||
/**
|
||||
* Get the subject with variables applied
|
||||
* @param variables Optional additional variables to apply
|
||||
* @returns The processed subject
|
||||
*/
|
||||
getSubjectWithVariables(variables?: Record<string, any>): string;
|
||||
/**
|
||||
* Get the text content with variables applied
|
||||
* @param variables Optional additional variables to apply
|
||||
* @returns The processed text content
|
||||
*/
|
||||
getTextWithVariables(variables?: Record<string, any>): string;
|
||||
/**
|
||||
* Get the HTML content with variables applied
|
||||
* @param variables Optional additional variables to apply
|
||||
* @returns The processed HTML content or undefined if none
|
||||
*/
|
||||
getHtmlWithVariables(variables?: Record<string, any>): string | undefined;
|
||||
/**
|
||||
* Apply template variables to a string
|
||||
* @param template The template string
|
||||
* @param additionalVariables Optional additional variables to apply
|
||||
* @returns The processed string
|
||||
*/
|
||||
private applyVariables;
|
||||
/**
|
||||
* Gets the total size of all attachments in bytes
|
||||
* @returns Total size of all attachments in bytes
|
||||
*/
|
||||
getAttachmentsSize(): number;
|
||||
/**
|
||||
* Perform advanced validation on sender and recipient email addresses
|
||||
* This should be called separately after instantiation when ready to check MX records
|
||||
* @param options Validation options
|
||||
* @returns Promise resolving to validation results for all addresses
|
||||
*/
|
||||
validateAddresses(options?: {
|
||||
checkMx?: boolean;
|
||||
checkDisposable?: boolean;
|
||||
checkSenderOnly?: boolean;
|
||||
checkFirstRecipientOnly?: boolean;
|
||||
}): Promise<{
|
||||
sender: {
|
||||
email: string;
|
||||
result: any;
|
||||
};
|
||||
recipients: Array<{
|
||||
email: string;
|
||||
result: any;
|
||||
}>;
|
||||
isValid: boolean;
|
||||
}>;
|
||||
/**
|
||||
* Convert this email to a smartmail instance
|
||||
* @returns A new Smartmail instance
|
||||
*/
|
||||
toSmartmail(): Promise<plugins.smartmail.Smartmail<any>>;
|
||||
/**
|
||||
* Get the from email address
|
||||
* @returns The from email address
|
||||
*/
|
||||
getFromEmail(): string;
|
||||
/**
|
||||
* Get the subject (Smartmail compatibility method)
|
||||
* @returns The email subject
|
||||
*/
|
||||
getSubject(): string;
|
||||
/**
|
||||
* Get the body content (Smartmail compatibility method)
|
||||
* @param isHtml Whether to return HTML content if available
|
||||
* @returns The email body (HTML if requested and available, otherwise plain text)
|
||||
*/
|
||||
getBody(isHtml?: boolean): string;
|
||||
/**
|
||||
* Get the from address (Smartmail compatibility method)
|
||||
* @returns The sender email address
|
||||
*/
|
||||
getFrom(): string;
|
||||
/**
|
||||
* Get the message ID
|
||||
* @returns The message ID
|
||||
*/
|
||||
getMessageId(): string;
|
||||
/**
|
||||
* Convert the Email instance back to IEmailOptions format.
|
||||
* Useful for serialization or passing to APIs that expect IEmailOptions.
|
||||
* Note: This loses some Email-specific properties like messageId and envelopeFrom.
|
||||
*
|
||||
* @returns IEmailOptions representation of this email
|
||||
*/
|
||||
toEmailOptions(): IEmailOptions;
|
||||
/**
|
||||
* Set a custom message ID
|
||||
* @param id The message ID to set
|
||||
* @returns This instance for method chaining
|
||||
*/
|
||||
setMessageId(id: string): this;
|
||||
/**
|
||||
* Get the envelope from address (return-path)
|
||||
* @returns The envelope from address
|
||||
*/
|
||||
getEnvelopeFrom(): string;
|
||||
/**
|
||||
* Set the envelope from address (return-path)
|
||||
* @param address The envelope from address to set
|
||||
* @returns This instance for method chaining
|
||||
*/
|
||||
setEnvelopeFrom(address: string): this;
|
||||
/**
|
||||
* Creates an RFC822 compliant email string
|
||||
* @param variables Optional template variables to apply
|
||||
* @returns The email formatted as an RFC822 compliant string
|
||||
*/
|
||||
toRFC822String(variables?: Record<string, any>): string;
|
||||
/**
|
||||
* Convert to simple Smartmail-compatible object (for backward compatibility)
|
||||
* @returns A Promise with a simple Smartmail-compatible object
|
||||
*/
|
||||
toSmartmailBasic(): Promise<any>;
|
||||
/**
|
||||
* Create an Email instance from a Smartmail object
|
||||
* @param smartmail The Smartmail instance to convert
|
||||
* @returns A new Email instance
|
||||
*/
|
||||
static fromSmartmail(smartmail: plugins.smartmail.Smartmail<any>): Email;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
61
dist_ts/mail/core/classes.emailvalidator.d.ts
vendored
61
dist_ts/mail/core/classes.emailvalidator.d.ts
vendored
@@ -1,61 +0,0 @@
|
||||
export interface IEmailValidationResult {
|
||||
isValid: boolean;
|
||||
hasMx: boolean;
|
||||
hasSpamMarkings: boolean;
|
||||
score: number;
|
||||
details?: {
|
||||
formatValid?: boolean;
|
||||
mxRecords?: string[];
|
||||
disposable?: boolean;
|
||||
role?: boolean;
|
||||
spamIndicators?: string[];
|
||||
errorMessage?: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Advanced email validator class using smartmail's capabilities
|
||||
*/
|
||||
export declare class EmailValidator {
|
||||
private validator;
|
||||
private dnsCache;
|
||||
constructor(options?: {
|
||||
maxCacheSize?: number;
|
||||
cacheTTL?: number;
|
||||
});
|
||||
/**
|
||||
* Validates an email address using comprehensive checks
|
||||
* @param email The email to validate
|
||||
* @param options Validation options
|
||||
* @returns Validation result with details
|
||||
*/
|
||||
validate(email: string, options?: {
|
||||
checkMx?: boolean;
|
||||
checkDisposable?: boolean;
|
||||
checkRole?: boolean;
|
||||
checkSyntaxOnly?: boolean;
|
||||
}): Promise<IEmailValidationResult>;
|
||||
/**
|
||||
* Gets MX records for a domain with caching
|
||||
* @param domain Domain to check
|
||||
* @returns Array of MX records
|
||||
*/
|
||||
private getMxRecords;
|
||||
/**
|
||||
* Validates multiple email addresses in batch
|
||||
* @param emails Array of emails to validate
|
||||
* @param options Validation options
|
||||
* @returns Object with email addresses as keys and validation results as values
|
||||
*/
|
||||
validateBatch(emails: string[], options?: {
|
||||
checkMx?: boolean;
|
||||
checkDisposable?: boolean;
|
||||
checkRole?: boolean;
|
||||
checkSyntaxOnly?: boolean;
|
||||
}): Promise<Record<string, IEmailValidationResult>>;
|
||||
/**
|
||||
* Quick check if an email format is valid (synchronous, no DNS checks)
|
||||
* @param email Email to check
|
||||
* @returns Boolean indicating if format is valid
|
||||
*/
|
||||
isValidFormat(email: string): boolean;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
95
dist_ts/mail/core/classes.templatemanager.d.ts
vendored
95
dist_ts/mail/core/classes.templatemanager.d.ts
vendored
@@ -1,95 +0,0 @@
|
||||
import { Email } from './classes.email.js';
|
||||
/**
|
||||
* Email template type definition
|
||||
*/
|
||||
export interface IEmailTemplate<T = any> {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
from: string;
|
||||
subject: string;
|
||||
bodyHtml: string;
|
||||
bodyText?: string;
|
||||
category?: string;
|
||||
sampleData?: T;
|
||||
attachments?: Array<{
|
||||
name: string;
|
||||
path: string;
|
||||
contentType?: string;
|
||||
}>;
|
||||
}
|
||||
/**
|
||||
* Email template context - data used to render the template
|
||||
*/
|
||||
export interface ITemplateContext {
|
||||
[key: string]: any;
|
||||
}
|
||||
/**
|
||||
* Template category definitions
|
||||
*/
|
||||
export declare enum TemplateCategory {
|
||||
NOTIFICATION = "notification",
|
||||
TRANSACTIONAL = "transactional",
|
||||
MARKETING = "marketing",
|
||||
SYSTEM = "system"
|
||||
}
|
||||
/**
|
||||
* Enhanced template manager using Email class for template rendering
|
||||
*/
|
||||
export declare class TemplateManager {
|
||||
private templates;
|
||||
private defaultConfig;
|
||||
constructor(defaultConfig?: {
|
||||
from?: string;
|
||||
replyTo?: string;
|
||||
footerHtml?: string;
|
||||
footerText?: string;
|
||||
});
|
||||
/**
|
||||
* Register built-in email templates
|
||||
*/
|
||||
private registerBuiltinTemplates;
|
||||
/**
|
||||
* Register a new email template
|
||||
* @param template The email template to register
|
||||
*/
|
||||
registerTemplate<T = any>(template: IEmailTemplate<T>): void;
|
||||
/**
|
||||
* Get an email template by ID
|
||||
* @param templateId The template ID
|
||||
* @returns The template or undefined if not found
|
||||
*/
|
||||
getTemplate<T = any>(templateId: string): IEmailTemplate<T> | undefined;
|
||||
/**
|
||||
* List all available templates
|
||||
* @param category Optional category filter
|
||||
* @returns Array of email templates
|
||||
*/
|
||||
listTemplates(category?: TemplateCategory): IEmailTemplate[];
|
||||
/**
|
||||
* Create an Email instance from a template
|
||||
* @param templateId The template ID
|
||||
* @param context The template context data
|
||||
* @returns A configured Email instance
|
||||
*/
|
||||
createEmail<T = any>(templateId: string, context?: ITemplateContext): Promise<Email>;
|
||||
/**
|
||||
* Create and completely process an Email instance from a template
|
||||
* @param templateId The template ID
|
||||
* @param context The template context data
|
||||
* @returns A complete, processed Email instance ready to send
|
||||
*/
|
||||
prepareEmail<T = any>(templateId: string, context?: ITemplateContext): Promise<Email>;
|
||||
/**
|
||||
* Create a MIME-formatted email from a template
|
||||
* @param templateId The template ID
|
||||
* @param context The template context data
|
||||
* @returns A MIME-formatted email string
|
||||
*/
|
||||
createMimeEmail(templateId: string, context?: ITemplateContext): Promise<string>;
|
||||
/**
|
||||
* Load templates from a directory
|
||||
* @param directory The directory containing template JSON files
|
||||
*/
|
||||
loadTemplatesFromDirectory(directory: string): Promise<void>;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
4
dist_ts/mail/core/index.d.ts
vendored
4
dist_ts/mail/core/index.d.ts
vendored
@@ -1,4 +0,0 @@
|
||||
export * from './classes.email.js';
|
||||
export * from './classes.emailvalidator.js';
|
||||
export * from './classes.templatemanager.js';
|
||||
export * from './classes.bouncemanager.js';
|
||||
@@ -1,6 +0,0 @@
|
||||
// Core email components
|
||||
export * from './classes.email.js';
|
||||
export * from './classes.emailvalidator.js';
|
||||
export * from './classes.templatemanager.js';
|
||||
export * from './classes.bouncemanager.js';
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL2NvcmUvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsd0JBQXdCO0FBQ3hCLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLDhCQUE4QixDQUFDO0FBQzdDLGNBQWMsNEJBQTRCLENBQUMifQ==
|
||||
163
dist_ts/mail/delivery/classes.delivery.queue.d.ts
vendored
163
dist_ts/mail/delivery/classes.delivery.queue.d.ts
vendored
@@ -1,163 +0,0 @@
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { type EmailProcessingMode } from '../routing/classes.email.config.js';
|
||||
import type { IEmailRoute } from '../routing/interfaces.js';
|
||||
/**
|
||||
* Queue item status
|
||||
*/
|
||||
export type QueueItemStatus = 'pending' | 'processing' | 'delivered' | 'failed' | 'deferred';
|
||||
/**
|
||||
* Queue item interface
|
||||
*/
|
||||
export interface IQueueItem {
|
||||
id: string;
|
||||
processingMode: EmailProcessingMode;
|
||||
processingResult: any;
|
||||
route: IEmailRoute;
|
||||
status: QueueItemStatus;
|
||||
attempts: number;
|
||||
nextAttempt: Date;
|
||||
lastError?: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
deliveredAt?: Date;
|
||||
}
|
||||
/**
|
||||
* Queue options interface
|
||||
*/
|
||||
export interface IQueueOptions {
|
||||
storageType?: 'memory' | 'disk';
|
||||
persistentPath?: string;
|
||||
checkInterval?: number;
|
||||
maxQueueSize?: number;
|
||||
maxPerDestination?: number;
|
||||
maxRetries?: number;
|
||||
baseRetryDelay?: number;
|
||||
maxRetryDelay?: number;
|
||||
}
|
||||
/**
|
||||
* Queue statistics interface
|
||||
*/
|
||||
export interface IQueueStats {
|
||||
queueSize: number;
|
||||
status: {
|
||||
pending: number;
|
||||
processing: number;
|
||||
delivered: number;
|
||||
failed: number;
|
||||
deferred: number;
|
||||
};
|
||||
modes: {
|
||||
forward: number;
|
||||
mta: number;
|
||||
process: number;
|
||||
};
|
||||
oldestItem?: Date;
|
||||
newestItem?: Date;
|
||||
averageAttempts: number;
|
||||
totalProcessed: number;
|
||||
processingActive: boolean;
|
||||
}
|
||||
/**
|
||||
* A unified queue for all email modes
|
||||
*/
|
||||
export declare class UnifiedDeliveryQueue extends EventEmitter {
|
||||
private options;
|
||||
private queue;
|
||||
private checkTimer?;
|
||||
private stats;
|
||||
private processing;
|
||||
private totalProcessed;
|
||||
/**
|
||||
* Create a new unified delivery queue
|
||||
* @param options Queue options
|
||||
*/
|
||||
constructor(options: IQueueOptions);
|
||||
/**
|
||||
* Initialize the queue
|
||||
*/
|
||||
initialize(): Promise<void>;
|
||||
/**
|
||||
* Start queue processing
|
||||
*/
|
||||
private startProcessing;
|
||||
/**
|
||||
* Stop queue processing
|
||||
*/
|
||||
private stopProcessing;
|
||||
/**
|
||||
* Check for items that need to be processed
|
||||
*/
|
||||
private processQueue;
|
||||
/**
|
||||
* Add an item to the queue
|
||||
* @param processingResult Processing result to queue
|
||||
* @param mode Processing mode
|
||||
* @param route Email route
|
||||
*/
|
||||
enqueue(processingResult: any, mode: EmailProcessingMode, route: IEmailRoute): Promise<string>;
|
||||
/**
|
||||
* Get an item from the queue
|
||||
* @param id Item ID
|
||||
*/
|
||||
getItem(id: string): IQueueItem | undefined;
|
||||
/**
|
||||
* Mark an item as being processed
|
||||
* @param id Item ID
|
||||
*/
|
||||
markProcessing(id: string): Promise<boolean>;
|
||||
/**
|
||||
* Mark an item as delivered
|
||||
* @param id Item ID
|
||||
*/
|
||||
markDelivered(id: string): Promise<boolean>;
|
||||
/**
|
||||
* Mark an item as failed
|
||||
* @param id Item ID
|
||||
* @param error Error message
|
||||
*/
|
||||
markFailed(id: string, error: string): Promise<boolean>;
|
||||
/**
|
||||
* Remove an item from the queue
|
||||
* @param id Item ID
|
||||
*/
|
||||
removeItem(id: string): Promise<boolean>;
|
||||
/**
|
||||
* Persist an item to disk
|
||||
* @param item Item to persist
|
||||
*/
|
||||
private persistItem;
|
||||
/**
|
||||
* Remove an item from disk
|
||||
* @param id Item ID
|
||||
*/
|
||||
private removeItemFromDisk;
|
||||
/**
|
||||
* Load queue items from disk
|
||||
*/
|
||||
private loadFromDisk;
|
||||
/**
|
||||
* Update queue statistics
|
||||
*/
|
||||
private updateStats;
|
||||
/**
|
||||
* Get queue statistics
|
||||
*/
|
||||
getStats(): IQueueStats;
|
||||
/**
|
||||
* Pause queue processing
|
||||
*/
|
||||
pause(): void;
|
||||
/**
|
||||
* Resume queue processing
|
||||
*/
|
||||
resume(): void;
|
||||
/**
|
||||
* Clean up old delivered and failed items
|
||||
* @param maxAge Maximum age in milliseconds (default: 7 days)
|
||||
*/
|
||||
cleanupOldItems(maxAge?: number): Promise<number>;
|
||||
/**
|
||||
* Shutdown the queue
|
||||
*/
|
||||
shutdown(): Promise<void>;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
186
dist_ts/mail/delivery/classes.delivery.system.d.ts
vendored
186
dist_ts/mail/delivery/classes.delivery.system.d.ts
vendored
@@ -1,186 +0,0 @@
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { UnifiedDeliveryQueue, type IQueueItem } from './classes.delivery.queue.js';
|
||||
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.js';
|
||||
/**
|
||||
* Delivery status enumeration
|
||||
*/
|
||||
export declare enum DeliveryStatus {
|
||||
PENDING = "pending",
|
||||
DELIVERING = "delivering",
|
||||
DELIVERED = "delivered",
|
||||
DEFERRED = "deferred",
|
||||
FAILED = "failed"
|
||||
}
|
||||
/**
|
||||
* Delivery handler interface
|
||||
*/
|
||||
export interface IDeliveryHandler {
|
||||
deliver(item: IQueueItem): Promise<any>;
|
||||
}
|
||||
/**
|
||||
* Delivery options
|
||||
*/
|
||||
export interface IMultiModeDeliveryOptions {
|
||||
connectionPoolSize?: number;
|
||||
socketTimeout?: number;
|
||||
concurrentDeliveries?: number;
|
||||
sendTimeout?: number;
|
||||
verifyCertificates?: boolean;
|
||||
tlsMinVersion?: string;
|
||||
forwardHandler?: IDeliveryHandler;
|
||||
deliveryHandler?: IDeliveryHandler;
|
||||
processHandler?: IDeliveryHandler;
|
||||
globalRateLimit?: number;
|
||||
perPatternRateLimit?: Record<string, number>;
|
||||
processBounces?: boolean;
|
||||
bounceHandler?: {
|
||||
processSmtpFailure: (recipient: string, smtpResponse: string, options: any) => Promise<any>;
|
||||
};
|
||||
onDeliveryStart?: (item: IQueueItem) => Promise<void>;
|
||||
onDeliverySuccess?: (item: IQueueItem, result: any) => Promise<void>;
|
||||
onDeliveryFailed?: (item: IQueueItem, error: string) => Promise<void>;
|
||||
}
|
||||
/**
|
||||
* Delivery system statistics
|
||||
*/
|
||||
export interface IDeliveryStats {
|
||||
activeDeliveries: number;
|
||||
totalSuccessful: number;
|
||||
totalFailed: number;
|
||||
avgDeliveryTime: number;
|
||||
byMode: {
|
||||
forward: {
|
||||
successful: number;
|
||||
failed: number;
|
||||
};
|
||||
mta: {
|
||||
successful: number;
|
||||
failed: number;
|
||||
};
|
||||
process: {
|
||||
successful: number;
|
||||
failed: number;
|
||||
};
|
||||
};
|
||||
rateLimiting: {
|
||||
currentRate: number;
|
||||
globalLimit: number;
|
||||
throttled: number;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Handles delivery for all email processing modes
|
||||
*/
|
||||
export declare class MultiModeDeliverySystem extends EventEmitter {
|
||||
private queue;
|
||||
private options;
|
||||
private stats;
|
||||
private deliveryTimes;
|
||||
private activeDeliveries;
|
||||
private running;
|
||||
private throttled;
|
||||
private rateLimitLastCheck;
|
||||
private rateLimitCounter;
|
||||
private emailServer?;
|
||||
/**
|
||||
* Create a new multi-mode delivery system
|
||||
* @param queue Unified delivery queue
|
||||
* @param options Delivery options
|
||||
* @param emailServer Optional reference to unified email server for SmtpClient access
|
||||
*/
|
||||
constructor(queue: UnifiedDeliveryQueue, options: IMultiModeDeliveryOptions, emailServer?: UnifiedEmailServer);
|
||||
/**
|
||||
* Start the delivery system
|
||||
*/
|
||||
start(): Promise<void>;
|
||||
/**
|
||||
* Stop the delivery system
|
||||
*/
|
||||
stop(): Promise<void>;
|
||||
/**
|
||||
* Process ready items from the queue
|
||||
* @param items Queue items ready for processing
|
||||
*/
|
||||
private processItems;
|
||||
/**
|
||||
* Deliver an item from the queue
|
||||
* @param item Queue item to deliver
|
||||
*/
|
||||
private deliverItem;
|
||||
/**
|
||||
* Default handler for forward mode delivery
|
||||
* @param item Queue item
|
||||
*/
|
||||
private handleForwardDelivery;
|
||||
/**
|
||||
* Legacy forward delivery using raw sockets (fallback)
|
||||
* @param item Queue item
|
||||
*/
|
||||
private handleForwardDeliveryLegacy;
|
||||
/**
|
||||
* Complete the SMTP exchange after connection and initial setup
|
||||
* @param socket Network socket
|
||||
* @param email Email to send
|
||||
* @param rule Domain rule
|
||||
*/
|
||||
private completeSMTPExchange;
|
||||
/**
|
||||
* Default handler for MTA mode delivery
|
||||
* @param item Queue item
|
||||
*/
|
||||
private handleMtaDelivery;
|
||||
/**
|
||||
* Default handler for process mode delivery
|
||||
* @param item Queue item
|
||||
*/
|
||||
private handleProcessDelivery;
|
||||
/**
|
||||
* Get file extension from filename
|
||||
*/
|
||||
private getFileExtension;
|
||||
/**
|
||||
* Apply DKIM signing to an email
|
||||
*/
|
||||
private applyDkimSigning;
|
||||
/**
|
||||
* Format email for SMTP transmission
|
||||
* @param email Email to format
|
||||
*/
|
||||
private getFormattedEmail;
|
||||
/**
|
||||
* Send SMTP command and wait for response
|
||||
* @param socket Socket connection
|
||||
* @param command SMTP command to send
|
||||
*/
|
||||
private smtpCommand;
|
||||
/**
|
||||
* Send SMTP DATA command with content
|
||||
* @param socket Socket connection
|
||||
* @param data Email content to send
|
||||
*/
|
||||
private smtpData;
|
||||
/**
|
||||
* Upgrade socket to TLS
|
||||
* @param socket Socket connection
|
||||
* @param hostname Target hostname for TLS
|
||||
*/
|
||||
private upgradeTls;
|
||||
/**
|
||||
* Update delivery time statistics
|
||||
*/
|
||||
private updateDeliveryTimeStats;
|
||||
/**
|
||||
* Check if rate limit is exceeded
|
||||
* @returns True if rate limited, false otherwise
|
||||
*/
|
||||
private checkRateLimit;
|
||||
/**
|
||||
* Update delivery options
|
||||
* @param options New options
|
||||
*/
|
||||
updateOptions(options: Partial<IMultiModeDeliveryOptions>): void;
|
||||
/**
|
||||
* Get delivery statistics
|
||||
*/
|
||||
getStats(): IDeliveryStats;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
84
dist_ts/mail/delivery/classes.emailsendjob.d.ts
vendored
84
dist_ts/mail/delivery/classes.emailsendjob.d.ts
vendored
@@ -1,84 +0,0 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import { Email } from '../core/classes.email.js';
|
||||
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.js';
|
||||
export interface IEmailSendOptions {
|
||||
maxRetries?: number;
|
||||
retryDelay?: number;
|
||||
connectionTimeout?: number;
|
||||
tlsOptions?: plugins.tls.ConnectionOptions;
|
||||
debugMode?: boolean;
|
||||
}
|
||||
export declare enum DeliveryStatus {
|
||||
PENDING = "pending",
|
||||
SENDING = "sending",
|
||||
DELIVERED = "delivered",
|
||||
FAILED = "failed",
|
||||
DEFERRED = "deferred"
|
||||
}
|
||||
export interface DeliveryInfo {
|
||||
status: DeliveryStatus;
|
||||
attempts: number;
|
||||
error?: Error;
|
||||
lastAttempt?: Date;
|
||||
nextAttempt?: Date;
|
||||
mxServer?: string;
|
||||
deliveryTime?: Date;
|
||||
logs: string[];
|
||||
}
|
||||
export declare class EmailSendJob {
|
||||
emailServerRef: UnifiedEmailServer;
|
||||
private email;
|
||||
private mxServers;
|
||||
private currentMxIndex;
|
||||
private options;
|
||||
deliveryInfo: DeliveryInfo;
|
||||
constructor(emailServerRef: UnifiedEmailServer, emailArg: Email, options?: IEmailSendOptions);
|
||||
/**
|
||||
* Send the email to its recipients
|
||||
*/
|
||||
send(): Promise<DeliveryStatus>;
|
||||
/**
|
||||
* Validate the email before sending
|
||||
*/
|
||||
private validateEmail;
|
||||
/**
|
||||
* Resolve MX records for the recipient domain
|
||||
*/
|
||||
private resolveMxRecords;
|
||||
/**
|
||||
* Attempt to deliver the email with retries
|
||||
*/
|
||||
private attemptDelivery;
|
||||
/**
|
||||
* Connect to a specific MX server and send the email using SmtpClient
|
||||
*/
|
||||
private connectAndSend;
|
||||
/**
|
||||
* Record delivery event for monitoring
|
||||
*/
|
||||
private recordDeliveryEvent;
|
||||
/**
|
||||
* Check if an error represents a permanent failure
|
||||
*/
|
||||
private isPermanentFailure;
|
||||
/**
|
||||
* Resolve MX records for a domain
|
||||
*/
|
||||
private resolveMx;
|
||||
/**
|
||||
* Log a message with timestamp
|
||||
*/
|
||||
private log;
|
||||
/**
|
||||
* Save successful email to storage
|
||||
*/
|
||||
private saveSuccess;
|
||||
/**
|
||||
* Save failed email to storage
|
||||
*/
|
||||
private saveFailed;
|
||||
/**
|
||||
* Delay for specified milliseconds
|
||||
*/
|
||||
private delay;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
18
dist_ts/mail/delivery/classes.emailsignjob.d.ts
vendored
18
dist_ts/mail/delivery/classes.emailsignjob.d.ts
vendored
@@ -1,18 +0,0 @@
|
||||
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.js';
|
||||
interface Headers {
|
||||
[key: string]: string;
|
||||
}
|
||||
interface IEmailSignJobOptions {
|
||||
domain: string;
|
||||
selector: string;
|
||||
headers: Headers;
|
||||
body: string;
|
||||
}
|
||||
export declare class EmailSignJob {
|
||||
emailServerRef: UnifiedEmailServer;
|
||||
jobOptions: IEmailSignJobOptions;
|
||||
constructor(emailServerRef: UnifiedEmailServer, options: IEmailSignJobOptions);
|
||||
loadPrivateKey(): Promise<string>;
|
||||
getSignatureHeader(emailMessage: string): Promise<string>;
|
||||
}
|
||||
export {};
|
||||
@@ -1,26 +0,0 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import { RustSecurityBridge } from '../../security/classes.rustsecuritybridge.js';
|
||||
export class EmailSignJob {
|
||||
emailServerRef;
|
||||
jobOptions;
|
||||
constructor(emailServerRef, options) {
|
||||
this.emailServerRef = emailServerRef;
|
||||
this.jobOptions = options;
|
||||
}
|
||||
async loadPrivateKey() {
|
||||
const keyInfo = await this.emailServerRef.dkimCreator.readDKIMKeys(this.jobOptions.domain);
|
||||
return keyInfo.privateKey;
|
||||
}
|
||||
async getSignatureHeader(emailMessage) {
|
||||
const privateKey = await this.loadPrivateKey();
|
||||
const bridge = RustSecurityBridge.getInstance();
|
||||
const signResult = await bridge.signDkim({
|
||||
rawMessage: emailMessage,
|
||||
domain: this.jobOptions.domain,
|
||||
selector: this.jobOptions.selector,
|
||||
privateKey,
|
||||
});
|
||||
return signResult.header;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5lbWFpbHNpZ25qb2IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL2RlbGl2ZXJ5L2NsYXNzZXMuZW1haWxzaWduam9iLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOENBQThDLENBQUM7QUFhbEYsTUFBTSxPQUFPLFlBQVk7SUFDdkIsY0FBYyxDQUFxQjtJQUNuQyxVQUFVLENBQXVCO0lBRWpDLFlBQVksY0FBa0MsRUFBRSxPQUE2QjtRQUMzRSxJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztRQUNyQyxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQztJQUM1QixDQUFDO0lBRUQsS0FBSyxDQUFDLGNBQWM7UUFDbEIsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMzRixPQUFPLE9BQU8sQ0FBQyxVQUFVLENBQUM7SUFDNUIsQ0FBQztJQUVNLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxZQUFvQjtRQUNsRCxNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUMvQyxNQUFNLE1BQU0sR0FBRyxrQkFBa0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNoRCxNQUFNLFVBQVUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUM7WUFDdkMsVUFBVSxFQUFFLFlBQVk7WUFDeEIsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTTtZQUM5QixRQUFRLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRO1lBQ2xDLFVBQVU7U0FDWCxDQUFDLENBQUM7UUFDSCxPQUFPLFVBQVUsQ0FBQyxNQUFNLENBQUM7SUFDM0IsQ0FBQztDQUNGIn0=
|
||||
22
dist_ts/mail/delivery/classes.mta.config.d.ts
vendored
22
dist_ts/mail/delivery/classes.mta.config.d.ts
vendored
@@ -1,22 +0,0 @@
|
||||
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.js';
|
||||
/**
|
||||
* Configures email server storage settings
|
||||
* @param emailServer Reference to the unified email server
|
||||
* @param options Configuration options containing storage paths
|
||||
*/
|
||||
export declare function configureEmailStorage(emailServer: UnifiedEmailServer, options: any): Promise<void>;
|
||||
/**
|
||||
* Configure email server with port and storage settings
|
||||
* @param emailServer Reference to the unified email server
|
||||
* @param config Configuration settings for email server
|
||||
*/
|
||||
export declare function configureEmailServer(emailServer: UnifiedEmailServer, config: {
|
||||
ports?: number[];
|
||||
hostname?: string;
|
||||
tls?: {
|
||||
certPath?: string;
|
||||
keyPath?: string;
|
||||
caPath?: string;
|
||||
};
|
||||
storagePath?: string;
|
||||
}): Promise<boolean>;
|
||||
@@ -1,51 +0,0 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import * as paths from '../../paths.js';
|
||||
/**
|
||||
* Configures email server storage settings
|
||||
* @param emailServer Reference to the unified email server
|
||||
* @param options Configuration options containing storage paths
|
||||
*/
|
||||
export async function configureEmailStorage(emailServer, options) {
|
||||
// Extract the receivedEmailsPath if available
|
||||
if (options?.emailPortConfig?.receivedEmailsPath) {
|
||||
const receivedEmailsPath = options.emailPortConfig.receivedEmailsPath;
|
||||
// Ensure the directory exists
|
||||
await plugins.smartfs.directory(receivedEmailsPath).recursive().create();
|
||||
// Set path for received emails
|
||||
if (emailServer) {
|
||||
// Storage paths are now handled by the unified email server system
|
||||
await plugins.smartfs.directory(paths.receivedEmailsDir).recursive().create();
|
||||
console.log(`Configured email server to store received emails to: ${receivedEmailsPath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Configure email server with port and storage settings
|
||||
* @param emailServer Reference to the unified email server
|
||||
* @param config Configuration settings for email server
|
||||
*/
|
||||
export async function configureEmailServer(emailServer, config) {
|
||||
if (!emailServer) {
|
||||
console.error('Email server not available');
|
||||
return false;
|
||||
}
|
||||
// Configure the email server with updated options
|
||||
const serverOptions = {
|
||||
ports: config.ports || [25, 587, 465],
|
||||
hostname: config.hostname || 'localhost',
|
||||
tls: config.tls
|
||||
};
|
||||
// Update the email server options
|
||||
emailServer.updateOptions(serverOptions);
|
||||
console.log(`Configured email server on ports ${serverOptions.ports.join(', ')}`);
|
||||
// Set up storage path if provided
|
||||
if (config.storagePath) {
|
||||
await configureEmailStorage(emailServer, {
|
||||
emailPortConfig: {
|
||||
receivedEmailsPath: config.storagePath
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5tdGEuY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvbWFpbC9kZWxpdmVyeS9jbGFzc2VzLm10YS5jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBR3hDOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLHFCQUFxQixDQUFDLFdBQStCLEVBQUUsT0FBWTtJQUN2Riw4Q0FBOEM7SUFDOUMsSUFBSSxPQUFPLEVBQUUsZUFBZSxFQUFFLGtCQUFrQixFQUFFLENBQUM7UUFDakQsTUFBTSxrQkFBa0IsR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLGtCQUFrQixDQUFDO1FBRXRFLDhCQUE4QjtRQUM5QixNQUFNLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7UUFFekUsK0JBQStCO1FBQy9CLElBQUksV0FBVyxFQUFFLENBQUM7WUFDaEIsbUVBQW1FO1lBQ25FLE1BQU0sT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFOUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3REFBd0Qsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO1FBQzVGLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLG9CQUFvQixDQUN4QyxXQUErQixFQUMvQixNQVNDO0lBRUQsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2pCLE9BQU8sQ0FBQyxLQUFLLENBQUMsNEJBQTRCLENBQUMsQ0FBQztRQUM1QyxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxrREFBa0Q7SUFDbEQsTUFBTSxhQUFhLEdBQUc7UUFDcEIsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQztRQUNyQyxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsSUFBSSxXQUFXO1FBQ3hDLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRztLQUNoQixDQUFDO0lBRUYsa0NBQWtDO0lBQ2xDLFdBQVcsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7SUFFekMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQ0FBb0MsYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBRWxGLGtDQUFrQztJQUNsQyxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN2QixNQUFNLHFCQUFxQixDQUFDLFdBQVcsRUFBRTtZQUN2QyxlQUFlLEVBQUU7Z0JBQ2Ysa0JBQWtCLEVBQUUsTUFBTSxDQUFDLFdBQVc7YUFDdkM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIn0=
|
||||
108
dist_ts/mail/delivery/classes.ratelimiter.d.ts
vendored
108
dist_ts/mail/delivery/classes.ratelimiter.d.ts
vendored
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Configuration options for rate limiter
|
||||
*/
|
||||
export interface IRateLimitConfig {
|
||||
/** Maximum tokens per period */
|
||||
maxPerPeriod: number;
|
||||
/** Time period in milliseconds */
|
||||
periodMs: number;
|
||||
/** Whether to apply per domain/key (vs globally) */
|
||||
perKey: boolean;
|
||||
/** Initial token count (defaults to max) */
|
||||
initialTokens?: number;
|
||||
/** Grace tokens to allow occasional bursts */
|
||||
burstTokens?: number;
|
||||
/** Apply global limit in addition to per-key limits */
|
||||
useGlobalLimit?: boolean;
|
||||
}
|
||||
/**
|
||||
* Rate limiter using token bucket algorithm
|
||||
* Provides more sophisticated rate limiting with burst handling
|
||||
*/
|
||||
export declare class RateLimiter {
|
||||
/** Rate limit configuration */
|
||||
private config;
|
||||
/** Token buckets per key */
|
||||
private buckets;
|
||||
/** Global bucket for non-keyed rate limiting */
|
||||
private globalBucket;
|
||||
/**
|
||||
* Create a new rate limiter
|
||||
* @param config Rate limiter configuration
|
||||
*/
|
||||
constructor(config: IRateLimitConfig);
|
||||
/**
|
||||
* Check if a request is allowed under rate limits
|
||||
* @param key Key to check rate limit for (e.g. domain, user, IP)
|
||||
* @param cost Token cost (defaults to 1)
|
||||
* @returns Whether the request is allowed
|
||||
*/
|
||||
isAllowed(key?: string, cost?: number): boolean;
|
||||
/**
|
||||
* Check if a bucket has enough tokens and consume them
|
||||
* @param bucket The token bucket to check
|
||||
* @param cost Token cost
|
||||
* @returns Whether tokens were consumed
|
||||
*/
|
||||
private checkBucket;
|
||||
/**
|
||||
* Consume tokens for a request (if available)
|
||||
* @param key Key to consume tokens for
|
||||
* @param cost Token cost (defaults to 1)
|
||||
* @returns Whether tokens were consumed
|
||||
*/
|
||||
consume(key?: string, cost?: number): boolean;
|
||||
/**
|
||||
* Get the remaining tokens for a key
|
||||
* @param key Key to check
|
||||
* @returns Number of remaining tokens
|
||||
*/
|
||||
getRemainingTokens(key?: string): number;
|
||||
/**
|
||||
* Get stats for a specific key
|
||||
* @param key Key to get stats for
|
||||
* @returns Rate limit statistics
|
||||
*/
|
||||
getStats(key?: string): {
|
||||
remaining: number;
|
||||
limit: number;
|
||||
resetIn: number;
|
||||
allowed: number;
|
||||
denied: number;
|
||||
};
|
||||
/**
|
||||
* Get or create a token bucket for a key
|
||||
* @param key The rate limit key
|
||||
* @returns Token bucket
|
||||
*/
|
||||
private getBucket;
|
||||
/**
|
||||
* Refill tokens in a bucket based on elapsed time
|
||||
* @param bucket Token bucket to refill
|
||||
*/
|
||||
private refillBucket;
|
||||
/**
|
||||
* Reset rate limits for a specific key
|
||||
* @param key Key to reset
|
||||
*/
|
||||
reset(key?: string): void;
|
||||
/**
|
||||
* Reset all rate limiters
|
||||
*/
|
||||
resetAll(): void;
|
||||
/**
|
||||
* Cleanup old buckets to prevent memory leaks
|
||||
* @param maxAge Maximum age in milliseconds
|
||||
*/
|
||||
cleanup(maxAge?: number): void;
|
||||
/**
|
||||
* Record an error for a key (e.g., IP address) and determine if blocking is needed
|
||||
* RFC 5321 Section 4.5.4.1 suggests limiting errors to prevent abuse
|
||||
*
|
||||
* @param key Key to record error for (typically an IP address)
|
||||
* @param errorWindow Time window for error tracking in ms (default: 5 minutes)
|
||||
* @param errorThreshold Maximum errors before blocking (default: 10)
|
||||
* @returns true if the key should be blocked due to excessive errors
|
||||
*/
|
||||
recordError(key: string, errorWindow?: number, errorThreshold?: number): boolean;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,275 +0,0 @@
|
||||
import { Email } from '../core/classes.email.js';
|
||||
import type { EmailProcessingMode } from './interfaces.js';
|
||||
/**
|
||||
* SMTP client connection options
|
||||
*/
|
||||
export type ISmtpClientOptions = {
|
||||
/**
|
||||
* Hostname of the SMTP server
|
||||
*/
|
||||
host: string;
|
||||
/**
|
||||
* Port to connect to
|
||||
*/
|
||||
port: number;
|
||||
/**
|
||||
* Whether to use TLS for the connection
|
||||
*/
|
||||
secure?: boolean;
|
||||
/**
|
||||
* Connection timeout in milliseconds
|
||||
*/
|
||||
connectionTimeout?: number;
|
||||
/**
|
||||
* Socket timeout in milliseconds
|
||||
*/
|
||||
socketTimeout?: number;
|
||||
/**
|
||||
* Command timeout in milliseconds
|
||||
*/
|
||||
commandTimeout?: number;
|
||||
/**
|
||||
* TLS options
|
||||
*/
|
||||
tls?: {
|
||||
/**
|
||||
* Whether to verify certificates
|
||||
*/
|
||||
rejectUnauthorized?: boolean;
|
||||
/**
|
||||
* Minimum TLS version
|
||||
*/
|
||||
minVersion?: string;
|
||||
/**
|
||||
* CA certificate path
|
||||
*/
|
||||
ca?: string;
|
||||
};
|
||||
/**
|
||||
* Authentication options
|
||||
*/
|
||||
auth?: {
|
||||
/**
|
||||
* Authentication user
|
||||
*/
|
||||
user: string;
|
||||
/**
|
||||
* Authentication password
|
||||
*/
|
||||
pass: string;
|
||||
/**
|
||||
* Authentication method
|
||||
*/
|
||||
method?: 'PLAIN' | 'LOGIN' | 'OAUTH2';
|
||||
};
|
||||
/**
|
||||
* Domain name for EHLO
|
||||
*/
|
||||
domain?: string;
|
||||
/**
|
||||
* DKIM options for signing outgoing emails
|
||||
*/
|
||||
dkim?: {
|
||||
/**
|
||||
* Whether to sign emails with DKIM
|
||||
*/
|
||||
enabled: boolean;
|
||||
/**
|
||||
* Domain name for DKIM
|
||||
*/
|
||||
domain: string;
|
||||
/**
|
||||
* Selector for DKIM
|
||||
*/
|
||||
selector: string;
|
||||
/**
|
||||
* Private key for DKIM signing
|
||||
*/
|
||||
privateKey: string;
|
||||
/**
|
||||
* Headers to sign
|
||||
*/
|
||||
headers?: string[];
|
||||
};
|
||||
};
|
||||
/**
|
||||
* SMTP delivery result
|
||||
*/
|
||||
export type ISmtpDeliveryResult = {
|
||||
/**
|
||||
* Whether the delivery was successful
|
||||
*/
|
||||
success: boolean;
|
||||
/**
|
||||
* Message ID if successful
|
||||
*/
|
||||
messageId?: string;
|
||||
/**
|
||||
* Error message if failed
|
||||
*/
|
||||
error?: string;
|
||||
/**
|
||||
* SMTP response code
|
||||
*/
|
||||
responseCode?: string;
|
||||
/**
|
||||
* Recipients successfully delivered to
|
||||
*/
|
||||
acceptedRecipients: string[];
|
||||
/**
|
||||
* Recipients rejected during delivery
|
||||
*/
|
||||
rejectedRecipients: string[];
|
||||
/**
|
||||
* Server response
|
||||
*/
|
||||
response?: string;
|
||||
/**
|
||||
* Timestamp of the delivery attempt
|
||||
*/
|
||||
timestamp: number;
|
||||
/**
|
||||
* Whether DKIM signing was applied
|
||||
*/
|
||||
dkimSigned?: boolean;
|
||||
/**
|
||||
* Whether this was a TLS secured delivery
|
||||
*/
|
||||
secure?: boolean;
|
||||
/**
|
||||
* Whether authentication was used
|
||||
*/
|
||||
authenticated?: boolean;
|
||||
};
|
||||
/**
|
||||
* SMTP client for sending emails to remote mail servers
|
||||
*/
|
||||
export declare class SmtpClient {
|
||||
private options;
|
||||
private connected;
|
||||
private socket?;
|
||||
private supportedExtensions;
|
||||
/**
|
||||
* Create a new SMTP client instance
|
||||
* @param options SMTP client connection options
|
||||
*/
|
||||
constructor(options: ISmtpClientOptions);
|
||||
/**
|
||||
* Connect to the SMTP server
|
||||
*/
|
||||
connect(): Promise<void>;
|
||||
/**
|
||||
* Send EHLO command to the server
|
||||
*/
|
||||
private sendEhlo;
|
||||
/**
|
||||
* Start TLS negotiation
|
||||
*/
|
||||
private startTls;
|
||||
/**
|
||||
* Upgrade socket to TLS
|
||||
* @param socket Original socket
|
||||
*/
|
||||
private upgradeTls;
|
||||
/**
|
||||
* Authenticate with the server
|
||||
*/
|
||||
private authenticate;
|
||||
/**
|
||||
* Authenticate using PLAIN method
|
||||
* @param user Username
|
||||
* @param pass Password
|
||||
*/
|
||||
private authPlain;
|
||||
/**
|
||||
* Authenticate using LOGIN method
|
||||
* @param user Username
|
||||
* @param pass Password
|
||||
*/
|
||||
private authLogin;
|
||||
/**
|
||||
* Authenticate using OAuth2 method
|
||||
* @param user Username
|
||||
* @param token OAuth2 token
|
||||
*/
|
||||
private authOAuth2;
|
||||
/**
|
||||
* Send an email through the SMTP client
|
||||
* @param email Email to send
|
||||
* @param processingMode Optional processing mode
|
||||
*/
|
||||
sendMail(email: Email, processingMode?: EmailProcessingMode): Promise<ISmtpDeliveryResult>;
|
||||
/**
|
||||
* Apply DKIM signature to email
|
||||
* @param email Email to sign
|
||||
*/
|
||||
private applyDkimSignature;
|
||||
/**
|
||||
* Format email for SMTP transmission
|
||||
* @param email Email to format
|
||||
*/
|
||||
private getFormattedEmail;
|
||||
/**
|
||||
* Get size of email in bytes
|
||||
* @param email Email to measure
|
||||
*/
|
||||
private getEmailSize;
|
||||
/**
|
||||
* Send SMTP command and wait for response
|
||||
* @param command SMTP command to send
|
||||
*/
|
||||
private commandQueue;
|
||||
private processingCommands;
|
||||
private supportsPipelining;
|
||||
/**
|
||||
* Send an SMTP command and wait for response
|
||||
* @param command SMTP command to send
|
||||
* @param allowPipelining Whether this command can be pipelined
|
||||
*/
|
||||
private sendCommand;
|
||||
/**
|
||||
* Process the command queue - either one by one or pipelined if supported
|
||||
*/
|
||||
private processCommandQueue;
|
||||
/**
|
||||
* Process the next command in the queue (non-pipelined mode)
|
||||
*/
|
||||
private processNextCommand;
|
||||
/**
|
||||
* Process responses for pipelined commands
|
||||
*/
|
||||
private processResponses;
|
||||
/**
|
||||
* Read response from the server
|
||||
*/
|
||||
private readResponse;
|
||||
/**
|
||||
* Check if the response is complete
|
||||
* @param response Response to check
|
||||
*/
|
||||
private isCompleteResponse;
|
||||
/**
|
||||
* Check if the response is an error
|
||||
* @param response Response to check
|
||||
*/
|
||||
private isErrorResponse;
|
||||
/**
|
||||
* Create appropriate error from response
|
||||
* @param response Error response
|
||||
* @param code SMTP status code
|
||||
*/
|
||||
private createErrorFromResponse;
|
||||
/**
|
||||
* Close the connection to the server
|
||||
*/
|
||||
close(): Promise<void>;
|
||||
/**
|
||||
* Checks if the connection is active
|
||||
*/
|
||||
isConnected(): boolean;
|
||||
/**
|
||||
* Update SMTP client options
|
||||
* @param options New options
|
||||
*/
|
||||
updateOptions(options: Partial<ISmtpClientOptions>): void;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,200 +0,0 @@
|
||||
import { EventEmitter } from 'node:events';
|
||||
/**
|
||||
* Interface for rate limit configuration
|
||||
*/
|
||||
export interface IRateLimitConfig {
|
||||
maxMessagesPerMinute?: number;
|
||||
maxRecipientsPerMessage?: number;
|
||||
maxConnectionsPerIP?: number;
|
||||
maxErrorsPerIP?: number;
|
||||
maxAuthFailuresPerIP?: number;
|
||||
blockDuration?: number;
|
||||
}
|
||||
/**
|
||||
* Interface for hierarchical rate limits
|
||||
*/
|
||||
export interface IHierarchicalRateLimits {
|
||||
global: IRateLimitConfig;
|
||||
patterns?: Record<string, IRateLimitConfig>;
|
||||
ips?: Record<string, IRateLimitConfig>;
|
||||
domains?: Record<string, IRateLimitConfig>;
|
||||
blocks?: Record<string, number>;
|
||||
}
|
||||
/**
|
||||
* Rate limiter statistics
|
||||
*/
|
||||
export interface IRateLimiterStats {
|
||||
activeCounters: number;
|
||||
totalBlocked: number;
|
||||
currentlyBlocked: number;
|
||||
byPattern: Record<string, {
|
||||
messagesPerMinute: number;
|
||||
totalMessages: number;
|
||||
totalBlocked: number;
|
||||
}>;
|
||||
byIp: Record<string, {
|
||||
messagesPerMinute: number;
|
||||
totalMessages: number;
|
||||
totalBlocked: number;
|
||||
connections: number;
|
||||
errors: number;
|
||||
authFailures: number;
|
||||
blocked: boolean;
|
||||
}>;
|
||||
}
|
||||
/**
|
||||
* Result of a rate limit check
|
||||
*/
|
||||
export interface IRateLimitResult {
|
||||
allowed: boolean;
|
||||
reason?: string;
|
||||
limit?: number;
|
||||
current?: number;
|
||||
resetIn?: number;
|
||||
}
|
||||
/**
|
||||
* Unified rate limiter for all email processing modes
|
||||
*/
|
||||
export declare class UnifiedRateLimiter extends EventEmitter {
|
||||
private config;
|
||||
private counters;
|
||||
private patternCounters;
|
||||
private ipCounters;
|
||||
private domainCounters;
|
||||
private cleanupInterval?;
|
||||
private stats;
|
||||
/**
|
||||
* Create a new unified rate limiter
|
||||
* @param config Rate limit configuration
|
||||
*/
|
||||
constructor(config: IHierarchicalRateLimits);
|
||||
/**
|
||||
* Start the cleanup interval
|
||||
*/
|
||||
private startCleanupInterval;
|
||||
/**
|
||||
* Stop the cleanup interval
|
||||
*/
|
||||
stop(): void;
|
||||
/**
|
||||
* Destroy the rate limiter and clean up all resources
|
||||
*/
|
||||
destroy(): void;
|
||||
/**
|
||||
* Clean up expired counters and blocks
|
||||
*/
|
||||
private cleanup;
|
||||
/**
|
||||
* Check if a message is allowed by rate limits
|
||||
* @param email Email address
|
||||
* @param ip IP address
|
||||
* @param recipients Number of recipients
|
||||
* @param pattern Matched pattern
|
||||
* @param domain Domain name for domain-specific limits
|
||||
* @returns Result of rate limit check
|
||||
*/
|
||||
checkMessageLimit(email: string, ip: string, recipients: number, pattern?: string, domain?: string): IRateLimitResult;
|
||||
/**
|
||||
* Check global message rate limit
|
||||
* @param email Email address
|
||||
*/
|
||||
private checkGlobalMessageLimit;
|
||||
/**
|
||||
* Check pattern-specific message rate limit
|
||||
* @param pattern Pattern to check
|
||||
*/
|
||||
private checkPatternMessageLimit;
|
||||
/**
|
||||
* Check domain-specific message rate limit
|
||||
* @param domain Domain to check
|
||||
*/
|
||||
private checkDomainMessageLimit;
|
||||
/**
|
||||
* Check IP-specific message rate limit
|
||||
* @param ip IP address
|
||||
*/
|
||||
private checkIpMessageLimit;
|
||||
/**
|
||||
* Check recipient limit
|
||||
* @param email Email address
|
||||
* @param recipients Number of recipients
|
||||
* @param pattern Matched pattern
|
||||
* @param domain Domain name
|
||||
*/
|
||||
private checkRecipientLimit;
|
||||
/**
|
||||
* Record a connection from an IP
|
||||
* @param ip IP address
|
||||
* @returns Result of rate limit check
|
||||
*/
|
||||
recordConnection(ip: string): IRateLimitResult;
|
||||
/**
|
||||
* Record an error from an IP
|
||||
* @param ip IP address
|
||||
* @returns True if IP should be blocked
|
||||
*/
|
||||
recordError(ip: string): boolean;
|
||||
/**
|
||||
* Record an authentication failure from an IP
|
||||
* @param ip IP address
|
||||
* @returns True if IP should be blocked
|
||||
*/
|
||||
recordAuthFailure(ip: string): boolean;
|
||||
/**
|
||||
* Block an IP address
|
||||
* @param ip IP address to block
|
||||
* @param duration Override the default block duration (milliseconds)
|
||||
*/
|
||||
blockIp(ip: string, duration?: number): void;
|
||||
/**
|
||||
* Unblock an IP address
|
||||
* @param ip IP address to unblock
|
||||
*/
|
||||
unblockIp(ip: string): void;
|
||||
/**
|
||||
* Check if an IP is blocked
|
||||
* @param ip IP address to check
|
||||
*/
|
||||
isIpBlocked(ip: string): boolean;
|
||||
/**
|
||||
* Get the time until a block is released
|
||||
* @param ip IP address
|
||||
* @returns Milliseconds until release or 0 if not blocked
|
||||
*/
|
||||
getBlockReleaseTime(ip: string): number;
|
||||
/**
|
||||
* Update rate limiter statistics
|
||||
*/
|
||||
private updateStats;
|
||||
/**
|
||||
* Get rate limiter statistics
|
||||
*/
|
||||
getStats(): IRateLimiterStats;
|
||||
/**
|
||||
* Update rate limiter configuration
|
||||
* @param config New configuration
|
||||
*/
|
||||
updateConfig(config: Partial<IHierarchicalRateLimits>): void;
|
||||
/**
|
||||
* Get configuration for debugging
|
||||
*/
|
||||
getConfig(): IHierarchicalRateLimits;
|
||||
/**
|
||||
* Apply domain-specific rate limits
|
||||
* Merges domain limits with existing configuration
|
||||
* @param domain Domain name
|
||||
* @param limits Rate limit configuration for the domain
|
||||
*/
|
||||
applyDomainLimits(domain: string, limits: IRateLimitConfig): void;
|
||||
/**
|
||||
* Remove domain-specific rate limits
|
||||
* @param domain Domain name
|
||||
*/
|
||||
removeDomainLimits(domain: string): void;
|
||||
/**
|
||||
* Get domain-specific rate limits
|
||||
* @param domain Domain name
|
||||
* @returns Domain rate limit config or undefined
|
||||
*/
|
||||
getDomainLimits(domain: string): IRateLimitConfig | undefined;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
12
dist_ts/mail/delivery/index.d.ts
vendored
12
dist_ts/mail/delivery/index.d.ts
vendored
@@ -1,12 +0,0 @@
|
||||
export * from './classes.emailsignjob.js';
|
||||
export * from './classes.delivery.queue.js';
|
||||
export * from './classes.delivery.system.js';
|
||||
export { EmailSendJob } from './classes.emailsendjob.js';
|
||||
export { DeliveryStatus } from './classes.delivery.system.js';
|
||||
export { RateLimiter } from './classes.ratelimiter.js';
|
||||
export type { IRateLimitConfig } from './classes.ratelimiter.js';
|
||||
export * from './classes.unified.rate.limiter.js';
|
||||
export * from './classes.mta.config.js';
|
||||
import * as smtpClientMod from './smtpclient/index.js';
|
||||
import * as smtpServerMod from './smtpserver/index.js';
|
||||
export { smtpClientMod, smtpServerMod };
|
||||
@@ -1,18 +0,0 @@
|
||||
// Email delivery components
|
||||
export * from './classes.emailsignjob.js';
|
||||
export * from './classes.delivery.queue.js';
|
||||
export * from './classes.delivery.system.js';
|
||||
// Handle exports with naming conflicts
|
||||
export { EmailSendJob } from './classes.emailsendjob.js';
|
||||
export { DeliveryStatus } from './classes.delivery.system.js';
|
||||
// Rate limiter exports - fix naming conflict
|
||||
export { RateLimiter } from './classes.ratelimiter.js';
|
||||
// Unified rate limiter
|
||||
export * from './classes.unified.rate.limiter.js';
|
||||
// SMTP client and configuration
|
||||
export * from './classes.mta.config.js';
|
||||
// Import and export SMTP modules as namespaces to avoid conflicts
|
||||
import * as smtpClientMod from './smtpclient/index.js';
|
||||
import * as smtpServerMod from './smtpserver/index.js';
|
||||
export { smtpClientMod, smtpServerMod };
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL2RlbGl2ZXJ5L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDRCQUE0QjtBQUM1QixjQUFjLDJCQUEyQixDQUFDO0FBQzFDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyw4QkFBOEIsQ0FBQztBQUU3Qyx1Q0FBdUM7QUFDdkMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUU5RCw2Q0FBNkM7QUFDN0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBR3ZELHVCQUF1QjtBQUN2QixjQUFjLG1DQUFtQyxDQUFDO0FBRWxELGdDQUFnQztBQUNoQyxjQUFjLHlCQUF5QixDQUFDO0FBRXhDLGtFQUFrRTtBQUNsRSxPQUFPLEtBQUssYUFBYSxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxhQUFhLE1BQU0sdUJBQXVCLENBQUM7QUFFdkQsT0FBTyxFQUFFLGFBQWEsRUFBRSxhQUFhLEVBQUUsQ0FBQyJ9
|
||||
243
dist_ts/mail/delivery/interfaces.d.ts
vendored
243
dist_ts/mail/delivery/interfaces.d.ts
vendored
@@ -1,243 +0,0 @@
|
||||
/**
|
||||
* SMTP and email delivery interface definitions
|
||||
*/
|
||||
import type { Email } from '../core/classes.email.js';
|
||||
/**
|
||||
* SMTP session state enumeration
|
||||
*/
|
||||
export declare enum SmtpState {
|
||||
GREETING = "GREETING",
|
||||
AFTER_EHLO = "AFTER_EHLO",
|
||||
MAIL_FROM = "MAIL_FROM",
|
||||
RCPT_TO = "RCPT_TO",
|
||||
DATA = "DATA",
|
||||
DATA_RECEIVING = "DATA_RECEIVING",
|
||||
FINISHED = "FINISHED"
|
||||
}
|
||||
/**
|
||||
* Email processing mode type
|
||||
*/
|
||||
export type EmailProcessingMode = 'forward' | 'mta' | 'process';
|
||||
/**
|
||||
* Envelope recipient information
|
||||
*/
|
||||
export interface IEnvelopeRecipient {
|
||||
/**
|
||||
* Email address of the recipient
|
||||
*/
|
||||
address: string;
|
||||
/**
|
||||
* Additional SMTP command arguments
|
||||
*/
|
||||
args: Record<string, string>;
|
||||
}
|
||||
/**
|
||||
* SMTP session envelope information
|
||||
*/
|
||||
export interface ISmtpEnvelope {
|
||||
/**
|
||||
* Envelope sender (MAIL FROM) information
|
||||
*/
|
||||
mailFrom: {
|
||||
/**
|
||||
* Email address of the sender
|
||||
*/
|
||||
address: string;
|
||||
/**
|
||||
* Additional SMTP command arguments
|
||||
*/
|
||||
args: Record<string, string>;
|
||||
};
|
||||
/**
|
||||
* Envelope recipients (RCPT TO) information
|
||||
*/
|
||||
rcptTo: IEnvelopeRecipient[];
|
||||
}
|
||||
/**
|
||||
* SMTP Session interface - represents an active SMTP connection
|
||||
*/
|
||||
export interface ISmtpSession {
|
||||
/**
|
||||
* Unique session identifier
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Current session state in the SMTP conversation
|
||||
*/
|
||||
state: SmtpState;
|
||||
/**
|
||||
* Hostname provided by the client in EHLO/HELO command
|
||||
*/
|
||||
clientHostname: string;
|
||||
/**
|
||||
* 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[];
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
secure: boolean;
|
||||
/**
|
||||
* Whether the client has been authenticated
|
||||
*/
|
||||
authenticated: boolean;
|
||||
/**
|
||||
* SMTP envelope information (structured format)
|
||||
*/
|
||||
envelope: ISmtpEnvelope;
|
||||
/**
|
||||
* Email processing mode to use for this session
|
||||
*/
|
||||
processingMode?: EmailProcessingMode;
|
||||
/**
|
||||
* Timestamp of last activity for session timeout tracking
|
||||
*/
|
||||
lastActivity?: number;
|
||||
/**
|
||||
* Timeout ID for DATA command timeout
|
||||
*/
|
||||
dataTimeoutId?: NodeJS.Timeout;
|
||||
}
|
||||
/**
|
||||
* SMTP authentication data
|
||||
*/
|
||||
export interface ISmtpAuth {
|
||||
/**
|
||||
* Authentication method used
|
||||
*/
|
||||
method: 'PLAIN' | 'LOGIN' | 'OAUTH2' | string;
|
||||
/**
|
||||
* Username for authentication
|
||||
*/
|
||||
username: string;
|
||||
/**
|
||||
* Password or token for authentication
|
||||
*/
|
||||
password: string;
|
||||
}
|
||||
/**
|
||||
* SMTP server options
|
||||
*/
|
||||
export interface ISmtpServerOptions {
|
||||
/**
|
||||
* Port to listen on
|
||||
*/
|
||||
port: number;
|
||||
/**
|
||||
* TLS private key (PEM format)
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* TLS certificate (PEM format)
|
||||
*/
|
||||
cert: string;
|
||||
/**
|
||||
* Server hostname for SMTP banner
|
||||
*/
|
||||
hostname?: string;
|
||||
/**
|
||||
* Host address to bind to (defaults to all interfaces)
|
||||
*/
|
||||
host?: string;
|
||||
/**
|
||||
* Secure port for dedicated TLS connections
|
||||
*/
|
||||
securePort?: number;
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* SMTP and email delivery interface definitions
|
||||
*/
|
||||
/**
|
||||
* SMTP session state enumeration
|
||||
*/
|
||||
export var SmtpState;
|
||||
(function (SmtpState) {
|
||||
SmtpState["GREETING"] = "GREETING";
|
||||
SmtpState["AFTER_EHLO"] = "AFTER_EHLO";
|
||||
SmtpState["MAIL_FROM"] = "MAIL_FROM";
|
||||
SmtpState["RCPT_TO"] = "RCPT_TO";
|
||||
SmtpState["DATA"] = "DATA";
|
||||
SmtpState["DATA_RECEIVING"] = "DATA_RECEIVING";
|
||||
SmtpState["FINISHED"] = "FINISHED";
|
||||
})(SmtpState || (SmtpState = {}));
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvaW50ZXJmYWNlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUlIOztHQUVHO0FBQ0gsTUFBTSxDQUFOLElBQVksU0FRWDtBQVJELFdBQVksU0FBUztJQUNuQixrQ0FBcUIsQ0FBQTtJQUNyQixzQ0FBeUIsQ0FBQTtJQUN6QixvQ0FBdUIsQ0FBQTtJQUN2QixnQ0FBbUIsQ0FBQTtJQUNuQiwwQkFBYSxDQUFBO0lBQ2IsOENBQWlDLENBQUE7SUFDakMsa0NBQXFCLENBQUE7QUFDdkIsQ0FBQyxFQVJXLFNBQVMsS0FBVCxTQUFTLFFBUXBCIn0=
|
||||
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Authentication Handler
|
||||
* Authentication mechanisms implementation
|
||||
*/
|
||||
import type { ISmtpConnection, ISmtpAuthOptions, ISmtpClientOptions } from './interfaces.js';
|
||||
import type { CommandHandler } from './command-handler.js';
|
||||
export declare class AuthHandler {
|
||||
private options;
|
||||
private commandHandler;
|
||||
constructor(options: ISmtpClientOptions, commandHandler: CommandHandler);
|
||||
/**
|
||||
* Authenticate using the configured method
|
||||
*/
|
||||
authenticate(connection: ISmtpConnection): Promise<void>;
|
||||
/**
|
||||
* Authenticate using AUTH PLAIN
|
||||
*/
|
||||
private authenticatePlain;
|
||||
/**
|
||||
* Authenticate using AUTH LOGIN
|
||||
*/
|
||||
private authenticateLogin;
|
||||
/**
|
||||
* Authenticate using OAuth2
|
||||
*/
|
||||
private authenticateOAuth2;
|
||||
/**
|
||||
* Select appropriate authentication method
|
||||
*/
|
||||
private selectAuthMethod;
|
||||
/**
|
||||
* Check if OAuth2 token is expired
|
||||
*/
|
||||
private isTokenExpired;
|
||||
/**
|
||||
* Refresh OAuth2 access token
|
||||
*/
|
||||
private refreshOAuth2Token;
|
||||
/**
|
||||
* Validate authentication configuration
|
||||
*/
|
||||
validateAuthConfig(auth: ISmtpAuthOptions): string[];
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Command Handler
|
||||
* SMTP command sending and response parsing
|
||||
*/
|
||||
import { EventEmitter } from 'node:events';
|
||||
import type { ISmtpConnection, ISmtpResponse, ISmtpClientOptions, ISmtpCapabilities } from './interfaces.js';
|
||||
export declare class CommandHandler extends EventEmitter {
|
||||
private options;
|
||||
private responseBuffer;
|
||||
private pendingCommand;
|
||||
private commandTimeout;
|
||||
constructor(options: ISmtpClientOptions);
|
||||
/**
|
||||
* Send EHLO command and parse capabilities
|
||||
*/
|
||||
sendEhlo(connection: ISmtpConnection, domain?: string): Promise<ISmtpCapabilities>;
|
||||
/**
|
||||
* Send MAIL FROM command
|
||||
*/
|
||||
sendMailFrom(connection: ISmtpConnection, fromAddress: string): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send RCPT TO command
|
||||
*/
|
||||
sendRcptTo(connection: ISmtpConnection, toAddress: string): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send DATA command
|
||||
*/
|
||||
sendData(connection: ISmtpConnection): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send email data content
|
||||
*/
|
||||
sendDataContent(connection: ISmtpConnection, emailData: string): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send RSET command
|
||||
*/
|
||||
sendRset(connection: ISmtpConnection): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send NOOP command
|
||||
*/
|
||||
sendNoop(connection: ISmtpConnection): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send QUIT command
|
||||
*/
|
||||
sendQuit(connection: ISmtpConnection): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send STARTTLS command
|
||||
*/
|
||||
sendStartTls(connection: ISmtpConnection): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send AUTH command
|
||||
*/
|
||||
sendAuth(connection: ISmtpConnection, method: string, credentials?: string): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send a generic SMTP command
|
||||
*/
|
||||
sendCommand(connection: ISmtpConnection, command: string): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Send raw data without command formatting
|
||||
*/
|
||||
sendRawData(connection: ISmtpConnection, data: string): Promise<ISmtpResponse>;
|
||||
/**
|
||||
* Wait for server greeting
|
||||
*/
|
||||
waitForGreeting(connection: ISmtpConnection): Promise<ISmtpResponse>;
|
||||
private handleIncomingData;
|
||||
private isCompleteResponse;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Connection Manager
|
||||
* Connection pooling and lifecycle management
|
||||
*/
|
||||
import { EventEmitter } from 'node:events';
|
||||
import type { ISmtpClientOptions, ISmtpConnection, IConnectionPoolStatus } from './interfaces.js';
|
||||
export declare class ConnectionManager extends EventEmitter {
|
||||
private options;
|
||||
private connections;
|
||||
private pendingConnections;
|
||||
private idleTimeout;
|
||||
constructor(options: ISmtpClientOptions);
|
||||
/**
|
||||
* Get or create a connection
|
||||
*/
|
||||
getConnection(): Promise<ISmtpConnection>;
|
||||
/**
|
||||
* Create a new connection
|
||||
*/
|
||||
createConnection(): Promise<ISmtpConnection>;
|
||||
/**
|
||||
* Release a connection back to the pool or close it
|
||||
*/
|
||||
releaseConnection(connection: ISmtpConnection): void;
|
||||
/**
|
||||
* Close a specific connection
|
||||
*/
|
||||
closeConnection(connection: ISmtpConnection): void;
|
||||
/**
|
||||
* Close all connections
|
||||
*/
|
||||
closeAllConnections(): void;
|
||||
/**
|
||||
* Get connection pool status
|
||||
*/
|
||||
getPoolStatus(): IConnectionPoolStatus;
|
||||
/**
|
||||
* Update connection activity timestamp
|
||||
*/
|
||||
updateActivity(connection: ISmtpConnection): void;
|
||||
private establishSocket;
|
||||
private setupSocketHandlers;
|
||||
private findIdleConnection;
|
||||
private shouldReuseConnection;
|
||||
private getActiveConnectionCount;
|
||||
private getConnectionId;
|
||||
private setupIdleCleanup;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
129
dist_ts/mail/delivery/smtpclient/constants.d.ts
vendored
129
dist_ts/mail/delivery/smtpclient/constants.d.ts
vendored
@@ -1,129 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Constants and Error Codes
|
||||
* All constants, error codes, and enums for SMTP client operations
|
||||
*/
|
||||
/**
|
||||
* SMTP response codes
|
||||
*/
|
||||
export declare const SMTP_CODES: {
|
||||
readonly SERVICE_READY: 220;
|
||||
readonly SERVICE_CLOSING: 221;
|
||||
readonly AUTHENTICATION_SUCCESSFUL: 235;
|
||||
readonly REQUESTED_ACTION_OK: 250;
|
||||
readonly USER_NOT_LOCAL: 251;
|
||||
readonly CANNOT_VERIFY_USER: 252;
|
||||
readonly START_MAIL_INPUT: 354;
|
||||
readonly SERVICE_NOT_AVAILABLE: 421;
|
||||
readonly MAILBOX_BUSY: 450;
|
||||
readonly LOCAL_ERROR: 451;
|
||||
readonly INSUFFICIENT_STORAGE: 452;
|
||||
readonly UNABLE_TO_ACCOMMODATE: 455;
|
||||
readonly SYNTAX_ERROR: 500;
|
||||
readonly SYNTAX_ERROR_PARAMETERS: 501;
|
||||
readonly COMMAND_NOT_IMPLEMENTED: 502;
|
||||
readonly BAD_SEQUENCE: 503;
|
||||
readonly PARAMETER_NOT_IMPLEMENTED: 504;
|
||||
readonly MAILBOX_UNAVAILABLE: 550;
|
||||
readonly USER_NOT_LOCAL_TRY_FORWARD: 551;
|
||||
readonly EXCEEDED_STORAGE: 552;
|
||||
readonly MAILBOX_NAME_NOT_ALLOWED: 553;
|
||||
readonly TRANSACTION_FAILED: 554;
|
||||
};
|
||||
/**
|
||||
* SMTP command names
|
||||
*/
|
||||
export declare const SMTP_COMMANDS: {
|
||||
readonly HELO: "HELO";
|
||||
readonly EHLO: "EHLO";
|
||||
readonly MAIL_FROM: "MAIL FROM";
|
||||
readonly RCPT_TO: "RCPT TO";
|
||||
readonly DATA: "DATA";
|
||||
readonly RSET: "RSET";
|
||||
readonly NOOP: "NOOP";
|
||||
readonly QUIT: "QUIT";
|
||||
readonly STARTTLS: "STARTTLS";
|
||||
readonly AUTH: "AUTH";
|
||||
};
|
||||
/**
|
||||
* Authentication methods
|
||||
*/
|
||||
export declare const AUTH_METHODS: {
|
||||
readonly PLAIN: "PLAIN";
|
||||
readonly LOGIN: "LOGIN";
|
||||
readonly OAUTH2: "XOAUTH2";
|
||||
readonly CRAM_MD5: "CRAM-MD5";
|
||||
};
|
||||
/**
|
||||
* Common SMTP extensions
|
||||
*/
|
||||
export declare const SMTP_EXTENSIONS: {
|
||||
readonly PIPELINING: "PIPELINING";
|
||||
readonly SIZE: "SIZE";
|
||||
readonly STARTTLS: "STARTTLS";
|
||||
readonly AUTH: "AUTH";
|
||||
readonly EIGHT_BIT_MIME: "8BITMIME";
|
||||
readonly CHUNKING: "CHUNKING";
|
||||
readonly ENHANCED_STATUS_CODES: "ENHANCEDSTATUSCODES";
|
||||
readonly DSN: "DSN";
|
||||
};
|
||||
/**
|
||||
* Default configuration values
|
||||
*/
|
||||
export declare const DEFAULTS: {
|
||||
readonly CONNECTION_TIMEOUT: 60000;
|
||||
readonly SOCKET_TIMEOUT: 300000;
|
||||
readonly COMMAND_TIMEOUT: 30000;
|
||||
readonly MAX_CONNECTIONS: 5;
|
||||
readonly MAX_MESSAGES: 100;
|
||||
readonly PORT_SMTP: 25;
|
||||
readonly PORT_SUBMISSION: 587;
|
||||
readonly PORT_SMTPS: 465;
|
||||
readonly RETRY_ATTEMPTS: 3;
|
||||
readonly RETRY_DELAY: 1000;
|
||||
readonly POOL_IDLE_TIMEOUT: 30000;
|
||||
};
|
||||
/**
|
||||
* Error types for classification
|
||||
*/
|
||||
export declare enum SmtpErrorType {
|
||||
CONNECTION_ERROR = "CONNECTION_ERROR",
|
||||
AUTHENTICATION_ERROR = "AUTHENTICATION_ERROR",
|
||||
PROTOCOL_ERROR = "PROTOCOL_ERROR",
|
||||
TIMEOUT_ERROR = "TIMEOUT_ERROR",
|
||||
TLS_ERROR = "TLS_ERROR",
|
||||
SYNTAX_ERROR = "SYNTAX_ERROR",
|
||||
MAILBOX_ERROR = "MAILBOX_ERROR",
|
||||
QUOTA_ERROR = "QUOTA_ERROR",
|
||||
UNKNOWN_ERROR = "UNKNOWN_ERROR"
|
||||
}
|
||||
/**
|
||||
* Regular expressions for parsing
|
||||
*/
|
||||
export declare const REGEX_PATTERNS: {
|
||||
readonly EMAIL_ADDRESS: RegExp;
|
||||
readonly RESPONSE_CODE: RegExp;
|
||||
readonly ENHANCED_STATUS: RegExp;
|
||||
readonly AUTH_CAPABILITIES: RegExp;
|
||||
readonly SIZE_EXTENSION: RegExp;
|
||||
};
|
||||
/**
|
||||
* Line endings and separators
|
||||
*/
|
||||
export declare const LINE_ENDINGS: {
|
||||
readonly CRLF: "\r\n";
|
||||
readonly LF: "\n";
|
||||
readonly CR: "\r";
|
||||
};
|
||||
/**
|
||||
* Connection states for internal use
|
||||
*/
|
||||
export declare const CONNECTION_STATES: {
|
||||
readonly DISCONNECTED: "disconnected";
|
||||
readonly CONNECTING: "connecting";
|
||||
readonly CONNECTED: "connected";
|
||||
readonly AUTHENTICATED: "authenticated";
|
||||
readonly READY: "ready";
|
||||
readonly BUSY: "busy";
|
||||
readonly CLOSING: "closing";
|
||||
readonly ERROR: "error";
|
||||
};
|
||||
@@ -1,135 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Constants and Error Codes
|
||||
* All constants, error codes, and enums for SMTP client operations
|
||||
*/
|
||||
/**
|
||||
* SMTP response codes
|
||||
*/
|
||||
export const SMTP_CODES = {
|
||||
// Positive completion replies
|
||||
SERVICE_READY: 220,
|
||||
SERVICE_CLOSING: 221,
|
||||
AUTHENTICATION_SUCCESSFUL: 235,
|
||||
REQUESTED_ACTION_OK: 250,
|
||||
USER_NOT_LOCAL: 251,
|
||||
CANNOT_VERIFY_USER: 252,
|
||||
// Positive intermediate replies
|
||||
START_MAIL_INPUT: 354,
|
||||
// Transient negative completion replies
|
||||
SERVICE_NOT_AVAILABLE: 421,
|
||||
MAILBOX_BUSY: 450,
|
||||
LOCAL_ERROR: 451,
|
||||
INSUFFICIENT_STORAGE: 452,
|
||||
UNABLE_TO_ACCOMMODATE: 455,
|
||||
// Permanent negative completion replies
|
||||
SYNTAX_ERROR: 500,
|
||||
SYNTAX_ERROR_PARAMETERS: 501,
|
||||
COMMAND_NOT_IMPLEMENTED: 502,
|
||||
BAD_SEQUENCE: 503,
|
||||
PARAMETER_NOT_IMPLEMENTED: 504,
|
||||
MAILBOX_UNAVAILABLE: 550,
|
||||
USER_NOT_LOCAL_TRY_FORWARD: 551,
|
||||
EXCEEDED_STORAGE: 552,
|
||||
MAILBOX_NAME_NOT_ALLOWED: 553,
|
||||
TRANSACTION_FAILED: 554
|
||||
};
|
||||
/**
|
||||
* SMTP command names
|
||||
*/
|
||||
export const SMTP_COMMANDS = {
|
||||
HELO: 'HELO',
|
||||
EHLO: 'EHLO',
|
||||
MAIL_FROM: 'MAIL FROM',
|
||||
RCPT_TO: 'RCPT TO',
|
||||
DATA: 'DATA',
|
||||
RSET: 'RSET',
|
||||
NOOP: 'NOOP',
|
||||
QUIT: 'QUIT',
|
||||
STARTTLS: 'STARTTLS',
|
||||
AUTH: 'AUTH'
|
||||
};
|
||||
/**
|
||||
* Authentication methods
|
||||
*/
|
||||
export const AUTH_METHODS = {
|
||||
PLAIN: 'PLAIN',
|
||||
LOGIN: 'LOGIN',
|
||||
OAUTH2: 'XOAUTH2',
|
||||
CRAM_MD5: 'CRAM-MD5'
|
||||
};
|
||||
/**
|
||||
* Common SMTP extensions
|
||||
*/
|
||||
export const SMTP_EXTENSIONS = {
|
||||
PIPELINING: 'PIPELINING',
|
||||
SIZE: 'SIZE',
|
||||
STARTTLS: 'STARTTLS',
|
||||
AUTH: 'AUTH',
|
||||
EIGHT_BIT_MIME: '8BITMIME',
|
||||
CHUNKING: 'CHUNKING',
|
||||
ENHANCED_STATUS_CODES: 'ENHANCEDSTATUSCODES',
|
||||
DSN: 'DSN'
|
||||
};
|
||||
/**
|
||||
* Default configuration values
|
||||
*/
|
||||
export const DEFAULTS = {
|
||||
CONNECTION_TIMEOUT: 60000, // 60 seconds
|
||||
SOCKET_TIMEOUT: 300000, // 5 minutes
|
||||
COMMAND_TIMEOUT: 30000, // 30 seconds
|
||||
MAX_CONNECTIONS: 5,
|
||||
MAX_MESSAGES: 100,
|
||||
PORT_SMTP: 25,
|
||||
PORT_SUBMISSION: 587,
|
||||
PORT_SMTPS: 465,
|
||||
RETRY_ATTEMPTS: 3,
|
||||
RETRY_DELAY: 1000,
|
||||
POOL_IDLE_TIMEOUT: 30000 // 30 seconds
|
||||
};
|
||||
/**
|
||||
* Error types for classification
|
||||
*/
|
||||
export var SmtpErrorType;
|
||||
(function (SmtpErrorType) {
|
||||
SmtpErrorType["CONNECTION_ERROR"] = "CONNECTION_ERROR";
|
||||
SmtpErrorType["AUTHENTICATION_ERROR"] = "AUTHENTICATION_ERROR";
|
||||
SmtpErrorType["PROTOCOL_ERROR"] = "PROTOCOL_ERROR";
|
||||
SmtpErrorType["TIMEOUT_ERROR"] = "TIMEOUT_ERROR";
|
||||
SmtpErrorType["TLS_ERROR"] = "TLS_ERROR";
|
||||
SmtpErrorType["SYNTAX_ERROR"] = "SYNTAX_ERROR";
|
||||
SmtpErrorType["MAILBOX_ERROR"] = "MAILBOX_ERROR";
|
||||
SmtpErrorType["QUOTA_ERROR"] = "QUOTA_ERROR";
|
||||
SmtpErrorType["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
|
||||
})(SmtpErrorType || (SmtpErrorType = {}));
|
||||
/**
|
||||
* Regular expressions for parsing
|
||||
*/
|
||||
export const REGEX_PATTERNS = {
|
||||
EMAIL_ADDRESS: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
||||
RESPONSE_CODE: /^(\d{3})([ -])(.*)/,
|
||||
ENHANCED_STATUS: /^(\d\.\d\.\d)\s/,
|
||||
AUTH_CAPABILITIES: /AUTH\s+(.+)/i,
|
||||
SIZE_EXTENSION: /SIZE\s+(\d+)/i
|
||||
};
|
||||
/**
|
||||
* Line endings and separators
|
||||
*/
|
||||
export const LINE_ENDINGS = {
|
||||
CRLF: '\r\n',
|
||||
LF: '\n',
|
||||
CR: '\r'
|
||||
};
|
||||
/**
|
||||
* Connection states for internal use
|
||||
*/
|
||||
export const CONNECTION_STATES = {
|
||||
DISCONNECTED: 'disconnected',
|
||||
CONNECTING: 'connecting',
|
||||
CONNECTED: 'connected',
|
||||
AUTHENTICATED: 'authenticated',
|
||||
READY: 'ready',
|
||||
BUSY: 'busy',
|
||||
CLOSING: 'closing',
|
||||
ERROR: 'error'
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvbWFpbC9kZWxpdmVyeS9zbXRwY2xpZW50L2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSDs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRztJQUN4Qiw4QkFBOEI7SUFDOUIsYUFBYSxFQUFFLEdBQUc7SUFDbEIsZUFBZSxFQUFFLEdBQUc7SUFDcEIseUJBQXlCLEVBQUUsR0FBRztJQUM5QixtQkFBbUIsRUFBRSxHQUFHO0lBQ3hCLGNBQWMsRUFBRSxHQUFHO0lBQ25CLGtCQUFrQixFQUFFLEdBQUc7SUFFdkIsZ0NBQWdDO0lBQ2hDLGdCQUFnQixFQUFFLEdBQUc7SUFFckIsd0NBQXdDO0lBQ3hDLHFCQUFxQixFQUFFLEdBQUc7SUFDMUIsWUFBWSxFQUFFLEdBQUc7SUFDakIsV0FBVyxFQUFFLEdBQUc7SUFDaEIsb0JBQW9CLEVBQUUsR0FBRztJQUN6QixxQkFBcUIsRUFBRSxHQUFHO0lBRTFCLHdDQUF3QztJQUN4QyxZQUFZLEVBQUUsR0FBRztJQUNqQix1QkFBdUIsRUFBRSxHQUFHO0lBQzVCLHVCQUF1QixFQUFFLEdBQUc7SUFDNUIsWUFBWSxFQUFFLEdBQUc7SUFDakIseUJBQXlCLEVBQUUsR0FBRztJQUM5QixtQkFBbUIsRUFBRSxHQUFHO0lBQ3hCLDBCQUEwQixFQUFFLEdBQUc7SUFDL0IsZ0JBQWdCLEVBQUUsR0FBRztJQUNyQix3QkFBd0IsRUFBRSxHQUFHO0lBQzdCLGtCQUFrQixFQUFFLEdBQUc7Q0FDZixDQUFDO0FBRVg7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUc7SUFDM0IsSUFBSSxFQUFFLE1BQU07SUFDWixJQUFJLEVBQUUsTUFBTTtJQUNaLFNBQVMsRUFBRSxXQUFXO0lBQ3RCLE9BQU8sRUFBRSxTQUFTO0lBQ2xCLElBQUksRUFBRSxNQUFNO0lBQ1osSUFB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
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Factory
|
||||
* Factory function for client creation and dependency injection
|
||||
*/
|
||||
import { SmtpClient } from './smtp-client.js';
|
||||
import type { ISmtpClientOptions } from './interfaces.js';
|
||||
/**
|
||||
* Create a complete SMTP client with all components
|
||||
*/
|
||||
export declare function createSmtpClient(options: ISmtpClientOptions): SmtpClient;
|
||||
/**
|
||||
* Create SMTP client with connection pooling enabled
|
||||
*/
|
||||
export declare function createPooledSmtpClient(options: ISmtpClientOptions): SmtpClient;
|
||||
/**
|
||||
* Create SMTP client for high-volume sending
|
||||
*/
|
||||
export declare function createBulkSmtpClient(options: ISmtpClientOptions): SmtpClient;
|
||||
/**
|
||||
* Create SMTP client for transactional emails
|
||||
*/
|
||||
export declare function createTransactionalSmtpClient(options: ISmtpClientOptions): SmtpClient;
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Factory
|
||||
* Factory function for client creation and dependency injection
|
||||
*/
|
||||
import { SmtpClient } from './smtp-client.js';
|
||||
import { ConnectionManager } from './connection-manager.js';
|
||||
import { CommandHandler } from './command-handler.js';
|
||||
import { AuthHandler } from './auth-handler.js';
|
||||
import { TlsHandler } from './tls-handler.js';
|
||||
import { SmtpErrorHandler } from './error-handler.js';
|
||||
import { validateClientOptions } from './utils/validation.js';
|
||||
import { DEFAULTS } from './constants.js';
|
||||
/**
|
||||
* Create a complete SMTP client with all components
|
||||
*/
|
||||
export function createSmtpClient(options) {
|
||||
// Validate options
|
||||
const errors = validateClientOptions(options);
|
||||
if (errors.length > 0) {
|
||||
throw new Error(`Invalid client options: ${errors.join(', ')}`);
|
||||
}
|
||||
// Apply defaults
|
||||
const clientOptions = {
|
||||
connectionTimeout: DEFAULTS.CONNECTION_TIMEOUT,
|
||||
socketTimeout: DEFAULTS.SOCKET_TIMEOUT,
|
||||
maxConnections: DEFAULTS.MAX_CONNECTIONS,
|
||||
maxMessages: DEFAULTS.MAX_MESSAGES,
|
||||
pool: false,
|
||||
secure: false,
|
||||
debug: false,
|
||||
...options
|
||||
};
|
||||
// Create handlers
|
||||
const errorHandler = new SmtpErrorHandler(clientOptions);
|
||||
const connectionManager = new ConnectionManager(clientOptions);
|
||||
const commandHandler = new CommandHandler(clientOptions);
|
||||
const authHandler = new AuthHandler(clientOptions, commandHandler);
|
||||
const tlsHandler = new TlsHandler(clientOptions, commandHandler);
|
||||
// Create and return SMTP client
|
||||
return new SmtpClient({
|
||||
options: clientOptions,
|
||||
connectionManager,
|
||||
commandHandler,
|
||||
authHandler,
|
||||
tlsHandler,
|
||||
errorHandler
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Create SMTP client with connection pooling enabled
|
||||
*/
|
||||
export function createPooledSmtpClient(options) {
|
||||
return createSmtpClient({
|
||||
...options,
|
||||
pool: true,
|
||||
maxConnections: options.maxConnections || DEFAULTS.MAX_CONNECTIONS,
|
||||
maxMessages: options.maxMessages || DEFAULTS.MAX_MESSAGES
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Create SMTP client for high-volume sending
|
||||
*/
|
||||
export function createBulkSmtpClient(options) {
|
||||
return createSmtpClient({
|
||||
...options,
|
||||
pool: true,
|
||||
maxConnections: Math.max(options.maxConnections || 10, 10),
|
||||
maxMessages: Math.max(options.maxMessages || 1000, 1000),
|
||||
connectionTimeout: options.connectionTimeout || 30000,
|
||||
socketTimeout: options.socketTimeout || 120000
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Create SMTP client for transactional emails
|
||||
*/
|
||||
export function createTransactionalSmtpClient(options) {
|
||||
return createSmtpClient({
|
||||
...options,
|
||||
pool: false, // Use fresh connections for transactional emails
|
||||
maxConnections: 1,
|
||||
maxMessages: 1,
|
||||
connectionTimeout: options.connectionTimeout || 10000,
|
||||
socketTimeout: options.socketTimeout || 30000
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvc210cGNsaWVudC9jcmVhdGUtY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUV0RCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFMUM7O0dBRUc7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsT0FBMkI7SUFDMUQsbUJBQW1CO0lBQ25CLE1BQU0sTUFBTSxHQUFHLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzlDLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBRUQsaUJBQWlCO0lBQ2pCLE1BQU0sYUFBYSxHQUF1QjtRQUN4QyxpQkFBaUIsRUFBRSxRQUFRLENBQUMsa0JBQWtCO1FBQzlDLGFBQWEsRUFBRSxRQUFRLENBQUMsY0FBYztRQUN0QyxjQUFjLEVBQUUsUUFBUSxDQUFDLGVBQWU7UUFDeEMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxZQUFZO1FBQ2xDLElBQUksRUFBRSxLQUFLO1FBQ1gsTUFBTSxFQUFFLEtBQUs7UUFDYixLQUFLLEVBQUUsS0FBSztRQUNaLEdBQUcsT0FBTztLQUNYLENBQUM7SUFFRixrQkFBa0I7SUFDbEIsTUFBTSxZQUFZLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUN6RCxNQUFNLGlCQUFpQixHQUFHLElBQUksaUJBQWlCLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDL0QsTUFBTSxjQUFjLEdBQUcsSUFBSSxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDekQsTUFBTSxXQUFXLEdBQUcsSUFBSSxXQUFXLENBQUMsYUFBYSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ25FLE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDLGFBQWEsRUFBRSxjQUFjLENBQUMsQ0FBQztJQUVqRSxnQ0FBZ0M7SUFDaEMsT0FBTyxJQUFJLFVBQVUsQ0FBQztRQUNwQixPQUFPLEVBQUUsYUFBYTtRQUN0QixpQkFBaUI7UUFDakIsY0FBYztRQUNkLFdBQVc7UUFDWCxVQUFVO1FBQ1YsWUFBWTtLQUNiLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFBVSxzQkFBc0IsQ0FBQyxPQUEyQjtJQUNoRSxPQUFPLGdCQUFnQixDQUFDO1FBQ3RCLEdBQUcsT0FBTztRQUNWLElBQUksRUFBRSxJQUFJO1FBQ1YsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjLElBQUksUUFBUSxDQUFDLGVBQWU7UUFDbEUsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXLElBQUksUUFBUSxDQUFDLFlBQVk7S0FDMUQsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLE9BQTJCO0lBQzlELE9BQU8sZ0JBQWdCLENBQUM7UUFDdEIsR0FBRyxPQUFPO1FBQ1YsSUFBSSxFQUFFLElBQUk7UUFDVixjQUFjLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsY0FBYyxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUM7UUFDMUQsV0FBVyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFdBQVcsSUFBSSxJQUFJLEVBQUUsSUFBSSxDQUFDO1FBQ3hELGlCQUFpQixFQUFFLE9BQU8sQ0FBQyxpQkFBaUIsSUFBSSxLQUFLO1FBQ3JELGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxJQUFJLE1BQU07S0FDL0MsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLDZCQUE2QixDQUFDLE9BQTJCO0lBQ3ZFLE9BQU8sZ0JBQWdCLENBQUM7UUFDdEIsR0FBRyxPQUFPO1FBQ1YsSUFBSSxFQUFFLEtBQUssRUFBRSxpREFBaUQ7UUFDOUQsY0FBYyxFQUFFLENBQUM7UUFDakIsV0FBVyxFQUFFLENBQUM7UUFDZCxpQkFBaUIsRUFBRSxPQUFPLENBQUMsaUJBQWlCLElBQUksS0FBSztRQUNyRCxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsSUFBSSxLQUFLO0tBQzlDLENBQUMsQ0FBQztBQUNMLENBQUMifQ==
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Error Handler
|
||||
* Error classification and recovery strategies
|
||||
*/
|
||||
import { SmtpErrorType } from './constants.js';
|
||||
import type { ISmtpResponse, ISmtpErrorContext, ISmtpClientOptions } from './interfaces.js';
|
||||
export declare class SmtpErrorHandler {
|
||||
private options;
|
||||
constructor(options: ISmtpClientOptions);
|
||||
/**
|
||||
* Classify error type based on response or error
|
||||
*/
|
||||
classifyError(error: Error | ISmtpResponse, context?: ISmtpErrorContext): SmtpErrorType;
|
||||
/**
|
||||
* Determine if error is retryable
|
||||
*/
|
||||
isRetryable(errorType: SmtpErrorType, response?: ISmtpResponse): boolean;
|
||||
/**
|
||||
* Get retry delay for error type
|
||||
*/
|
||||
getRetryDelay(attempt: number, errorType: SmtpErrorType): number;
|
||||
/**
|
||||
* Create enhanced error with context
|
||||
*/
|
||||
createError(message: string, errorType: SmtpErrorType, context?: ISmtpErrorContext, originalError?: Error): Error;
|
||||
private classifyErrorByMessage;
|
||||
private classifyErrorByCode;
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Error Handler
|
||||
* Error classification and recovery strategies
|
||||
*/
|
||||
import { SmtpErrorType } from './constants.js';
|
||||
import { logDebug } from './utils/logging.js';
|
||||
export class SmtpErrorHandler {
|
||||
options;
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
}
|
||||
/**
|
||||
* Classify error type based on response or error
|
||||
*/
|
||||
classifyError(error, context) {
|
||||
logDebug('Classifying error', this.options, { errorMessage: error instanceof Error ? error.message : String(error), context });
|
||||
// Handle Error objects
|
||||
if (error instanceof Error) {
|
||||
return this.classifyErrorByMessage(error);
|
||||
}
|
||||
// Handle SMTP response codes
|
||||
if (typeof error === 'object' && 'code' in error) {
|
||||
return this.classifyErrorByCode(error.code);
|
||||
}
|
||||
return SmtpErrorType.UNKNOWN_ERROR;
|
||||
}
|
||||
/**
|
||||
* Determine if error is retryable
|
||||
*/
|
||||
isRetryable(errorType, response) {
|
||||
switch (errorType) {
|
||||
case SmtpErrorType.CONNECTION_ERROR:
|
||||
case SmtpErrorType.TIMEOUT_ERROR:
|
||||
return true;
|
||||
case SmtpErrorType.PROTOCOL_ERROR:
|
||||
// Only retry on temporary failures (4xx codes)
|
||||
return response ? response.code >= 400 && response.code < 500 : false;
|
||||
case SmtpErrorType.AUTHENTICATION_ERROR:
|
||||
case SmtpErrorType.TLS_ERROR:
|
||||
case SmtpErrorType.SYNTAX_ERROR:
|
||||
case SmtpErrorType.MAILBOX_ERROR:
|
||||
case SmtpErrorType.QUOTA_ERROR:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get retry delay for error type
|
||||
*/
|
||||
getRetryDelay(attempt, errorType) {
|
||||
const baseDelay = 1000; // 1 second
|
||||
const maxDelay = 30000; // 30 seconds
|
||||
// Exponential backoff with jitter
|
||||
const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
||||
const jitter = Math.random() * 0.1 * delay; // 10% jitter
|
||||
return Math.floor(delay + jitter);
|
||||
}
|
||||
/**
|
||||
* Create enhanced error with context
|
||||
*/
|
||||
createError(message, errorType, context, originalError) {
|
||||
const error = new Error(message);
|
||||
error.type = errorType;
|
||||
error.context = context;
|
||||
error.originalError = originalError;
|
||||
return error;
|
||||
}
|
||||
classifyErrorByMessage(error) {
|
||||
const message = error.message.toLowerCase();
|
||||
if (message.includes('timeout') || message.includes('etimedout')) {
|
||||
return SmtpErrorType.TIMEOUT_ERROR;
|
||||
}
|
||||
if (message.includes('connect') || message.includes('econnrefused') ||
|
||||
message.includes('enotfound') || message.includes('enetunreach')) {
|
||||
return SmtpErrorType.CONNECTION_ERROR;
|
||||
}
|
||||
if (message.includes('tls') || message.includes('ssl') ||
|
||||
message.includes('certificate') || message.includes('handshake')) {
|
||||
return SmtpErrorType.TLS_ERROR;
|
||||
}
|
||||
if (message.includes('auth')) {
|
||||
return SmtpErrorType.AUTHENTICATION_ERROR;
|
||||
}
|
||||
return SmtpErrorType.UNKNOWN_ERROR;
|
||||
}
|
||||
classifyErrorByCode(code) {
|
||||
if (code >= 500) {
|
||||
// Permanent failures
|
||||
if (code === 550 || code === 551 || code === 553) {
|
||||
return SmtpErrorType.MAILBOX_ERROR;
|
||||
}
|
||||
if (code === 552) {
|
||||
return SmtpErrorType.QUOTA_ERROR;
|
||||
}
|
||||
if (code === 500 || code === 501 || code === 502 || code === 504) {
|
||||
return SmtpErrorType.SYNTAX_ERROR;
|
||||
}
|
||||
return SmtpErrorType.PROTOCOL_ERROR;
|
||||
}
|
||||
if (code >= 400) {
|
||||
// Temporary failures
|
||||
if (code === 450 || code === 451 || code === 452) {
|
||||
return SmtpErrorType.QUOTA_ERROR;
|
||||
}
|
||||
return SmtpErrorType.PROTOCOL_ERROR;
|
||||
}
|
||||
return SmtpErrorType.UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3ItaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvc210cGNsaWVudC9lcnJvci1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUvQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFOUMsTUFBTSxPQUFPLGdCQUFnQjtJQUNuQixPQUFPLENBQXFCO0lBRXBDLFlBQVksT0FBMkI7UUFDckMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksYUFBYSxDQUFDLEtBQTRCLEVBQUUsT0FBMkI7UUFDNUUsUUFBUSxDQUFDLG1CQUFtQixFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxZQUFZLEVBQUUsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFFL0gsdUJBQXVCO1FBQ3ZCLElBQUksS0FBSyxZQUFZLEtBQUssRUFBRSxDQUFDO1lBQzNCLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVDLENBQUM7UUFFRCw2QkFBNkI7UUFDN0IsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksTUFBTSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ2pELE9BQU8sSUFBSSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBRUQsT0FBTyxhQUFhLENBQUMsYUFBYSxDQUFDO0lBQ3JDLENBQUM7SUFFRDs7T0FFRztJQUNJLFdBQVcsQ0FBQyxTQUF3QixFQUFFLFFBQXdCO1FBQ25F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
|
||||
16
dist_ts/mail/delivery/smtpclient/index.d.ts
vendored
16
dist_ts/mail/delivery/smtpclient/index.d.ts
vendored
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Module Exports
|
||||
* Modular SMTP client implementation for robust email delivery
|
||||
*/
|
||||
export * from './smtp-client.js';
|
||||
export * from './create-client.js';
|
||||
export * from './connection-manager.js';
|
||||
export * from './command-handler.js';
|
||||
export * from './auth-handler.js';
|
||||
export * from './tls-handler.js';
|
||||
export * from './error-handler.js';
|
||||
export * from './interfaces.js';
|
||||
export * from './constants.js';
|
||||
export * from './utils/validation.js';
|
||||
export * from './utils/logging.js';
|
||||
export * from './utils/helpers.js';
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Module Exports
|
||||
* Modular SMTP client implementation for robust email delivery
|
||||
*/
|
||||
// Main client class and factory
|
||||
export * from './smtp-client.js';
|
||||
export * from './create-client.js';
|
||||
// Core handlers
|
||||
export * from './connection-manager.js';
|
||||
export * from './command-handler.js';
|
||||
export * from './auth-handler.js';
|
||||
export * from './tls-handler.js';
|
||||
export * from './error-handler.js';
|
||||
// Interfaces and types
|
||||
export * from './interfaces.js';
|
||||
export * from './constants.js';
|
||||
// Utilities
|
||||
export * from './utils/validation.js';
|
||||
export * from './utils/logging.js';
|
||||
export * from './utils/helpers.js';
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9tYWlsL2RlbGl2ZXJ5L3NtdHBjbGllbnQvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsZ0NBQWdDO0FBQ2hDLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxvQkFBb0IsQ0FBQztBQUVuQyxnQkFBZ0I7QUFDaEIsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLG9CQUFvQixDQUFDO0FBRW5DLHVCQUF1QjtBQUN2QixjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsZ0JBQWdCLENBQUM7QUFFL0IsWUFBWTtBQUNaLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxjQUFjLG9CQUFvQixDQUFDIn0=
|
||||
183
dist_ts/mail/delivery/smtpclient/interfaces.d.ts
vendored
183
dist_ts/mail/delivery/smtpclient/interfaces.d.ts
vendored
@@ -1,183 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Interfaces and Types
|
||||
* All interface definitions for the modular SMTP client
|
||||
*/
|
||||
import type * as tls from 'node:tls';
|
||||
import type * as net from 'node:net';
|
||||
/**
|
||||
* SMTP client connection options
|
||||
*/
|
||||
export interface ISmtpClientOptions {
|
||||
/** Hostname of the SMTP server */
|
||||
host: string;
|
||||
/** Port to connect to */
|
||||
port: number;
|
||||
/** Whether to use TLS for the connection */
|
||||
secure?: boolean;
|
||||
/** Connection timeout in milliseconds */
|
||||
connectionTimeout?: number;
|
||||
/** Socket timeout in milliseconds */
|
||||
socketTimeout?: number;
|
||||
/** Domain name for EHLO command */
|
||||
domain?: string;
|
||||
/** Authentication options */
|
||||
auth?: ISmtpAuthOptions;
|
||||
/** TLS options */
|
||||
tls?: tls.ConnectionOptions;
|
||||
/** Maximum number of connections in pool */
|
||||
pool?: boolean;
|
||||
maxConnections?: number;
|
||||
maxMessages?: number;
|
||||
/** Enable debug logging */
|
||||
debug?: boolean;
|
||||
/** Proxy settings */
|
||||
proxy?: string;
|
||||
}
|
||||
/**
|
||||
* Authentication options for SMTP
|
||||
*/
|
||||
export interface ISmtpAuthOptions {
|
||||
/** Username */
|
||||
user?: string;
|
||||
/** Password */
|
||||
pass?: string;
|
||||
/** OAuth2 settings */
|
||||
oauth2?: IOAuth2Options;
|
||||
/** Authentication method preference */
|
||||
method?: 'PLAIN' | 'LOGIN' | 'OAUTH2' | 'AUTO';
|
||||
}
|
||||
/**
|
||||
* OAuth2 authentication options
|
||||
*/
|
||||
export interface IOAuth2Options {
|
||||
/** OAuth2 user identifier */
|
||||
user: string;
|
||||
/** OAuth2 client ID */
|
||||
clientId: string;
|
||||
/** OAuth2 client secret */
|
||||
clientSecret: string;
|
||||
/** OAuth2 refresh token */
|
||||
refreshToken: string;
|
||||
/** OAuth2 access token */
|
||||
accessToken?: string;
|
||||
/** Token expiry time */
|
||||
expires?: number;
|
||||
}
|
||||
/**
|
||||
* Result of an email send operation
|
||||
*/
|
||||
export interface ISmtpSendResult {
|
||||
/** Whether the send was successful */
|
||||
success: boolean;
|
||||
/** Message ID from server */
|
||||
messageId?: string;
|
||||
/** List of accepted recipients */
|
||||
acceptedRecipients: string[];
|
||||
/** List of rejected recipients */
|
||||
rejectedRecipients: string[];
|
||||
/** Error information if failed */
|
||||
error?: Error;
|
||||
/** Server response */
|
||||
response?: string;
|
||||
/** Envelope information */
|
||||
envelope?: ISmtpEnvelope;
|
||||
}
|
||||
/**
|
||||
* SMTP envelope information
|
||||
*/
|
||||
export interface ISmtpEnvelope {
|
||||
/** Sender address */
|
||||
from: string;
|
||||
/** Recipient addresses */
|
||||
to: string[];
|
||||
}
|
||||
/**
|
||||
* Connection pool status
|
||||
*/
|
||||
export interface IConnectionPoolStatus {
|
||||
/** Total connections in pool */
|
||||
total: number;
|
||||
/** Active connections */
|
||||
active: number;
|
||||
/** Idle connections */
|
||||
idle: number;
|
||||
/** Pending connection requests */
|
||||
pending: number;
|
||||
}
|
||||
/**
|
||||
* SMTP command response
|
||||
*/
|
||||
export interface ISmtpResponse {
|
||||
/** Response code */
|
||||
code: number;
|
||||
/** Response message */
|
||||
message: string;
|
||||
/** Enhanced status code */
|
||||
enhancedCode?: string;
|
||||
/** Raw response */
|
||||
raw: string;
|
||||
}
|
||||
/**
|
||||
* Connection state
|
||||
*/
|
||||
export declare enum ConnectionState {
|
||||
DISCONNECTED = "disconnected",
|
||||
CONNECTING = "connecting",
|
||||
CONNECTED = "connected",
|
||||
AUTHENTICATED = "authenticated",
|
||||
READY = "ready",
|
||||
BUSY = "busy",
|
||||
CLOSING = "closing",
|
||||
ERROR = "error"
|
||||
}
|
||||
/**
|
||||
* SMTP capabilities
|
||||
*/
|
||||
export interface ISmtpCapabilities {
|
||||
/** Supported extensions */
|
||||
extensions: Set<string>;
|
||||
/** Maximum message size */
|
||||
maxSize?: number;
|
||||
/** Supported authentication methods */
|
||||
authMethods: Set<string>;
|
||||
/** Support for pipelining */
|
||||
pipelining: boolean;
|
||||
/** Support for STARTTLS */
|
||||
starttls: boolean;
|
||||
/** Support for 8BITMIME */
|
||||
eightBitMime: boolean;
|
||||
}
|
||||
/**
|
||||
* Internal connection interface
|
||||
*/
|
||||
export interface ISmtpConnection {
|
||||
/** Socket connection */
|
||||
socket: net.Socket | tls.TLSSocket;
|
||||
/** Connection state */
|
||||
state: ConnectionState;
|
||||
/** Server capabilities */
|
||||
capabilities?: ISmtpCapabilities;
|
||||
/** Connection options */
|
||||
options: ISmtpClientOptions;
|
||||
/** Whether connection is secure */
|
||||
secure: boolean;
|
||||
/** Connection creation time */
|
||||
createdAt: Date;
|
||||
/** Last activity time */
|
||||
lastActivity: Date;
|
||||
/** Number of messages sent */
|
||||
messageCount: number;
|
||||
}
|
||||
/**
|
||||
* Error context for detailed error reporting
|
||||
*/
|
||||
export interface ISmtpErrorContext {
|
||||
/** Command that caused the error */
|
||||
command?: string;
|
||||
/** Server response */
|
||||
response?: ISmtpResponse;
|
||||
/** Connection state */
|
||||
connectionState?: ConnectionState;
|
||||
/** Additional context data */
|
||||
data?: Record<string, any>;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Interfaces and Types
|
||||
* All interface definitions for the modular SMTP client
|
||||
*/
|
||||
/**
|
||||
* Connection state
|
||||
*/
|
||||
export var ConnectionState;
|
||||
(function (ConnectionState) {
|
||||
ConnectionState["DISCONNECTED"] = "disconnected";
|
||||
ConnectionState["CONNECTING"] = "connecting";
|
||||
ConnectionState["CONNECTED"] = "connected";
|
||||
ConnectionState["AUTHENTICATED"] = "authenticated";
|
||||
ConnectionState["READY"] = "ready";
|
||||
ConnectionState["BUSY"] = "busy";
|
||||
ConnectionState["CLOSING"] = "closing";
|
||||
ConnectionState["ERROR"] = "error";
|
||||
})(ConnectionState || (ConnectionState = {}));
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvc210cGNsaWVudC9pbnRlcmZhY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQTZKSDs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLGVBU1g7QUFURCxXQUFZLGVBQWU7SUFDekIsZ0RBQTZCLENBQUE7SUFDN0IsNENBQXlCLENBQUE7SUFDekIsMENBQXVCLENBQUE7SUFDdkIsa0RBQStCLENBQUE7SUFDL0Isa0NBQWUsQ0FBQTtJQUNmLGdDQUFhLENBQUE7SUFDYixzQ0FBbUIsQ0FBQTtJQUNuQixrQ0FBZSxDQUFBO0FBQ2pCLENBQUMsRUFUVyxlQUFlLEtBQWYsZUFBZSxRQVMxQiJ9
|
||||
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Core Implementation
|
||||
* Main client class with delegation to handlers
|
||||
*/
|
||||
import { EventEmitter } from 'node:events';
|
||||
import type { Email } from '../../core/classes.email.js';
|
||||
import type { ISmtpClientOptions, ISmtpSendResult, IConnectionPoolStatus } from './interfaces.js';
|
||||
import type { ConnectionManager } from './connection-manager.js';
|
||||
import type { CommandHandler } from './command-handler.js';
|
||||
import type { AuthHandler } from './auth-handler.js';
|
||||
import type { TlsHandler } from './tls-handler.js';
|
||||
import type { SmtpErrorHandler } from './error-handler.js';
|
||||
interface ISmtpClientDependencies {
|
||||
options: ISmtpClientOptions;
|
||||
connectionManager: ConnectionManager;
|
||||
commandHandler: CommandHandler;
|
||||
authHandler: AuthHandler;
|
||||
tlsHandler: TlsHandler;
|
||||
errorHandler: SmtpErrorHandler;
|
||||
}
|
||||
export declare class SmtpClient extends EventEmitter {
|
||||
private options;
|
||||
private connectionManager;
|
||||
private commandHandler;
|
||||
private authHandler;
|
||||
private tlsHandler;
|
||||
private errorHandler;
|
||||
private isShuttingDown;
|
||||
constructor(dependencies: ISmtpClientDependencies);
|
||||
/**
|
||||
* Send an email
|
||||
*/
|
||||
sendMail(email: Email): Promise<ISmtpSendResult>;
|
||||
/**
|
||||
* Test connection to SMTP server
|
||||
*/
|
||||
verify(): Promise<boolean>;
|
||||
/**
|
||||
* Check if client is connected
|
||||
*/
|
||||
isConnected(): boolean;
|
||||
/**
|
||||
* Get connection pool status
|
||||
*/
|
||||
getPoolStatus(): IConnectionPoolStatus;
|
||||
/**
|
||||
* Update client options
|
||||
*/
|
||||
updateOptions(newOptions: Partial<ISmtpClientOptions>): void;
|
||||
/**
|
||||
* Close all connections and shutdown client
|
||||
*/
|
||||
close(): Promise<void>;
|
||||
private formatEmailData;
|
||||
private extractMessageId;
|
||||
private setupEventForwarding;
|
||||
}
|
||||
export {};
|
||||
File diff suppressed because one or more lines are too long
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* SMTP Client TLS Handler
|
||||
* TLS and STARTTLS client functionality
|
||||
*/
|
||||
import * as tls from 'node:tls';
|
||||
import type { ISmtpConnection, ISmtpClientOptions } from './interfaces.js';
|
||||
import type { CommandHandler } from './command-handler.js';
|
||||
export declare class TlsHandler {
|
||||
private options;
|
||||
private commandHandler;
|
||||
constructor(options: ISmtpClientOptions, commandHandler: CommandHandler);
|
||||
/**
|
||||
* Upgrade connection to TLS using STARTTLS
|
||||
*/
|
||||
upgradeToTLS(connection: ISmtpConnection): Promise<void>;
|
||||
/**
|
||||
* Create a direct TLS connection
|
||||
*/
|
||||
createTLSConnection(host: string, port: number): Promise<tls.TLSSocket>;
|
||||
/**
|
||||
* Validate TLS certificate
|
||||
*/
|
||||
validateCertificate(socket: tls.TLSSocket): boolean;
|
||||
/**
|
||||
* Get TLS connection information
|
||||
*/
|
||||
getTLSInfo(socket: tls.TLSSocket): any;
|
||||
/**
|
||||
* Check if TLS upgrade is required or recommended
|
||||
*/
|
||||
shouldUseTLS(connection: ISmtpConnection): boolean;
|
||||
private performTLSUpgrade;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Helper Functions
|
||||
* Protocol helper functions and utilities
|
||||
*/
|
||||
import type { ISmtpResponse, ISmtpCapabilities } from '../interfaces.js';
|
||||
/**
|
||||
* Parse SMTP server response
|
||||
*/
|
||||
export declare function parseSmtpResponse(data: string): ISmtpResponse;
|
||||
/**
|
||||
* Parse EHLO response and extract capabilities
|
||||
*/
|
||||
export declare function parseEhloResponse(response: string): ISmtpCapabilities;
|
||||
/**
|
||||
* Format SMTP command with proper line ending
|
||||
*/
|
||||
export declare function formatCommand(command: string, ...args: string[]): string;
|
||||
/**
|
||||
* Encode authentication string for AUTH PLAIN
|
||||
*/
|
||||
export declare function encodeAuthPlain(username: string, password: string): string;
|
||||
/**
|
||||
* Encode authentication string for AUTH LOGIN
|
||||
*/
|
||||
export declare function encodeAuthLogin(value: string): string;
|
||||
/**
|
||||
* Generate OAuth2 authentication string
|
||||
*/
|
||||
export declare function generateOAuth2String(username: string, accessToken: string): string;
|
||||
/**
|
||||
* Check if response code indicates success
|
||||
*/
|
||||
export declare function isSuccessCode(code: number): boolean;
|
||||
/**
|
||||
* Check if response code indicates temporary failure
|
||||
*/
|
||||
export declare function isTemporaryFailure(code: number): boolean;
|
||||
/**
|
||||
* Check if response code indicates permanent failure
|
||||
*/
|
||||
export declare function isPermanentFailure(code: number): boolean;
|
||||
/**
|
||||
* Escape email address for SMTP commands
|
||||
*/
|
||||
export declare function escapeEmailAddress(email: string): string;
|
||||
/**
|
||||
* Extract email address from angle brackets
|
||||
*/
|
||||
export declare function extractEmailAddress(email: string): string;
|
||||
/**
|
||||
* Generate unique connection ID
|
||||
*/
|
||||
export declare function generateConnectionId(): string;
|
||||
/**
|
||||
* Format timeout duration for human readability
|
||||
*/
|
||||
export declare function formatTimeout(milliseconds: number): string;
|
||||
/**
|
||||
* Validate and normalize email data size
|
||||
*/
|
||||
export declare function validateEmailSize(emailData: string, maxSize?: number): boolean;
|
||||
/**
|
||||
* Clean sensitive data from logs
|
||||
*/
|
||||
export declare function sanitizeForLogging(data: any): any;
|
||||
/**
|
||||
* Calculate exponential backoff delay
|
||||
*/
|
||||
export declare function calculateBackoffDelay(attempt: number, baseDelay?: number): number;
|
||||
/**
|
||||
* Parse enhanced status code
|
||||
*/
|
||||
export declare function parseEnhancedStatusCode(code: string): {
|
||||
class: number;
|
||||
subject: number;
|
||||
detail: number;
|
||||
} | null;
|
||||
File diff suppressed because one or more lines are too long
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Logging Utilities
|
||||
* Client-side logging utilities for SMTP operations
|
||||
*/
|
||||
import type { ISmtpResponse, ISmtpClientOptions } from '../interfaces.js';
|
||||
export interface ISmtpClientLogData {
|
||||
component: string;
|
||||
host?: string;
|
||||
port?: number;
|
||||
secure?: boolean;
|
||||
command?: string;
|
||||
response?: ISmtpResponse;
|
||||
error?: Error;
|
||||
connectionId?: string;
|
||||
messageId?: string;
|
||||
duration?: number;
|
||||
[key: string]: any;
|
||||
}
|
||||
/**
|
||||
* Log SMTP client connection events
|
||||
*/
|
||||
export declare function logConnection(event: 'connecting' | 'connected' | 'disconnected' | 'error', options: ISmtpClientOptions, data?: Partial<ISmtpClientLogData>): void;
|
||||
/**
|
||||
* Log SMTP command execution
|
||||
*/
|
||||
export declare function logCommand(command: string, response?: ISmtpResponse, options?: ISmtpClientOptions, data?: Partial<ISmtpClientLogData>): void;
|
||||
/**
|
||||
* Log authentication events
|
||||
*/
|
||||
export declare function logAuthentication(event: 'start' | 'success' | 'failure', method: string, options: ISmtpClientOptions, data?: Partial<ISmtpClientLogData>): void;
|
||||
/**
|
||||
* Log TLS/STARTTLS events
|
||||
*/
|
||||
export declare function logTLS(event: 'starttls_start' | 'starttls_success' | 'starttls_failure' | 'tls_connected', options: ISmtpClientOptions, data?: Partial<ISmtpClientLogData>): void;
|
||||
/**
|
||||
* Log email sending events
|
||||
*/
|
||||
export declare function logEmailSend(event: 'start' | 'success' | 'failure', recipients: string[], options: ISmtpClientOptions, data?: Partial<ISmtpClientLogData>): void;
|
||||
/**
|
||||
* Log performance metrics
|
||||
*/
|
||||
export declare function logPerformance(operation: string, duration: number, options: ISmtpClientOptions, data?: Partial<ISmtpClientLogData>): void;
|
||||
/**
|
||||
* Log debug information (only when debug is enabled)
|
||||
*/
|
||||
export declare function logDebug(message: string, options: ISmtpClientOptions, data?: Partial<ISmtpClientLogData>): void;
|
||||
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Logging Utilities
|
||||
* Client-side logging utilities for SMTP operations
|
||||
*/
|
||||
import { logger } from '../../../../logger.js';
|
||||
/**
|
||||
* Log SMTP client connection events
|
||||
*/
|
||||
export function logConnection(event, options, data) {
|
||||
const logData = {
|
||||
component: 'smtp-client',
|
||||
event,
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
secure: options.secure,
|
||||
...data
|
||||
};
|
||||
switch (event) {
|
||||
case 'connecting':
|
||||
logger.info('SMTP client connecting', logData);
|
||||
break;
|
||||
case 'connected':
|
||||
logger.info('SMTP client connected', logData);
|
||||
break;
|
||||
case 'disconnected':
|
||||
logger.info('SMTP client disconnected', logData);
|
||||
break;
|
||||
case 'error':
|
||||
logger.error('SMTP client connection error', logData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Log SMTP command execution
|
||||
*/
|
||||
export function logCommand(command, response, options, data) {
|
||||
const logData = {
|
||||
component: 'smtp-client',
|
||||
command,
|
||||
response,
|
||||
host: options?.host,
|
||||
port: options?.port,
|
||||
...data
|
||||
};
|
||||
if (response && response.code >= 400) {
|
||||
logger.warn('SMTP command failed', logData);
|
||||
}
|
||||
else {
|
||||
logger.debug('SMTP command executed', logData);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Log authentication events
|
||||
*/
|
||||
export function logAuthentication(event, method, options, data) {
|
||||
const logData = {
|
||||
component: 'smtp-client',
|
||||
event: `auth_${event}`,
|
||||
authMethod: method,
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
...data
|
||||
};
|
||||
switch (event) {
|
||||
case 'start':
|
||||
logger.debug('SMTP authentication started', logData);
|
||||
break;
|
||||
case 'success':
|
||||
logger.info('SMTP authentication successful', logData);
|
||||
break;
|
||||
case 'failure':
|
||||
logger.error('SMTP authentication failed', logData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Log TLS/STARTTLS events
|
||||
*/
|
||||
export function logTLS(event, options, data) {
|
||||
const logData = {
|
||||
component: 'smtp-client',
|
||||
event,
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
...data
|
||||
};
|
||||
if (event.includes('failure')) {
|
||||
logger.error('SMTP TLS operation failed', logData);
|
||||
}
|
||||
else {
|
||||
logger.info('SMTP TLS operation', logData);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Log email sending events
|
||||
*/
|
||||
export function logEmailSend(event, recipients, options, data) {
|
||||
const logData = {
|
||||
component: 'smtp-client',
|
||||
event: `send_${event}`,
|
||||
recipientCount: recipients.length,
|
||||
recipients: recipients.slice(0, 5), // Only log first 5 recipients for privacy
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
...data
|
||||
};
|
||||
switch (event) {
|
||||
case 'start':
|
||||
logger.info('SMTP email send started', logData);
|
||||
break;
|
||||
case 'success':
|
||||
logger.info('SMTP email send successful', logData);
|
||||
break;
|
||||
case 'failure':
|
||||
logger.error('SMTP email send failed', logData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Log performance metrics
|
||||
*/
|
||||
export function logPerformance(operation, duration, options, data) {
|
||||
const logData = {
|
||||
component: 'smtp-client',
|
||||
operation,
|
||||
duration,
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
...data
|
||||
};
|
||||
if (duration > 10000) { // Log slow operations (>10s)
|
||||
logger.warn('SMTP slow operation detected', logData);
|
||||
}
|
||||
else {
|
||||
logger.debug('SMTP operation performance', logData);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Log debug information (only when debug is enabled)
|
||||
*/
|
||||
export function logDebug(message, options, data) {
|
||||
if (!options.debug) {
|
||||
return;
|
||||
}
|
||||
const logData = {
|
||||
component: 'smtp-client-debug',
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
...data
|
||||
};
|
||||
logger.debug(`[SMTP Client Debug] ${message}`, logData);
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvc210cGNsaWVudC91dGlscy9sb2dnaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQWlCL0M7O0dBRUc7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUMzQixLQUE0RCxFQUM1RCxPQUEyQixFQUMzQixJQUFrQztJQUVsQyxNQUFNLE9BQU8sR0FBdUI7UUFDbEMsU0FBUyxFQUFFLGFBQWE7UUFDeEIsS0FBSztRQUNMLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtRQUNsQixJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7UUFDbEIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1FBQ3RCLEdBQUcsSUFBSTtLQUNSLENBQUM7SUFFRixRQUFRLEtBQUssRUFBRSxDQUFDO1FBQ2QsS0FBSyxZQUFZO1lBQ2YsTUFBTSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUMvQyxNQUFNO1FBQ1IsS0FBSyxXQUFXO1lBQ2QsTUFBTSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM5QyxNQUFNO1FBQ1IsS0FBSyxjQUFjO1lBQ2pCLE1BQU0sQ0FBQyxJQUFJLENBQUMsMEJBQTBCLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDakQsTUFBTTtRQUNSLEtBQUssT0FBTztZQUNWLE1BQU0sQ0FBQyxLQUFLLENBQUMsOEJBQThCLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDdEQsTUFBTTtJQUNWLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUN4QixPQUFlLEVBQ2YsUUFBd0IsRUFDeEIsT0FBNEIsRUFDNUIsSUFBa0M7SUFFbEMsTUFBTSxPQUFPLEdBQXVCO1FB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
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* SMTP Client Validation Utilities
|
||||
* Input validation functions for SMTP client operations
|
||||
*/
|
||||
import type { ISmtpClientOptions, ISmtpAuthOptions } from '../interfaces.js';
|
||||
/**
|
||||
* Validate email address format
|
||||
* Supports RFC-compliant addresses including empty return paths for bounces
|
||||
*/
|
||||
export declare function validateEmailAddress(email: string): boolean;
|
||||
/**
|
||||
* Validate SMTP client options
|
||||
*/
|
||||
export declare function validateClientOptions(options: ISmtpClientOptions): string[];
|
||||
/**
|
||||
* Validate authentication options
|
||||
*/
|
||||
export declare function validateAuthOptions(auth: ISmtpAuthOptions): string[];
|
||||
/**
|
||||
* Validate hostname format
|
||||
*/
|
||||
export declare function validateHostname(hostname: string): boolean;
|
||||
/**
|
||||
* Validate port number
|
||||
*/
|
||||
export declare function validatePort(port: number): boolean;
|
||||
/**
|
||||
* Sanitize and validate domain name for EHLO
|
||||
*/
|
||||
export declare function validateAndSanitizeDomain(domain: string): string;
|
||||
/**
|
||||
* Validate recipient list
|
||||
*/
|
||||
export declare function validateRecipients(recipients: string | string[]): string[];
|
||||
/**
|
||||
* Validate sender address
|
||||
*/
|
||||
export declare function validateSender(sender: string): boolean;
|
||||
File diff suppressed because one or more lines are too long
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* Certificate Utilities for SMTP Server
|
||||
* Provides utilities for managing TLS certificates
|
||||
*/
|
||||
import * as tls from 'tls';
|
||||
/**
|
||||
* Certificate data
|
||||
*/
|
||||
export interface ICertificateData {
|
||||
key: Buffer;
|
||||
cert: Buffer;
|
||||
ca?: Buffer;
|
||||
}
|
||||
/**
|
||||
* Load certificates from PEM format strings
|
||||
* @param options - Certificate options
|
||||
* @returns Certificate data with Buffer format
|
||||
*/
|
||||
export declare function loadCertificatesFromString(options: {
|
||||
key: string | Buffer;
|
||||
cert: string | Buffer;
|
||||
ca?: string | Buffer;
|
||||
}): ICertificateData;
|
||||
/**
|
||||
* Load certificates from files
|
||||
* @param options - Certificate file paths
|
||||
* @returns Certificate data with Buffer format
|
||||
*/
|
||||
export declare function loadCertificatesFromFiles(options: {
|
||||
keyPath: string;
|
||||
certPath: string;
|
||||
caPath?: string;
|
||||
}): ICertificateData;
|
||||
/**
|
||||
* Generate self-signed certificates for testing
|
||||
* @returns Certificate data with Buffer format
|
||||
*/
|
||||
export declare function generateSelfSignedCertificates(): ICertificateData;
|
||||
/**
|
||||
* Create TLS options for secure server or STARTTLS
|
||||
* @param certificates - Certificate data
|
||||
* @param isServer - Whether this is for server (true) or client (false)
|
||||
* @returns TLS options
|
||||
*/
|
||||
export declare function createTlsOptions(certificates: ICertificateData, isServer?: boolean): tls.TlsOptions;
|
||||
File diff suppressed because one or more lines are too long
@@ -1,156 +0,0 @@
|
||||
/**
|
||||
* SMTP Command Handler
|
||||
* Responsible for parsing and handling SMTP commands
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import type { ISmtpSession } from './interfaces.js';
|
||||
import type { ICommandHandler, ISmtpServer } from './interfaces.js';
|
||||
import { SmtpCommand } from './constants.js';
|
||||
/**
|
||||
* Handles SMTP commands and responses
|
||||
*/
|
||||
export declare class CommandHandler implements ICommandHandler {
|
||||
/**
|
||||
* Reference to the SMTP server instance
|
||||
*/
|
||||
private smtpServer;
|
||||
/**
|
||||
* Creates a new command handler
|
||||
* @param smtpServer - SMTP server instance
|
||||
*/
|
||||
constructor(smtpServer: ISmtpServer);
|
||||
/**
|
||||
* Process a command from the client
|
||||
* @param socket - Client socket
|
||||
* @param commandLine - Command line from client
|
||||
*/
|
||||
processCommand(socket: plugins.net.Socket | plugins.tls.TLSSocket, commandLine: string): Promise<void>;
|
||||
/**
|
||||
* Send a response to the client
|
||||
* @param socket - Client socket
|
||||
* @param response - Response to send
|
||||
*/
|
||||
sendResponse(socket: plugins.net.Socket | plugins.tls.TLSSocket, response: string): void;
|
||||
/**
|
||||
* Check if a socket error is potentially recoverable
|
||||
* @param error - The error that occurred
|
||||
* @returns Whether the error is potentially recoverable
|
||||
*/
|
||||
private isRecoverableSocketError;
|
||||
/**
|
||||
* Handle recoverable socket errors with retry logic
|
||||
* @param socket - Client socket
|
||||
* @param error - The error that occurred
|
||||
* @param response - The response that failed to send
|
||||
*/
|
||||
private handleSocketError;
|
||||
/**
|
||||
* Handle EHLO command
|
||||
* @param socket - Client socket
|
||||
* @param clientHostname - Client hostname from EHLO command
|
||||
*/
|
||||
handleEhlo(socket: plugins.net.Socket | plugins.tls.TLSSocket, clientHostname: string): void;
|
||||
/**
|
||||
* Handle MAIL FROM command
|
||||
* @param socket - Client socket
|
||||
* @param args - Command arguments
|
||||
*/
|
||||
handleMailFrom(socket: plugins.net.Socket | plugins.tls.TLSSocket, args: string): void;
|
||||
/**
|
||||
* Handle RCPT TO command
|
||||
* @param socket - Client socket
|
||||
* @param args - Command arguments
|
||||
*/
|
||||
handleRcptTo(socket: plugins.net.Socket | plugins.tls.TLSSocket, args: string): void;
|
||||
/**
|
||||
* Handle DATA command
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
handleData(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
|
||||
/**
|
||||
* Handle RSET command
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
handleRset(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
|
||||
/**
|
||||
* Handle NOOP command
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
handleNoop(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
|
||||
/**
|
||||
* Handle QUIT command
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
handleQuit(socket: plugins.net.Socket | plugins.tls.TLSSocket, args?: string): void;
|
||||
/**
|
||||
* Handle AUTH command
|
||||
* @param socket - Client socket
|
||||
* @param args - Command arguments
|
||||
*/
|
||||
private handleAuth;
|
||||
/**
|
||||
* Handle AUTH PLAIN authentication
|
||||
* @param socket - Client socket
|
||||
* @param session - Session
|
||||
* @param initialResponse - Optional initial response
|
||||
*/
|
||||
private handleAuthPlain;
|
||||
/**
|
||||
* Handle AUTH LOGIN authentication
|
||||
* @param socket - Client socket
|
||||
* @param session - Session
|
||||
* @param initialResponse - Optional initial response
|
||||
*/
|
||||
private handleAuthLogin;
|
||||
/**
|
||||
* Handle AUTH LOGIN response
|
||||
* @param socket - Client socket
|
||||
* @param session - Session
|
||||
* @param response - Response from client
|
||||
*/
|
||||
private handleAuthLoginResponse;
|
||||
/**
|
||||
* Handle HELP command
|
||||
* @param socket - Client socket
|
||||
* @param args - Command arguments
|
||||
*/
|
||||
private handleHelp;
|
||||
/**
|
||||
* Handle VRFY command (Verify user/mailbox)
|
||||
* RFC 5321 Section 3.5.1: Server MAY respond with 252 to avoid disclosing sensitive information
|
||||
* @param socket - Client socket
|
||||
* @param args - Command arguments (username to verify)
|
||||
*/
|
||||
private handleVrfy;
|
||||
/**
|
||||
* Handle EXPN command (Expand mailing list)
|
||||
* RFC 5321 Section 3.5.2: Server MAY disable this for security
|
||||
* @param socket - Client socket
|
||||
* @param args - Command arguments (mailing list to expand)
|
||||
*/
|
||||
private handleExpn;
|
||||
/**
|
||||
* Reset session to after-EHLO state
|
||||
* @param session - SMTP session to reset
|
||||
*/
|
||||
private resetSession;
|
||||
/**
|
||||
* Validate command sequence based on current state
|
||||
* @param command - Command to validate
|
||||
* @param session - Current session
|
||||
* @returns Whether the command is valid in the current state
|
||||
*/
|
||||
private validateCommandSequence;
|
||||
/**
|
||||
* Handle an SMTP command (interface requirement)
|
||||
*/
|
||||
handleCommand(socket: plugins.net.Socket | plugins.tls.TLSSocket, command: SmtpCommand, args: string, session: ISmtpSession): Promise<void>;
|
||||
/**
|
||||
* Get supported commands for current session state (interface requirement)
|
||||
*/
|
||||
getSupportedCommands(session: ISmtpSession): SmtpCommand[];
|
||||
/**
|
||||
* Clean up resources
|
||||
*/
|
||||
destroy(): void;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,159 +0,0 @@
|
||||
/**
|
||||
* SMTP Connection Manager
|
||||
* Responsible for managing socket connections to the SMTP server
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import type { IConnectionManager, ISmtpServer } from './interfaces.js';
|
||||
/**
|
||||
* Manager for SMTP connections
|
||||
* Handles connection setup, event listeners, and lifecycle management
|
||||
* Provides resource management, connection tracking, and monitoring
|
||||
*/
|
||||
export declare class ConnectionManager implements IConnectionManager {
|
||||
/**
|
||||
* Reference to the SMTP server instance
|
||||
*/
|
||||
private smtpServer;
|
||||
/**
|
||||
* Set of active socket connections
|
||||
*/
|
||||
private activeConnections;
|
||||
/**
|
||||
* Connection tracking for resource management
|
||||
*/
|
||||
private connectionStats;
|
||||
/**
|
||||
* Per-IP connection tracking for rate limiting
|
||||
*/
|
||||
private ipConnections;
|
||||
/**
|
||||
* Resource monitoring interval
|
||||
*/
|
||||
private resourceCheckInterval;
|
||||
/**
|
||||
* Track cleanup timers so we can clear them
|
||||
*/
|
||||
private cleanupTimers;
|
||||
/**
|
||||
* SMTP server options with enhanced resource controls
|
||||
*/
|
||||
private options;
|
||||
/**
|
||||
* Creates a new connection manager with enhanced resource management
|
||||
* @param smtpServer - SMTP server instance
|
||||
*/
|
||||
constructor(smtpServer: ISmtpServer);
|
||||
/**
|
||||
* Start resource monitoring interval to check resource usage
|
||||
*/
|
||||
private startResourceMonitoring;
|
||||
/**
|
||||
* Monitor resource usage and log statistics
|
||||
*/
|
||||
private monitorResourceUsage;
|
||||
/**
|
||||
* Clean up expired IP rate limits and perform additional resource monitoring
|
||||
*/
|
||||
private cleanupIpRateLimits;
|
||||
/**
|
||||
* Validate and repair resource tracking to prevent leaks
|
||||
*/
|
||||
private validateResourceTracking;
|
||||
/**
|
||||
* Handle a new connection with resource management
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
handleNewConnection(socket: plugins.net.Socket): Promise<void>;
|
||||
/**
|
||||
* Check if an IP has exceeded the rate limit
|
||||
* @param ip - Client IP address
|
||||
* @returns True if rate limited
|
||||
*/
|
||||
private isIPRateLimited;
|
||||
/**
|
||||
* Track a new connection from an IP
|
||||
* @param ip - Client IP address
|
||||
*/
|
||||
private trackIPConnection;
|
||||
/**
|
||||
* Check if an IP has reached its connection limit
|
||||
* @param ip - Client IP address
|
||||
* @returns True if limit reached
|
||||
*/
|
||||
private hasReachedIPConnectionLimit;
|
||||
/**
|
||||
* Handle a new secure TLS connection with resource management
|
||||
* @param socket - Client TLS socket
|
||||
*/
|
||||
handleNewSecureConnection(socket: plugins.tls.TLSSocket): Promise<void>;
|
||||
/**
|
||||
* Set up event handlers for a socket with enhanced resource management
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
setupSocketEventHandlers(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
|
||||
/**
|
||||
* Get the current connection count
|
||||
* @returns Number of active connections
|
||||
*/
|
||||
getConnectionCount(): number;
|
||||
/**
|
||||
* Check if the server has reached the maximum number of connections
|
||||
* @returns True if max connections reached
|
||||
*/
|
||||
hasReachedMaxConnections(): boolean;
|
||||
/**
|
||||
* Close all active connections
|
||||
*/
|
||||
closeAllConnections(): void;
|
||||
/**
|
||||
* Handle socket close event
|
||||
* @param socket - Client socket
|
||||
* @param hadError - Whether the socket was closed due to error
|
||||
*/
|
||||
private handleSocketClose;
|
||||
/**
|
||||
* Handle socket error event
|
||||
* @param socket - Client socket
|
||||
* @param error - Error object
|
||||
*/
|
||||
private handleSocketError;
|
||||
/**
|
||||
* Handle socket timeout event
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
private handleSocketTimeout;
|
||||
/**
|
||||
* Reject a connection
|
||||
* @param socket - Client socket
|
||||
* @param reason - Reason for rejection
|
||||
*/
|
||||
private rejectConnection;
|
||||
/**
|
||||
* Send greeting message
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
private sendGreeting;
|
||||
/**
|
||||
* Send service closing notification
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
private sendServiceClosing;
|
||||
/**
|
||||
* Send response to client
|
||||
* @param socket - Client socket
|
||||
* @param response - Response to send
|
||||
*/
|
||||
private sendResponse;
|
||||
/**
|
||||
* Handle a new connection (interface requirement)
|
||||
*/
|
||||
handleConnection(socket: plugins.net.Socket | plugins.tls.TLSSocket, secure: boolean): Promise<void>;
|
||||
/**
|
||||
* Check if accepting new connections (interface requirement)
|
||||
*/
|
||||
canAcceptConnection(): boolean;
|
||||
/**
|
||||
* Clean up resources
|
||||
*/
|
||||
destroy(): void;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
130
dist_ts/mail/delivery/smtpserver/constants.d.ts
vendored
130
dist_ts/mail/delivery/smtpserver/constants.d.ts
vendored
@@ -1,130 +0,0 @@
|
||||
/**
|
||||
* SMTP Server Constants
|
||||
* This file contains all constants and enums used by the SMTP server
|
||||
*/
|
||||
import { SmtpState } from '../interfaces.js';
|
||||
export { SmtpState };
|
||||
/**
|
||||
* SMTP Response Codes
|
||||
* Based on RFC 5321 and common SMTP practice
|
||||
*/
|
||||
export declare enum SmtpResponseCode {
|
||||
SUCCESS = 250,// Requested mail action okay, completed
|
||||
SYSTEM_STATUS = 211,// System status, or system help reply
|
||||
HELP_MESSAGE = 214,// Help message
|
||||
SERVICE_READY = 220,// <domain> Service ready
|
||||
SERVICE_CLOSING = 221,// <domain> Service closing transmission channel
|
||||
AUTHENTICATION_SUCCESSFUL = 235,// Authentication successful
|
||||
OK = 250,// Requested mail action okay, completed
|
||||
FORWARD = 251,// User not local; will forward to <forward-path>
|
||||
CANNOT_VRFY = 252,// Cannot VRFY user, but will accept message and attempt delivery
|
||||
MORE_INFO_NEEDED = 334,// Server challenge for authentication
|
||||
START_MAIL_INPUT = 354,// Start mail input; end with <CRLF>.<CRLF>
|
||||
SERVICE_NOT_AVAILABLE = 421,// <domain> Service not available, closing transmission channel
|
||||
MAILBOX_TEMPORARILY_UNAVAILABLE = 450,// Requested mail action not taken: mailbox unavailable
|
||||
LOCAL_ERROR = 451,// Requested action aborted: local error in processing
|
||||
INSUFFICIENT_STORAGE = 452,// Requested action not taken: insufficient system storage
|
||||
TLS_UNAVAILABLE_TEMP = 454,// TLS not available due to temporary reason
|
||||
SYNTAX_ERROR = 500,// Syntax error, command unrecognized
|
||||
SYNTAX_ERROR_PARAMETERS = 501,// Syntax error in parameters or arguments
|
||||
COMMAND_NOT_IMPLEMENTED = 502,// Command not implemented
|
||||
BAD_SEQUENCE = 503,// Bad sequence of commands
|
||||
COMMAND_PARAMETER_NOT_IMPLEMENTED = 504,// Command parameter not implemented
|
||||
AUTH_REQUIRED = 530,// Authentication required
|
||||
AUTH_FAILED = 535,// Authentication credentials invalid
|
||||
MAILBOX_UNAVAILABLE = 550,// Requested action not taken: mailbox unavailable
|
||||
USER_NOT_LOCAL = 551,// User not local; please try <forward-path>
|
||||
EXCEEDED_STORAGE = 552,// Requested mail action aborted: exceeded storage allocation
|
||||
MAILBOX_NAME_INVALID = 553,// Requested action not taken: mailbox name not allowed
|
||||
TRANSACTION_FAILED = 554,// Transaction failed
|
||||
MAIL_RCPT_PARAMETERS_INVALID = 555
|
||||
}
|
||||
/**
|
||||
* SMTP Command Types
|
||||
*/
|
||||
export declare enum SmtpCommand {
|
||||
HELO = "HELO",
|
||||
EHLO = "EHLO",
|
||||
MAIL_FROM = "MAIL",
|
||||
RCPT_TO = "RCPT",
|
||||
DATA = "DATA",
|
||||
RSET = "RSET",
|
||||
NOOP = "NOOP",
|
||||
QUIT = "QUIT",
|
||||
STARTTLS = "STARTTLS",
|
||||
AUTH = "AUTH",
|
||||
HELP = "HELP",
|
||||
VRFY = "VRFY",
|
||||
EXPN = "EXPN"
|
||||
}
|
||||
/**
|
||||
* Security log event types
|
||||
*/
|
||||
export declare enum SecurityEventType {
|
||||
CONNECTION = "connection",
|
||||
AUTHENTICATION = "authentication",
|
||||
COMMAND = "command",
|
||||
DATA = "data",
|
||||
IP_REPUTATION = "ip_reputation",
|
||||
TLS_NEGOTIATION = "tls_negotiation",
|
||||
DKIM = "dkim",
|
||||
SPF = "spf",
|
||||
DMARC = "dmarc",
|
||||
EMAIL_VALIDATION = "email_validation",
|
||||
SPAM = "spam",
|
||||
ACCESS_CONTROL = "access_control"
|
||||
}
|
||||
/**
|
||||
* Security log levels
|
||||
*/
|
||||
export declare enum SecurityLogLevel {
|
||||
DEBUG = "debug",
|
||||
INFO = "info",
|
||||
WARN = "warn",
|
||||
ERROR = "error"
|
||||
}
|
||||
/**
|
||||
* SMTP Server Defaults
|
||||
*/
|
||||
export declare const SMTP_DEFAULTS: {
|
||||
CONNECTION_TIMEOUT: number;
|
||||
SOCKET_TIMEOUT: number;
|
||||
DATA_TIMEOUT: number;
|
||||
CLEANUP_INTERVAL: number;
|
||||
MAX_CONNECTIONS: number;
|
||||
MAX_RECIPIENTS: number;
|
||||
MAX_MESSAGE_SIZE: number;
|
||||
SMTP_PORT: number;
|
||||
SUBMISSION_PORT: number;
|
||||
SECURE_PORT: number;
|
||||
HOSTNAME: string;
|
||||
CRLF: string;
|
||||
};
|
||||
/**
|
||||
* SMTP Command Patterns
|
||||
* Regular expressions for parsing SMTP commands
|
||||
*/
|
||||
export declare const SMTP_PATTERNS: {
|
||||
EHLO: RegExp;
|
||||
MAIL_FROM: RegExp;
|
||||
RCPT_TO: RegExp;
|
||||
PARAM: RegExp;
|
||||
EMAIL: RegExp;
|
||||
END_DATA: RegExp;
|
||||
};
|
||||
/**
|
||||
* SMTP Extension List
|
||||
* These extensions are advertised in the EHLO response
|
||||
*/
|
||||
export declare const SMTP_EXTENSIONS: {
|
||||
PIPELINING: string;
|
||||
SIZE: string;
|
||||
EIGHTBITMIME: string;
|
||||
STARTTLS: string;
|
||||
AUTH: string;
|
||||
ENHANCEDSTATUSCODES: string;
|
||||
HELP: string;
|
||||
CHUNKING: string;
|
||||
DSN: string;
|
||||
formatExtension(name: string, parameter?: string | number): string;
|
||||
};
|
||||
@@ -1,162 +0,0 @@
|
||||
/**
|
||||
* SMTP Server Constants
|
||||
* This file contains all constants and enums used by the SMTP server
|
||||
*/
|
||||
import { SmtpState } from '../interfaces.js';
|
||||
// Re-export SmtpState enum from the main interfaces file
|
||||
export { SmtpState };
|
||||
/**
|
||||
* SMTP Response Codes
|
||||
* Based on RFC 5321 and common SMTP practice
|
||||
*/
|
||||
export var SmtpResponseCode;
|
||||
(function (SmtpResponseCode) {
|
||||
// Success codes (2xx)
|
||||
SmtpResponseCode[SmtpResponseCode["SUCCESS"] = 250] = "SUCCESS";
|
||||
SmtpResponseCode[SmtpResponseCode["SYSTEM_STATUS"] = 211] = "SYSTEM_STATUS";
|
||||
SmtpResponseCode[SmtpResponseCode["HELP_MESSAGE"] = 214] = "HELP_MESSAGE";
|
||||
SmtpResponseCode[SmtpResponseCode["SERVICE_READY"] = 220] = "SERVICE_READY";
|
||||
SmtpResponseCode[SmtpResponseCode["SERVICE_CLOSING"] = 221] = "SERVICE_CLOSING";
|
||||
SmtpResponseCode[SmtpResponseCode["AUTHENTICATION_SUCCESSFUL"] = 235] = "AUTHENTICATION_SUCCESSFUL";
|
||||
SmtpResponseCode[SmtpResponseCode["OK"] = 250] = "OK";
|
||||
SmtpResponseCode[SmtpResponseCode["FORWARD"] = 251] = "FORWARD";
|
||||
SmtpResponseCode[SmtpResponseCode["CANNOT_VRFY"] = 252] = "CANNOT_VRFY";
|
||||
// Intermediate codes (3xx)
|
||||
SmtpResponseCode[SmtpResponseCode["MORE_INFO_NEEDED"] = 334] = "MORE_INFO_NEEDED";
|
||||
SmtpResponseCode[SmtpResponseCode["START_MAIL_INPUT"] = 354] = "START_MAIL_INPUT";
|
||||
// Temporary error codes (4xx)
|
||||
SmtpResponseCode[SmtpResponseCode["SERVICE_NOT_AVAILABLE"] = 421] = "SERVICE_NOT_AVAILABLE";
|
||||
SmtpResponseCode[SmtpResponseCode["MAILBOX_TEMPORARILY_UNAVAILABLE"] = 450] = "MAILBOX_TEMPORARILY_UNAVAILABLE";
|
||||
SmtpResponseCode[SmtpResponseCode["LOCAL_ERROR"] = 451] = "LOCAL_ERROR";
|
||||
SmtpResponseCode[SmtpResponseCode["INSUFFICIENT_STORAGE"] = 452] = "INSUFFICIENT_STORAGE";
|
||||
SmtpResponseCode[SmtpResponseCode["TLS_UNAVAILABLE_TEMP"] = 454] = "TLS_UNAVAILABLE_TEMP";
|
||||
// Permanent error codes (5xx)
|
||||
SmtpResponseCode[SmtpResponseCode["SYNTAX_ERROR"] = 500] = "SYNTAX_ERROR";
|
||||
SmtpResponseCode[SmtpResponseCode["SYNTAX_ERROR_PARAMETERS"] = 501] = "SYNTAX_ERROR_PARAMETERS";
|
||||
SmtpResponseCode[SmtpResponseCode["COMMAND_NOT_IMPLEMENTED"] = 502] = "COMMAND_NOT_IMPLEMENTED";
|
||||
SmtpResponseCode[SmtpResponseCode["BAD_SEQUENCE"] = 503] = "BAD_SEQUENCE";
|
||||
SmtpResponseCode[SmtpResponseCode["COMMAND_PARAMETER_NOT_IMPLEMENTED"] = 504] = "COMMAND_PARAMETER_NOT_IMPLEMENTED";
|
||||
SmtpResponseCode[SmtpResponseCode["AUTH_REQUIRED"] = 530] = "AUTH_REQUIRED";
|
||||
SmtpResponseCode[SmtpResponseCode["AUTH_FAILED"] = 535] = "AUTH_FAILED";
|
||||
SmtpResponseCode[SmtpResponseCode["MAILBOX_UNAVAILABLE"] = 550] = "MAILBOX_UNAVAILABLE";
|
||||
SmtpResponseCode[SmtpResponseCode["USER_NOT_LOCAL"] = 551] = "USER_NOT_LOCAL";
|
||||
SmtpResponseCode[SmtpResponseCode["EXCEEDED_STORAGE"] = 552] = "EXCEEDED_STORAGE";
|
||||
SmtpResponseCode[SmtpResponseCode["MAILBOX_NAME_INVALID"] = 553] = "MAILBOX_NAME_INVALID";
|
||||
SmtpResponseCode[SmtpResponseCode["TRANSACTION_FAILED"] = 554] = "TRANSACTION_FAILED";
|
||||
SmtpResponseCode[SmtpResponseCode["MAIL_RCPT_PARAMETERS_INVALID"] = 555] = "MAIL_RCPT_PARAMETERS_INVALID";
|
||||
})(SmtpResponseCode || (SmtpResponseCode = {}));
|
||||
/**
|
||||
* SMTP Command Types
|
||||
*/
|
||||
export var SmtpCommand;
|
||||
(function (SmtpCommand) {
|
||||
SmtpCommand["HELO"] = "HELO";
|
||||
SmtpCommand["EHLO"] = "EHLO";
|
||||
SmtpCommand["MAIL_FROM"] = "MAIL";
|
||||
SmtpCommand["RCPT_TO"] = "RCPT";
|
||||
SmtpCommand["DATA"] = "DATA";
|
||||
SmtpCommand["RSET"] = "RSET";
|
||||
SmtpCommand["NOOP"] = "NOOP";
|
||||
SmtpCommand["QUIT"] = "QUIT";
|
||||
SmtpCommand["STARTTLS"] = "STARTTLS";
|
||||
SmtpCommand["AUTH"] = "AUTH";
|
||||
SmtpCommand["HELP"] = "HELP";
|
||||
SmtpCommand["VRFY"] = "VRFY";
|
||||
SmtpCommand["EXPN"] = "EXPN";
|
||||
})(SmtpCommand || (SmtpCommand = {}));
|
||||
/**
|
||||
* Security log event types
|
||||
*/
|
||||
export var SecurityEventType;
|
||||
(function (SecurityEventType) {
|
||||
SecurityEventType["CONNECTION"] = "connection";
|
||||
SecurityEventType["AUTHENTICATION"] = "authentication";
|
||||
SecurityEventType["COMMAND"] = "command";
|
||||
SecurityEventType["DATA"] = "data";
|
||||
SecurityEventType["IP_REPUTATION"] = "ip_reputation";
|
||||
SecurityEventType["TLS_NEGOTIATION"] = "tls_negotiation";
|
||||
SecurityEventType["DKIM"] = "dkim";
|
||||
SecurityEventType["SPF"] = "spf";
|
||||
SecurityEventType["DMARC"] = "dmarc";
|
||||
SecurityEventType["EMAIL_VALIDATION"] = "email_validation";
|
||||
SecurityEventType["SPAM"] = "spam";
|
||||
SecurityEventType["ACCESS_CONTROL"] = "access_control";
|
||||
})(SecurityEventType || (SecurityEventType = {}));
|
||||
/**
|
||||
* Security log levels
|
||||
*/
|
||||
export var SecurityLogLevel;
|
||||
(function (SecurityLogLevel) {
|
||||
SecurityLogLevel["DEBUG"] = "debug";
|
||||
SecurityLogLevel["INFO"] = "info";
|
||||
SecurityLogLevel["WARN"] = "warn";
|
||||
SecurityLogLevel["ERROR"] = "error";
|
||||
})(SecurityLogLevel || (SecurityLogLevel = {}));
|
||||
/**
|
||||
* SMTP Server Defaults
|
||||
*/
|
||||
export const SMTP_DEFAULTS = {
|
||||
// Default timeouts in milliseconds
|
||||
CONNECTION_TIMEOUT: 30000, // 30 seconds
|
||||
SOCKET_TIMEOUT: 300000, // 5 minutes
|
||||
DATA_TIMEOUT: 60000, // 1 minute
|
||||
CLEANUP_INTERVAL: 5000, // 5 seconds
|
||||
// Default limits
|
||||
MAX_CONNECTIONS: 100,
|
||||
MAX_RECIPIENTS: 100,
|
||||
MAX_MESSAGE_SIZE: 10485760, // 10MB
|
||||
// Default ports
|
||||
SMTP_PORT: 25,
|
||||
SUBMISSION_PORT: 587,
|
||||
SECURE_PORT: 465,
|
||||
// Default hostname
|
||||
HOSTNAME: 'mail.lossless.one',
|
||||
// CRLF line ending required by SMTP protocol
|
||||
CRLF: '\r\n',
|
||||
};
|
||||
/**
|
||||
* SMTP Command Patterns
|
||||
* Regular expressions for parsing SMTP commands
|
||||
*/
|
||||
export const SMTP_PATTERNS = {
|
||||
// Match EHLO/HELO command: "EHLO example.com"
|
||||
// Made very permissive to handle various client implementations
|
||||
EHLO: /^(?:EHLO|HELO)\s+(.+)$/i,
|
||||
// Match MAIL FROM command: "MAIL FROM:<user@example.com> [PARAM=VALUE]"
|
||||
// Made more permissive with whitespace and parameter formats
|
||||
MAIL_FROM: /^MAIL\s+FROM\s*:\s*<([^>]*)>((?:\s+[a-zA-Z0-9][a-zA-Z0-9\-]*(?:=[^\s]+)?)*)$/i,
|
||||
// Match RCPT TO command: "RCPT TO:<user@example.com> [PARAM=VALUE]"
|
||||
// Made more permissive with whitespace and parameter formats
|
||||
RCPT_TO: /^RCPT\s+TO\s*:\s*<([^>]*)>((?:\s+[a-zA-Z0-9][a-zA-Z0-9\-]*(?:=[^\s]+)?)*)$/i,
|
||||
// Match parameter format: "PARAM=VALUE"
|
||||
PARAM: /\s+([A-Za-z0-9][A-Za-z0-9\-]*)(?:=([^\s]+))?/g,
|
||||
// Match email address format - basic validation
|
||||
// This pattern rejects common invalid formats while being permissive for edge cases
|
||||
// Checks: no spaces, has @, has domain with dot, no double dots, proper domain format
|
||||
EMAIL: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
||||
// Match end of DATA marker: \r\n.\r\n or just .\r\n at the start of a line (to handle various client implementations)
|
||||
END_DATA: /(\r\n\.\r\n$)|(\n\.\r\n$)|(\r\n\.\n$)|(\n\.\n$)|^\.(\r\n|\n)$/,
|
||||
};
|
||||
/**
|
||||
* SMTP Extension List
|
||||
* These extensions are advertised in the EHLO response
|
||||
*/
|
||||
export const SMTP_EXTENSIONS = {
|
||||
// Basic extensions (RFC 1869)
|
||||
PIPELINING: 'PIPELINING',
|
||||
SIZE: 'SIZE',
|
||||
EIGHTBITMIME: '8BITMIME',
|
||||
// Security extensions
|
||||
STARTTLS: 'STARTTLS',
|
||||
AUTH: 'AUTH',
|
||||
// Additional extensions
|
||||
ENHANCEDSTATUSCODES: 'ENHANCEDSTATUSCODES',
|
||||
HELP: 'HELP',
|
||||
CHUNKING: 'CHUNKING',
|
||||
DSN: 'DSN',
|
||||
// Format an extension with a parameter
|
||||
formatExtension(name, parameter) {
|
||||
return parameter !== undefined ? `${name} ${parameter}` : name;
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvbWFpbC9kZWxpdmVyeS9zbXRwc2VydmVyL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFN0MseURBQXlEO0FBQ3pELE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQztBQUVyQjs7O0dBR0c7QUFDSCxNQUFNLENBQU4sSUFBWSxnQkFxQ1g7QUFyQ0QsV0FBWSxnQkFBZ0I7SUFDMUIsc0JBQXNCO0lBQ3RCLCtEQUFhLENBQUE7SUFDYiwyRUFBbUIsQ0FBQTtJQUNuQix5RUFBa0IsQ0FBQTtJQUNsQiwyRUFBbUIsQ0FBQTtJQUNuQiwrRUFBcUIsQ0FBQTtJQUNyQixtR0FBK0IsQ0FBQTtJQUMvQixxREFBUSxDQUFBO0lBQ1IsK0RBQWEsQ0FBQTtJQUNiLHVFQUFpQixDQUFBO0lBRWpCLDJCQUEyQjtJQUMzQixpRkFBc0IsQ0FBQTtJQUN0QixpRkFBc0IsQ0FBQTtJQUV0Qiw4QkFBOEI7SUFDOUIsMkZBQTJCLENBQUE7SUFDM0IsK0dBQXFDLENBQUE7SUFDckMsdUVBQWlCLENBQUE7SUFDakIseUZBQTBCLENBQUE7SUFDMUIseUZBQTBCLENBQUE7SUFFMUIsOEJBQThCO0lBQzlCLHlFQUFrQixDQUFBO0lBQ2xCLCtGQUE2QixDQUFBO0lBQzdCLCtGQUE2QixDQUFBO0lBQzdCLHlFQUFrQixDQUFBO0lBQ2xCLG1IQUF1QyxDQUFBO0lBQ3ZDLDJFQUFtQixDQUFBO0lBQ25CLHVFQUFpQixDQUFBO0lBQ2pCLHVGQUF5QixDQUFBO0lBQ3pCLDZFQUFvQixDQUFBO0lBQ3BCLGlGQUFzQixDQUFBO0lBQ3RCLHlGQUEwQixDQUFBO0lBQzFCLHFGQUF3QixDQUFBO0lBQ3hCLHlHQUFrQyxDQUFBO0FBQ3BDLENBQUMsRUFyQ1csZ0JBQWdCLEtBQWhCLGdCQUFn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
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* SMTP Server Creation Factory
|
||||
* Provides a simple way to create a complete SMTP server
|
||||
*/
|
||||
import { SmtpServer } from './smtp-server.js';
|
||||
import type { ISmtpServerOptions } from './interfaces.js';
|
||||
import { UnifiedEmailServer } from '../../routing/classes.unified.email.server.js';
|
||||
/**
|
||||
* Create a complete SMTP server with all components
|
||||
* @param emailServer - Email server reference
|
||||
* @param options - SMTP server options
|
||||
* @returns Configured SMTP server instance
|
||||
*/
|
||||
export declare function createSmtpServer(emailServer: UnifiedEmailServer, options: ISmtpServerOptions): SmtpServer;
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* SMTP Server Creation Factory
|
||||
* Provides a simple way to create a complete SMTP server
|
||||
*/
|
||||
import { SmtpServer } from './smtp-server.js';
|
||||
import { SessionManager } from './session-manager.js';
|
||||
import { ConnectionManager } from './connection-manager.js';
|
||||
import { CommandHandler } from './command-handler.js';
|
||||
import { DataHandler } from './data-handler.js';
|
||||
import { TlsHandler } from './tls-handler.js';
|
||||
import { SecurityHandler } from './security-handler.js';
|
||||
import { UnifiedEmailServer } from '../../routing/classes.unified.email.server.js';
|
||||
/**
|
||||
* Create a complete SMTP server with all components
|
||||
* @param emailServer - Email server reference
|
||||
* @param options - SMTP server options
|
||||
* @returns Configured SMTP server instance
|
||||
*/
|
||||
export function createSmtpServer(emailServer, options) {
|
||||
// First create the SMTP server instance
|
||||
const smtpServer = new SmtpServer({
|
||||
emailServer,
|
||||
options
|
||||
});
|
||||
// Return the configured server
|
||||
return smtpServer;
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLXNlcnZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvc210cHNlcnZlci9jcmVhdGUtc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDOUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRXhELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBRW5GOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLFdBQStCLEVBQUUsT0FBMkI7SUFDM0Ysd0NBQXdDO0lBQ3hDLE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDO1FBQ2hDLFdBQVc7UUFDWCxPQUFPO0tBQ1IsQ0FBQyxDQUFDO0lBRUgsK0JBQStCO0lBQy9CLE9BQU8sVUFBVSxDQUFDO0FBQ3BCLENBQUMifQ==
|
||||
123
dist_ts/mail/delivery/smtpserver/data-handler.d.ts
vendored
123
dist_ts/mail/delivery/smtpserver/data-handler.d.ts
vendored
@@ -1,123 +0,0 @@
|
||||
/**
|
||||
* SMTP Data Handler
|
||||
* Responsible for processing email data during and after DATA command
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import type { ISmtpSession, ISmtpTransactionResult } from './interfaces.js';
|
||||
import type { IDataHandler, ISmtpServer } from './interfaces.js';
|
||||
import { Email } from '../../core/classes.email.js';
|
||||
/**
|
||||
* Handles SMTP DATA command and email data processing
|
||||
*/
|
||||
export declare class DataHandler implements IDataHandler {
|
||||
/**
|
||||
* Reference to the SMTP server instance
|
||||
*/
|
||||
private smtpServer;
|
||||
/**
|
||||
* Creates a new data handler
|
||||
* @param smtpServer - SMTP server instance
|
||||
*/
|
||||
constructor(smtpServer: ISmtpServer);
|
||||
/**
|
||||
* Process incoming email data
|
||||
* @param socket - Client socket
|
||||
* @param data - Data chunk
|
||||
* @returns Promise that resolves when the data is processed
|
||||
*/
|
||||
processEmailData(socket: plugins.net.Socket | plugins.tls.TLSSocket, data: string): Promise<void>;
|
||||
/**
|
||||
* Handle raw data chunks during DATA mode (optimized for large messages)
|
||||
* @param socket - Client socket
|
||||
* @param data - Raw data chunk
|
||||
*/
|
||||
handleDataReceived(socket: plugins.net.Socket | plugins.tls.TLSSocket, data: string): Promise<void>;
|
||||
/**
|
||||
* Process email data chunks efficiently for large messages
|
||||
* @param chunks - Array of email data chunks
|
||||
* @returns Processed email data string
|
||||
*/
|
||||
private processEmailDataStreaming;
|
||||
/**
|
||||
* Process a complete email
|
||||
* @param rawData - Raw email data
|
||||
* @param session - SMTP session
|
||||
* @returns Promise that resolves with the Email object
|
||||
*/
|
||||
processEmail(rawData: string, session: ISmtpSession): Promise<Email>;
|
||||
/**
|
||||
* Parse email from raw data
|
||||
* @param rawData - Raw email data
|
||||
* @param session - SMTP session
|
||||
* @returns Email object
|
||||
*/
|
||||
private parseEmailFromData;
|
||||
/**
|
||||
* Process a complete email (legacy method)
|
||||
* @param session - SMTP session
|
||||
* @returns Promise that resolves with the result of the transaction
|
||||
*/
|
||||
processEmailLegacy(session: ISmtpSession): Promise<ISmtpTransactionResult>;
|
||||
/**
|
||||
* Save an email to disk
|
||||
* @param session - SMTP session
|
||||
*/
|
||||
saveEmail(session: ISmtpSession): void;
|
||||
/**
|
||||
* Parse an email into an Email object
|
||||
* @param session - SMTP session
|
||||
* @returns Promise that resolves with the parsed Email object
|
||||
*/
|
||||
parseEmail(session: ISmtpSession): Promise<Email>;
|
||||
/**
|
||||
* Basic fallback method for parsing emails
|
||||
* @param session - SMTP session
|
||||
* @returns The parsed Email object
|
||||
*/
|
||||
private parseEmailBasic;
|
||||
/**
|
||||
* Handle multipart content parsing
|
||||
* @param email - Email object to update
|
||||
* @param bodyText - Body text to parse
|
||||
* @param boundary - MIME boundary
|
||||
*/
|
||||
private handleMultipartContent;
|
||||
/**
|
||||
* Handle end of data marker received
|
||||
* @param socket - Client socket
|
||||
* @param session - SMTP session
|
||||
*/
|
||||
private handleEndOfData;
|
||||
/**
|
||||
* Reset session after email processing
|
||||
* @param session - SMTP session
|
||||
*/
|
||||
private resetSession;
|
||||
/**
|
||||
* Send a response to the client
|
||||
* @param socket - Client socket
|
||||
* @param response - Response message
|
||||
*/
|
||||
private sendResponse;
|
||||
/**
|
||||
* Check if a socket error is potentially recoverable
|
||||
* @param error - The error that occurred
|
||||
* @returns Whether the error is potentially recoverable
|
||||
*/
|
||||
private isRecoverableSocketError;
|
||||
/**
|
||||
* Handle recoverable socket errors with retry logic
|
||||
* @param socket - Client socket
|
||||
* @param error - The error that occurred
|
||||
* @param response - The response that failed to send
|
||||
*/
|
||||
private handleSocketError;
|
||||
/**
|
||||
* Handle email data (interface requirement)
|
||||
*/
|
||||
handleData(socket: plugins.net.Socket | plugins.tls.TLSSocket, data: string, session: ISmtpSession): Promise<void>;
|
||||
/**
|
||||
* Clean up resources
|
||||
*/
|
||||
destroy(): void;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
20
dist_ts/mail/delivery/smtpserver/index.d.ts
vendored
20
dist_ts/mail/delivery/smtpserver/index.d.ts
vendored
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* SMTP Server Module Exports
|
||||
* This file exports all components of the refactored SMTP server
|
||||
*/
|
||||
export * from './interfaces.js';
|
||||
export { SmtpServer } from './smtp-server.js';
|
||||
export { SessionManager } from './session-manager.js';
|
||||
export { ConnectionManager } from './connection-manager.js';
|
||||
export { CommandHandler } from './command-handler.js';
|
||||
export { DataHandler } from './data-handler.js';
|
||||
export { TlsHandler } from './tls-handler.js';
|
||||
export { SecurityHandler } from './security-handler.js';
|
||||
export * from './constants.js';
|
||||
export { SmtpLogger } from './utils/logging.js';
|
||||
export * from './utils/validation.js';
|
||||
export * from './utils/helpers.js';
|
||||
export * from './certificate-utils.js';
|
||||
export * from './secure-server.js';
|
||||
export * from './starttls-handler.js';
|
||||
export { createSmtpServer } from './create-server.js';
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* SMTP Server Module Exports
|
||||
* This file exports all components of the refactored SMTP server
|
||||
*/
|
||||
// Export interfaces
|
||||
export * from './interfaces.js';
|
||||
// Export server classes
|
||||
export { SmtpServer } from './smtp-server.js';
|
||||
export { SessionManager } from './session-manager.js';
|
||||
export { ConnectionManager } from './connection-manager.js';
|
||||
export { CommandHandler } from './command-handler.js';
|
||||
export { DataHandler } from './data-handler.js';
|
||||
export { TlsHandler } from './tls-handler.js';
|
||||
export { SecurityHandler } from './security-handler.js';
|
||||
// Export constants
|
||||
export * from './constants.js';
|
||||
// Export utilities
|
||||
export { SmtpLogger } from './utils/logging.js';
|
||||
export * from './utils/validation.js';
|
||||
export * from './utils/helpers.js';
|
||||
// Export TLS and certificate utilities
|
||||
export * from './certificate-utils.js';
|
||||
export * from './secure-server.js';
|
||||
export * from './starttls-handler.js';
|
||||
// Factory function to create a complete SMTP server with default components
|
||||
export { createSmtpServer } from './create-server.js';
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9tYWlsL2RlbGl2ZXJ5L3NtdHBzZXJ2ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsb0JBQW9CO0FBQ3BCLGNBQWMsaUJBQWlCLENBQUM7QUFFaEMsd0JBQXdCO0FBQ3hCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDOUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRXhELG1CQUFtQjtBQUNuQixjQUFjLGdCQUFnQixDQUFDO0FBRS9CLG1CQUFtQjtBQUNuQixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLG9CQUFvQixDQUFDO0FBRW5DLHVDQUF1QztBQUN2QyxjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyx1QkFBdUIsQ0FBQztBQUV0Qyw0RUFBNEU7QUFDNUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sb0JBQW9CLENBQUMifQ==
|
||||
530
dist_ts/mail/delivery/smtpserver/interfaces.d.ts
vendored
530
dist_ts/mail/delivery/smtpserver/interfaces.d.ts
vendored
@@ -1,530 +0,0 @@
|
||||
/**
|
||||
* 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';
|
||||
import { SmtpCommand } from './constants.js';
|
||||
export { SmtpState, SmtpCommand };
|
||||
export type { IEnvelopeRecipient } from '../interfaces.js';
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* SMTP Server Interfaces
|
||||
* Defines all the interfaces used by the SMTP server implementation
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
// Re-export types from other modules
|
||||
import { SmtpState } from '../interfaces.js';
|
||||
import { SmtpCommand } from './constants.js';
|
||||
export { SmtpState, SmtpCommand };
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvc210cHNlcnZlci9pbnRlcmZhY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFJL0MsdUNBQXVDO0FBQ3ZDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsQ0FBQyJ9
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Secure SMTP Server Utility Functions
|
||||
* Provides helper functions for creating and managing secure TLS server
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
/**
|
||||
* Create a secure TLS server for direct TLS connections
|
||||
* @param options - TLS certificate options
|
||||
* @returns A configured TLS server or undefined if TLS is not available
|
||||
*/
|
||||
export declare function createSecureTlsServer(options: {
|
||||
key: string;
|
||||
cert: string;
|
||||
ca?: string;
|
||||
}): plugins.tls.Server | undefined;
|
||||
@@ -1,79 +0,0 @@
|
||||
/**
|
||||
* Secure SMTP Server Utility Functions
|
||||
* Provides helper functions for creating and managing secure TLS server
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import { loadCertificatesFromString, generateSelfSignedCertificates, createTlsOptions } from './certificate-utils.js';
|
||||
import { SmtpLogger } from './utils/logging.js';
|
||||
/**
|
||||
* Create a secure TLS server for direct TLS connections
|
||||
* @param options - TLS certificate options
|
||||
* @returns A configured TLS server or undefined if TLS is not available
|
||||
*/
|
||||
export function createSecureTlsServer(options) {
|
||||
try {
|
||||
// Log the creation attempt
|
||||
SmtpLogger.info('Creating secure TLS server for direct connections');
|
||||
// Load certificates from strings
|
||||
let certificates;
|
||||
try {
|
||||
certificates = loadCertificatesFromString({
|
||||
key: options.key,
|
||||
cert: options.cert,
|
||||
ca: options.ca
|
||||
});
|
||||
SmtpLogger.info('Successfully loaded TLS certificates for secure server');
|
||||
}
|
||||
catch (certificateError) {
|
||||
SmtpLogger.warn(`Failed to load certificates, using self-signed: ${certificateError instanceof Error ? certificateError.message : String(certificateError)}`);
|
||||
certificates = generateSelfSignedCertificates();
|
||||
}
|
||||
// Create server-side TLS options
|
||||
const tlsOptions = createTlsOptions(certificates, true);
|
||||
// Log details for debugging
|
||||
SmtpLogger.debug('Creating secure server with options', {
|
||||
certificates: {
|
||||
keyLength: certificates.key.length,
|
||||
certLength: certificates.cert.length,
|
||||
caLength: certificates.ca ? certificates.ca.length : 0
|
||||
},
|
||||
tlsOptions: {
|
||||
minVersion: tlsOptions.minVersion,
|
||||
maxVersion: tlsOptions.maxVersion,
|
||||
ciphers: tlsOptions.ciphers?.substring(0, 50) + '...' // Truncate long cipher list
|
||||
}
|
||||
});
|
||||
// Create the TLS server
|
||||
const server = new plugins.tls.Server(tlsOptions);
|
||||
// Set up error handlers
|
||||
server.on('error', (err) => {
|
||||
SmtpLogger.error(`Secure server error: ${err.message}`, {
|
||||
component: 'secure-server',
|
||||
error: err,
|
||||
stack: err.stack
|
||||
});
|
||||
});
|
||||
// Log secure connections
|
||||
server.on('secureConnection', (socket) => {
|
||||
const protocol = socket.getProtocol();
|
||||
const cipher = socket.getCipher();
|
||||
SmtpLogger.info('New direct TLS connection established', {
|
||||
component: 'secure-server',
|
||||
remoteAddress: socket.remoteAddress,
|
||||
remotePort: socket.remotePort,
|
||||
protocol: protocol || 'unknown',
|
||||
cipher: cipher?.name || 'unknown'
|
||||
});
|
||||
});
|
||||
return server;
|
||||
}
|
||||
catch (error) {
|
||||
SmtpLogger.error(`Failed to create secure TLS server: ${error instanceof Error ? error.message : String(error)}`, {
|
||||
component: 'secure-server',
|
||||
error: error instanceof Error ? error : new Error(String(error)),
|
||||
stack: error instanceof Error ? error.stack : 'No stack trace available'
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VjdXJlLXNlcnZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvc210cHNlcnZlci9zZWN1cmUtc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxFQUNMLDBCQUEwQixFQUMxQiw4QkFBOEIsRUFDOUIsZ0JBQWdCLEVBRWpCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRWhEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQUMsT0FJckM7SUFDQyxJQUFJLENBQUM7UUFDSCwyQkFBMkI7UUFDM0IsVUFBVSxDQUFDLElBQUksQ0FBQyxtREFBbUQsQ0FBQyxDQUFDO1FBRXJFLGlDQUFpQztRQUNqQyxJQUFJLFlBQThCLENBQUM7UUFDbkMsSUFBSSxDQUFDO1lBQ0gsWUFBWSxHQUFHLDBCQUEwQixDQUFDO2dCQUN4QyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7Z0JBQ2hCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtnQkFDbEIsRUFBRSxFQUFFLE9BQU8sQ0FBQyxFQUFFO2FBQ2YsQ0FBQyxDQUFDO1lBRUgsVUFBVSxDQUFDLElBQUksQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO1FBQzVFLENBQUM7UUFBQyxPQUFPLGdCQUFnQixFQUFFLENBQUM7WUFDMUIsVUFBVSxDQUFDLElBQUksQ0FBQyxtREFBbUQsZ0JBQWdCLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUM5SixZQUFZLEdBQUcsOEJBQThCLEVBQUUsQ0FBQztRQUNsRCxDQUFDO1FBRUQsaUNBQWlDO1FBQ2pDLE1BQU0s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
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* SMTP Security Handler
|
||||
* Responsible for security aspects including IP reputation checking,
|
||||
* email validation, and authentication
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import type { ISmtpAuth } from './interfaces.js';
|
||||
import type { ISecurityHandler, ISmtpServer } from './interfaces.js';
|
||||
/**
|
||||
* Handles security aspects for SMTP server
|
||||
*/
|
||||
export declare class SecurityHandler implements ISecurityHandler {
|
||||
/**
|
||||
* Reference to the SMTP server instance
|
||||
*/
|
||||
private smtpServer;
|
||||
/**
|
||||
* IP reputation checker service
|
||||
*/
|
||||
private ipReputationService;
|
||||
/**
|
||||
* Simple in-memory IP denylist
|
||||
*/
|
||||
private ipDenylist;
|
||||
/**
|
||||
* Cleanup interval timer
|
||||
*/
|
||||
private cleanupInterval;
|
||||
/**
|
||||
* Creates a new security handler
|
||||
* @param smtpServer - SMTP server instance
|
||||
*/
|
||||
constructor(smtpServer: ISmtpServer);
|
||||
/**
|
||||
* Check IP reputation for a connection
|
||||
* @param socket - Client socket
|
||||
* @returns Promise that resolves to true if IP is allowed, false if blocked
|
||||
*/
|
||||
checkIpReputation(socket: plugins.net.Socket | plugins.tls.TLSSocket): Promise<boolean>;
|
||||
/**
|
||||
* Validate an email address
|
||||
* @param email - Email address to validate
|
||||
* @returns Whether the email address is valid
|
||||
*/
|
||||
isValidEmail(email: string): boolean;
|
||||
/**
|
||||
* Validate authentication credentials
|
||||
* @param auth - Authentication credentials
|
||||
* @returns Promise that resolves to true if authenticated
|
||||
*/
|
||||
authenticate(auth: ISmtpAuth): Promise<boolean>;
|
||||
/**
|
||||
* Log a security event
|
||||
* @param event - Event type
|
||||
* @param level - Log level
|
||||
* @param details - Event details
|
||||
*/
|
||||
logSecurityEvent(event: string, level: string, message: string, details: Record<string, any>): void;
|
||||
/**
|
||||
* Add an IP to the denylist
|
||||
* @param ip - IP address
|
||||
* @param reason - Reason for denylisting
|
||||
* @param duration - Duration in milliseconds (optional, indefinite if not specified)
|
||||
*/
|
||||
private addToDenylist;
|
||||
/**
|
||||
* Check if an IP is denylisted
|
||||
* @param ip - IP address
|
||||
* @returns Whether the IP is denylisted
|
||||
*/
|
||||
private isIpDenylisted;
|
||||
/**
|
||||
* Get the reason an IP was denylisted
|
||||
* @param ip - IP address
|
||||
* @returns Reason for denylisting or undefined if not denylisted
|
||||
*/
|
||||
private getDenylistReason;
|
||||
/**
|
||||
* Clean expired denylist entries
|
||||
*/
|
||||
private cleanExpiredDenylistEntries;
|
||||
/**
|
||||
* Clean up resources
|
||||
*/
|
||||
destroy(): void;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,140 +0,0 @@
|
||||
/**
|
||||
* SMTP Session Manager
|
||||
* Responsible for creating, managing, and cleaning up SMTP sessions
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import { SmtpState } from './interfaces.js';
|
||||
import type { ISmtpSession } from './interfaces.js';
|
||||
import type { ISessionManager, ISessionEvents } from './interfaces.js';
|
||||
/**
|
||||
* Manager for SMTP sessions
|
||||
* Handles session creation, tracking, timeout management, and cleanup
|
||||
*/
|
||||
export declare class SessionManager implements ISessionManager {
|
||||
/**
|
||||
* Map of socket ID to session
|
||||
*/
|
||||
private sessions;
|
||||
/**
|
||||
* Map of socket to socket ID
|
||||
*/
|
||||
private socketIds;
|
||||
/**
|
||||
* SMTP server options
|
||||
*/
|
||||
private options;
|
||||
/**
|
||||
* Event listeners
|
||||
*/
|
||||
private eventListeners;
|
||||
/**
|
||||
* Timer for cleanup interval
|
||||
*/
|
||||
private cleanupTimer;
|
||||
/**
|
||||
* Creates a new session manager
|
||||
* @param options - Session manager options
|
||||
*/
|
||||
constructor(options?: {
|
||||
socketTimeout?: number;
|
||||
connectionTimeout?: number;
|
||||
cleanupInterval?: number;
|
||||
});
|
||||
/**
|
||||
* Creates a new session for a socket connection
|
||||
* @param socket - Client socket
|
||||
* @param secure - Whether the connection is secure (TLS)
|
||||
* @returns New SMTP session
|
||||
*/
|
||||
createSession(socket: plugins.net.Socket | plugins.tls.TLSSocket, secure: boolean): ISmtpSession;
|
||||
/**
|
||||
* Updates the session state
|
||||
* @param session - SMTP session
|
||||
* @param newState - New state
|
||||
*/
|
||||
updateSessionState(session: ISmtpSession, newState: SmtpState): void;
|
||||
/**
|
||||
* Updates the session's last activity timestamp
|
||||
* @param session - SMTP session
|
||||
*/
|
||||
updateSessionActivity(session: ISmtpSession): void;
|
||||
/**
|
||||
* Removes a session
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
removeSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
|
||||
/**
|
||||
* Gets a session for a socket
|
||||
* @param socket - Client socket
|
||||
* @returns SMTP session or undefined if not found
|
||||
*/
|
||||
getSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): ISmtpSession | undefined;
|
||||
/**
|
||||
* Cleans up idle sessions
|
||||
*/
|
||||
cleanupIdleSessions(): void;
|
||||
/**
|
||||
* Gets the current number of active sessions
|
||||
* @returns Number of active sessions
|
||||
*/
|
||||
getSessionCount(): number;
|
||||
/**
|
||||
* Clears all sessions (used when shutting down)
|
||||
*/
|
||||
clearAllSessions(): void;
|
||||
/**
|
||||
* Register an event listener
|
||||
* @param event - Event name
|
||||
* @param listener - Event listener function
|
||||
*/
|
||||
on<K extends keyof ISessionEvents>(event: K, listener: ISessionEvents[K]): void;
|
||||
/**
|
||||
* Remove an event listener
|
||||
* @param event - Event name
|
||||
* @param listener - Event listener function
|
||||
*/
|
||||
off<K extends keyof ISessionEvents>(event: K, listener: ISessionEvents[K]): void;
|
||||
/**
|
||||
* Emit an event to registered listeners
|
||||
* @param event - Event name
|
||||
* @param args - Event arguments
|
||||
*/
|
||||
private emitEvent;
|
||||
/**
|
||||
* Start the cleanup timer
|
||||
*/
|
||||
private startCleanupTimer;
|
||||
/**
|
||||
* Stop the cleanup timer
|
||||
*/
|
||||
private stopCleanupTimer;
|
||||
/**
|
||||
* Replace socket mapping for STARTTLS upgrades
|
||||
* @param oldSocket - Original plain socket
|
||||
* @param newSocket - New TLS socket
|
||||
* @returns Whether the replacement was successful
|
||||
*/
|
||||
replaceSocket(oldSocket: plugins.net.Socket | plugins.tls.TLSSocket, newSocket: plugins.net.Socket | plugins.tls.TLSSocket): boolean;
|
||||
/**
|
||||
* Gets a unique key for a socket
|
||||
* @param socket - Client socket
|
||||
* @returns Socket key
|
||||
*/
|
||||
private getSocketKey;
|
||||
/**
|
||||
* Get all active sessions
|
||||
*/
|
||||
getAllSessions(): ISmtpSession[];
|
||||
/**
|
||||
* Update last activity for a session by socket
|
||||
*/
|
||||
updateLastActivity(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
|
||||
/**
|
||||
* Check for timed out sessions
|
||||
*/
|
||||
checkTimeouts(timeoutMs: number): ISmtpSession[];
|
||||
/**
|
||||
* Clean up resources
|
||||
*/
|
||||
destroy(): void;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
137
dist_ts/mail/delivery/smtpserver/smtp-server.d.ts
vendored
137
dist_ts/mail/delivery/smtpserver/smtp-server.d.ts
vendored
@@ -1,137 +0,0 @@
|
||||
/**
|
||||
* SMTP Server
|
||||
* Core implementation for the refactored SMTP server
|
||||
*/
|
||||
import type { ISmtpServerOptions } from './interfaces.js';
|
||||
import type { ISmtpServer, ISmtpServerConfig, ISessionManager, IConnectionManager, ICommandHandler, IDataHandler, ITlsHandler, ISecurityHandler } from './interfaces.js';
|
||||
import { UnifiedEmailServer } from '../../routing/classes.unified.email.server.js';
|
||||
/**
|
||||
* SMTP Server implementation
|
||||
* The main server class that coordinates all components
|
||||
*/
|
||||
export declare class SmtpServer implements ISmtpServer {
|
||||
/**
|
||||
* Email server reference
|
||||
*/
|
||||
private emailServer;
|
||||
/**
|
||||
* Session manager
|
||||
*/
|
||||
private sessionManager;
|
||||
/**
|
||||
* Connection manager
|
||||
*/
|
||||
private connectionManager;
|
||||
/**
|
||||
* Command handler
|
||||
*/
|
||||
private commandHandler;
|
||||
/**
|
||||
* Data handler
|
||||
*/
|
||||
private dataHandler;
|
||||
/**
|
||||
* TLS handler
|
||||
*/
|
||||
private tlsHandler;
|
||||
/**
|
||||
* Security handler
|
||||
*/
|
||||
private securityHandler;
|
||||
/**
|
||||
* SMTP server options
|
||||
*/
|
||||
private options;
|
||||
/**
|
||||
* Net server instance
|
||||
*/
|
||||
private server;
|
||||
/**
|
||||
* Secure server instance
|
||||
*/
|
||||
private secureServer;
|
||||
/**
|
||||
* Whether the server is running
|
||||
*/
|
||||
private running;
|
||||
/**
|
||||
* Server recovery state
|
||||
*/
|
||||
private recoveryState;
|
||||
/**
|
||||
* Creates a new SMTP server
|
||||
* @param config - Server configuration
|
||||
*/
|
||||
constructor(config: ISmtpServerConfig);
|
||||
/**
|
||||
* Start the SMTP server
|
||||
* @returns Promise that resolves when server is started
|
||||
*/
|
||||
listen(): Promise<void>;
|
||||
/**
|
||||
* Stop the SMTP server
|
||||
* @returns Promise that resolves when server is stopped
|
||||
*/
|
||||
close(): Promise<void>;
|
||||
/**
|
||||
* Get the session manager
|
||||
* @returns Session manager instance
|
||||
*/
|
||||
getSessionManager(): ISessionManager;
|
||||
/**
|
||||
* Get the connection manager
|
||||
* @returns Connection manager instance
|
||||
*/
|
||||
getConnectionManager(): IConnectionManager;
|
||||
/**
|
||||
* Get the command handler
|
||||
* @returns Command handler instance
|
||||
*/
|
||||
getCommandHandler(): ICommandHandler;
|
||||
/**
|
||||
* Get the data handler
|
||||
* @returns Data handler instance
|
||||
*/
|
||||
getDataHandler(): IDataHandler;
|
||||
/**
|
||||
* Get the TLS handler
|
||||
* @returns TLS handler instance
|
||||
*/
|
||||
getTlsHandler(): ITlsHandler;
|
||||
/**
|
||||
* Get the security handler
|
||||
* @returns Security handler instance
|
||||
*/
|
||||
getSecurityHandler(): ISecurityHandler;
|
||||
/**
|
||||
* Get the server options
|
||||
* @returns SMTP server options
|
||||
*/
|
||||
getOptions(): ISmtpServerOptions;
|
||||
/**
|
||||
* Get the email server reference
|
||||
* @returns Email server instance
|
||||
*/
|
||||
getEmailServer(): UnifiedEmailServer;
|
||||
/**
|
||||
* Check if the server is running
|
||||
* @returns Whether the server is running
|
||||
*/
|
||||
isRunning(): boolean;
|
||||
/**
|
||||
* Check if we should attempt to recover from an error
|
||||
* @param error - The error that occurred
|
||||
* @returns Whether recovery should be attempted
|
||||
*/
|
||||
private shouldAttemptRecovery;
|
||||
/**
|
||||
* Attempt to recover the server after a critical error
|
||||
* @param serverType - The type of server to recover ('standard' or 'secure')
|
||||
* @param error - The error that triggered recovery
|
||||
*/
|
||||
private attemptServerRecovery;
|
||||
/**
|
||||
* Clean up all component resources
|
||||
*/
|
||||
destroy(): Promise<void>;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* STARTTLS Implementation
|
||||
* Provides an improved implementation for STARTTLS upgrades
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import type { ISmtpSession, ISessionManager, IConnectionManager } from './interfaces.js';
|
||||
import { SmtpState } from '../interfaces.js';
|
||||
/**
|
||||
* Enhanced STARTTLS handler for more reliable TLS upgrades
|
||||
*/
|
||||
export declare function performStartTLS(socket: plugins.net.Socket, options: {
|
||||
key: string;
|
||||
cert: string;
|
||||
ca?: string;
|
||||
session?: ISmtpSession;
|
||||
sessionManager?: ISessionManager;
|
||||
connectionManager?: IConnectionManager;
|
||||
onSuccess?: (tlsSocket: plugins.tls.TLSSocket) => void;
|
||||
onFailure?: (error: Error) => void;
|
||||
updateSessionState?: (session: ISmtpSession, state: SmtpState) => void;
|
||||
}): Promise<plugins.tls.TLSSocket | undefined>;
|
||||
File diff suppressed because one or more lines are too long
@@ -1,66 +0,0 @@
|
||||
/**
|
||||
* SMTP TLS Handler
|
||||
* Responsible for handling TLS-related SMTP functionality
|
||||
*/
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import type { ITlsHandler, ISmtpServer, ISmtpSession } from './interfaces.js';
|
||||
/**
|
||||
* Handles TLS functionality for SMTP server
|
||||
*/
|
||||
export declare class TlsHandler implements ITlsHandler {
|
||||
/**
|
||||
* Reference to the SMTP server instance
|
||||
*/
|
||||
private smtpServer;
|
||||
/**
|
||||
* Certificate data
|
||||
*/
|
||||
private certificates;
|
||||
/**
|
||||
* TLS options
|
||||
*/
|
||||
private options;
|
||||
/**
|
||||
* Creates a new TLS handler
|
||||
* @param smtpServer - SMTP server instance
|
||||
*/
|
||||
constructor(smtpServer: ISmtpServer);
|
||||
/**
|
||||
* Handle STARTTLS command
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
handleStartTls(socket: plugins.net.Socket, session: ISmtpSession): Promise<plugins.tls.TLSSocket | null>;
|
||||
/**
|
||||
* Upgrade a connection to TLS
|
||||
* @param socket - Client socket
|
||||
*/
|
||||
startTLS(socket: plugins.net.Socket): Promise<plugins.tls.TLSSocket>;
|
||||
/**
|
||||
* Create a secure server
|
||||
* @returns TLS server instance or undefined if TLS is not enabled
|
||||
*/
|
||||
createSecureServer(): plugins.tls.Server | undefined;
|
||||
/**
|
||||
* Check if TLS is enabled
|
||||
* @returns Whether TLS is enabled
|
||||
*/
|
||||
isTlsEnabled(): boolean;
|
||||
/**
|
||||
* Send a response to the client
|
||||
* @param socket - Client socket
|
||||
* @param response - Response message
|
||||
*/
|
||||
private sendResponse;
|
||||
/**
|
||||
* Check if TLS is available (interface requirement)
|
||||
*/
|
||||
isTlsAvailable(): boolean;
|
||||
/**
|
||||
* Get TLS options (interface requirement)
|
||||
*/
|
||||
getTlsOptions(): plugins.tls.TlsOptions;
|
||||
/**
|
||||
* Clean up resources
|
||||
*/
|
||||
destroy(): void;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,117 +0,0 @@
|
||||
/**
|
||||
* Adaptive SMTP Logging System
|
||||
* Automatically switches between logging modes based on server load (active connections)
|
||||
* to maintain performance during high-concurrency scenarios
|
||||
*/
|
||||
import * as plugins from '../../../../plugins.js';
|
||||
import { SecurityLogLevel, SecurityEventType } from '../constants.js';
|
||||
import type { ISmtpSession } from '../interfaces.js';
|
||||
import type { LogLevel, ISmtpLogOptions } from './logging.js';
|
||||
/**
|
||||
* Log modes based on server load
|
||||
*/
|
||||
export declare enum LogMode {
|
||||
VERBOSE = "VERBOSE",// < 20 connections: Full detailed logging
|
||||
REDUCED = "REDUCED",// 20-40 connections: Limited command/response logging, full error logging
|
||||
MINIMAL = "MINIMAL"
|
||||
}
|
||||
/**
|
||||
* Configuration for adaptive logging thresholds
|
||||
*/
|
||||
export interface IAdaptiveLogConfig {
|
||||
verboseThreshold: number;
|
||||
reducedThreshold: number;
|
||||
aggregationInterval: number;
|
||||
maxAggregatedEntries: number;
|
||||
}
|
||||
/**
|
||||
* Connection metadata for aggregation tracking
|
||||
*/
|
||||
interface IConnectionTracker {
|
||||
activeConnections: number;
|
||||
peakConnections: number;
|
||||
totalConnections: number;
|
||||
connectionsPerSecond: number;
|
||||
lastConnectionTime: number;
|
||||
}
|
||||
/**
|
||||
* Adaptive SMTP Logger that scales logging based on server load
|
||||
*/
|
||||
export declare class AdaptiveSmtpLogger {
|
||||
private static instance;
|
||||
private currentMode;
|
||||
private config;
|
||||
private aggregatedEntries;
|
||||
private aggregationTimer;
|
||||
private connectionTracker;
|
||||
private constructor();
|
||||
/**
|
||||
* Get singleton instance
|
||||
*/
|
||||
static getInstance(config?: Partial<IAdaptiveLogConfig>): AdaptiveSmtpLogger;
|
||||
/**
|
||||
* Update active connection count and adjust log mode if needed
|
||||
*/
|
||||
updateConnectionCount(activeConnections: number): void;
|
||||
/**
|
||||
* Track new connection for rate calculation
|
||||
*/
|
||||
trackConnection(): void;
|
||||
/**
|
||||
* Get current logging mode
|
||||
*/
|
||||
getCurrentMode(): LogMode;
|
||||
/**
|
||||
* Get connection statistics
|
||||
*/
|
||||
getConnectionStats(): IConnectionTracker;
|
||||
/**
|
||||
* Log a message with adaptive behavior
|
||||
*/
|
||||
log(level: LogLevel, message: string, options?: ISmtpLogOptions): void;
|
||||
/**
|
||||
* Log command with adaptive behavior
|
||||
*/
|
||||
logCommand(command: string, socket: plugins.net.Socket | plugins.tls.TLSSocket, session?: ISmtpSession): void;
|
||||
/**
|
||||
* Log response with adaptive behavior
|
||||
*/
|
||||
logResponse(response: string, socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
|
||||
/**
|
||||
* Log connection event with adaptive behavior
|
||||
*/
|
||||
logConnection(socket: plugins.net.Socket | plugins.tls.TLSSocket, eventType: 'connect' | 'close' | 'error', session?: ISmtpSession, error?: Error): void;
|
||||
/**
|
||||
* Log security event (always logged regardless of mode)
|
||||
*/
|
||||
logSecurityEvent(level: SecurityLogLevel, type: SecurityEventType, message: string, details: Record<string, any>, ipAddress?: string, domain?: string, success?: boolean): void;
|
||||
/**
|
||||
* Determine appropriate log mode based on connection count
|
||||
*/
|
||||
private determineLogMode;
|
||||
/**
|
||||
* Switch to a new log mode
|
||||
*/
|
||||
private switchLogMode;
|
||||
/**
|
||||
* Add entry to aggregation buffer
|
||||
*/
|
||||
private aggregateEntry;
|
||||
/**
|
||||
* Start the aggregation timer
|
||||
*/
|
||||
private startAggregationTimer;
|
||||
/**
|
||||
* Flush aggregated entries to logs
|
||||
*/
|
||||
private flushAggregatedEntries;
|
||||
/**
|
||||
* Cleanup resources
|
||||
*/
|
||||
destroy(): void;
|
||||
}
|
||||
/**
|
||||
* Default instance for easy access
|
||||
*/
|
||||
export declare const adaptiveLogger: AdaptiveSmtpLogger;
|
||||
export {};
|
||||
File diff suppressed because one or more lines are too long
@@ -1,78 +0,0 @@
|
||||
/**
|
||||
* SMTP Helper Functions
|
||||
* Provides utility functions for SMTP server implementation
|
||||
*/
|
||||
import * as plugins from '../../../../plugins.js';
|
||||
import type { ISmtpServerOptions } from '../interfaces.js';
|
||||
/**
|
||||
* Formats a multi-line SMTP response according to RFC 5321
|
||||
* @param code - Response code
|
||||
* @param lines - Response lines
|
||||
* @returns Formatted SMTP response
|
||||
*/
|
||||
export declare function formatMultilineResponse(code: number, lines: string[]): string;
|
||||
/**
|
||||
* Generates a unique session ID
|
||||
* @returns Unique session ID
|
||||
*/
|
||||
export declare function generateSessionId(): string;
|
||||
/**
|
||||
* Safely parses an integer from string with a default value
|
||||
* @param value - String value to parse
|
||||
* @param defaultValue - Default value if parsing fails
|
||||
* @returns Parsed integer or default value
|
||||
*/
|
||||
export declare function safeParseInt(value: string | undefined, defaultValue: number): number;
|
||||
/**
|
||||
* Safely gets the socket details
|
||||
* @param socket - Socket to get details from
|
||||
* @returns Socket details object
|
||||
*/
|
||||
export declare function getSocketDetails(socket: plugins.net.Socket | plugins.tls.TLSSocket): {
|
||||
remoteAddress: string;
|
||||
remotePort: number;
|
||||
remoteFamily: string;
|
||||
localAddress: string;
|
||||
localPort: number;
|
||||
encrypted: boolean;
|
||||
};
|
||||
/**
|
||||
* Gets TLS details if socket is TLS
|
||||
* @param socket - Socket to get TLS details from
|
||||
* @returns TLS details or undefined if not TLS
|
||||
*/
|
||||
export declare function getTlsDetails(socket: plugins.net.Socket | plugins.tls.TLSSocket): {
|
||||
protocol?: string;
|
||||
cipher?: string;
|
||||
authorized?: boolean;
|
||||
} | undefined;
|
||||
/**
|
||||
* Merges default options with provided options
|
||||
* @param options - User provided options
|
||||
* @returns Merged options with defaults
|
||||
*/
|
||||
export declare function mergeWithDefaults(options: Partial<ISmtpServerOptions>): ISmtpServerOptions;
|
||||
/**
|
||||
* Creates a text response formatter for the SMTP server
|
||||
* @param socket - Socket to send responses to
|
||||
* @returns Function to send formatted response
|
||||
*/
|
||||
export declare function createResponseFormatter(socket: plugins.net.Socket | plugins.tls.TLSSocket): (response: string) => void;
|
||||
/**
|
||||
* Extracts SMTP command name from a command line
|
||||
* @param commandLine - Full command line
|
||||
* @returns Command name in uppercase
|
||||
*/
|
||||
export declare function extractCommandName(commandLine: string): string;
|
||||
/**
|
||||
* Extracts SMTP command arguments from a command line
|
||||
* @param commandLine - Full command line
|
||||
* @returns Arguments string
|
||||
*/
|
||||
export declare function extractCommandArgs(commandLine: string): string;
|
||||
/**
|
||||
* Sanitizes data for logging (hides sensitive info)
|
||||
* @param data - Data to sanitize
|
||||
* @returns Sanitized data
|
||||
*/
|
||||
export declare function sanitizeForLogging(data: any): any;
|
||||
File diff suppressed because one or more lines are too long
106
dist_ts/mail/delivery/smtpserver/utils/logging.d.ts
vendored
106
dist_ts/mail/delivery/smtpserver/utils/logging.d.ts
vendored
@@ -1,106 +0,0 @@
|
||||
/**
|
||||
* SMTP Logging Utilities
|
||||
* Provides structured logging for SMTP server components
|
||||
*/
|
||||
import * as plugins from '../../../../plugins.js';
|
||||
import { SecurityLogLevel, SecurityEventType } from '../constants.js';
|
||||
import type { ISmtpSession } from '../interfaces.js';
|
||||
/**
|
||||
* SMTP connection metadata to include in logs
|
||||
*/
|
||||
export interface IConnectionMetadata {
|
||||
remoteAddress?: string;
|
||||
remotePort?: number;
|
||||
socketId?: string;
|
||||
secure?: boolean;
|
||||
sessionId?: string;
|
||||
}
|
||||
/**
|
||||
* Log levels for SMTP server
|
||||
*/
|
||||
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
||||
/**
|
||||
* Options for SMTP log
|
||||
*/
|
||||
export interface ISmtpLogOptions {
|
||||
level?: LogLevel;
|
||||
sessionId?: string;
|
||||
sessionState?: string;
|
||||
remoteAddress?: string;
|
||||
remotePort?: number;
|
||||
command?: string;
|
||||
error?: Error;
|
||||
[key: string]: any;
|
||||
}
|
||||
/**
|
||||
* SMTP logger - provides structured logging for SMTP server
|
||||
*/
|
||||
export declare class SmtpLogger {
|
||||
/**
|
||||
* Log a message with context
|
||||
* @param level - Log level
|
||||
* @param message - Log message
|
||||
* @param options - Additional log options
|
||||
*/
|
||||
static log(level: LogLevel, message: string, options?: ISmtpLogOptions): void;
|
||||
/**
|
||||
* Log debug level message
|
||||
* @param message - Log message
|
||||
* @param options - Additional log options
|
||||
*/
|
||||
static debug(message: string, options?: ISmtpLogOptions): void;
|
||||
/**
|
||||
* Log info level message
|
||||
* @param message - Log message
|
||||
* @param options - Additional log options
|
||||
*/
|
||||
static info(message: string, options?: ISmtpLogOptions): void;
|
||||
/**
|
||||
* Log warning level message
|
||||
* @param message - Log message
|
||||
* @param options - Additional log options
|
||||
*/
|
||||
static warn(message: string, options?: ISmtpLogOptions): void;
|
||||
/**
|
||||
* Log error level message
|
||||
* @param message - Log message
|
||||
* @param options - Additional log options
|
||||
*/
|
||||
static error(message: string, options?: ISmtpLogOptions): void;
|
||||
/**
|
||||
* Log command received from client
|
||||
* @param command - The command string
|
||||
* @param socket - The client socket
|
||||
* @param session - The SMTP session
|
||||
*/
|
||||
static logCommand(command: string, socket: plugins.net.Socket | plugins.tls.TLSSocket, session?: ISmtpSession): void;
|
||||
/**
|
||||
* Log response sent to client
|
||||
* @param response - The response string
|
||||
* @param socket - The client socket
|
||||
*/
|
||||
static logResponse(response: string, socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
|
||||
/**
|
||||
* Log client connection event
|
||||
* @param socket - The client socket
|
||||
* @param eventType - Type of connection event (connect, close, error)
|
||||
* @param session - The SMTP session
|
||||
* @param error - Optional error object for error events
|
||||
*/
|
||||
static logConnection(socket: plugins.net.Socket | plugins.tls.TLSSocket, eventType: 'connect' | 'close' | 'error', session?: ISmtpSession, error?: Error): void;
|
||||
/**
|
||||
* Log security event
|
||||
* @param level - Security log level
|
||||
* @param type - Security event type
|
||||
* @param message - Log message
|
||||
* @param details - Event details
|
||||
* @param ipAddress - Client IP address
|
||||
* @param domain - Optional domain involved
|
||||
* @param success - Whether the security check was successful
|
||||
*/
|
||||
static logSecurityEvent(level: SecurityLogLevel, type: SecurityEventType, message: string, details: Record<string, any>, ipAddress?: string, domain?: string, success?: boolean): void;
|
||||
}
|
||||
/**
|
||||
* Default instance for backward compatibility
|
||||
*/
|
||||
export declare const smtpLogger: typeof SmtpLogger;
|
||||
File diff suppressed because one or more lines are too long
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* SMTP Validation Utilities
|
||||
* Provides validation functions for SMTP server
|
||||
*/
|
||||
import { SmtpState } from '../interfaces.js';
|
||||
/**
|
||||
* Detects header injection attempts in input strings
|
||||
* @param input - The input string to check
|
||||
* @param context - The context where this input is being used ('smtp-command' or 'email-header')
|
||||
* @returns true if header injection is detected, false otherwise
|
||||
*/
|
||||
export declare function detectHeaderInjection(input: string, context?: 'smtp-command' | 'email-header'): boolean;
|
||||
/**
|
||||
* Sanitizes input by removing or escaping potentially dangerous characters
|
||||
* @param input - The input string to sanitize
|
||||
* @returns Sanitized string
|
||||
*/
|
||||
export declare function sanitizeInput(input: string): string;
|
||||
/**
|
||||
* Validates an email address
|
||||
* @param email - Email address to validate
|
||||
* @returns Whether the email address is valid
|
||||
*/
|
||||
export declare function isValidEmail(email: string): boolean;
|
||||
/**
|
||||
* Validates the MAIL FROM command syntax
|
||||
* @param args - Arguments string from the MAIL FROM command
|
||||
* @returns Object with validation result and extracted data
|
||||
*/
|
||||
export declare function validateMailFrom(args: string): {
|
||||
isValid: boolean;
|
||||
address?: string;
|
||||
params?: Record<string, string>;
|
||||
errorMessage?: string;
|
||||
};
|
||||
/**
|
||||
* Validates the RCPT TO command syntax
|
||||
* @param args - Arguments string from the RCPT TO command
|
||||
* @returns Object with validation result and extracted data
|
||||
*/
|
||||
export declare function validateRcptTo(args: string): {
|
||||
isValid: boolean;
|
||||
address?: string;
|
||||
params?: Record<string, string>;
|
||||
errorMessage?: string;
|
||||
};
|
||||
/**
|
||||
* Validates the EHLO command syntax
|
||||
* @param args - Arguments string from the EHLO command
|
||||
* @returns Object with validation result and extracted data
|
||||
*/
|
||||
export declare function validateEhlo(args: string): {
|
||||
isValid: boolean;
|
||||
hostname?: string;
|
||||
errorMessage?: string;
|
||||
};
|
||||
/**
|
||||
* Validates command in the current SMTP state
|
||||
* @param command - SMTP command
|
||||
* @param currentState - Current SMTP state
|
||||
* @returns Whether the command is valid in the current state
|
||||
*/
|
||||
export declare function isValidCommandSequence(command: string, currentState: SmtpState): boolean;
|
||||
/**
|
||||
* Validates if a hostname is valid according to RFC 5321
|
||||
* @param hostname - Hostname to validate
|
||||
* @returns Whether the hostname is valid
|
||||
*/
|
||||
export declare function isValidHostname(hostname: string): boolean;
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user