Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 399f5fa418 | |||
| cd4584ec26 |
29
.gitignore
vendored
29
.gitignore
vendored
@@ -1,9 +1,24 @@
|
|||||||
node_modules/
|
|
||||||
.nogit/
|
.nogit/
|
||||||
|
|
||||||
|
# artifacts
|
||||||
|
coverage/
|
||||||
|
public/
|
||||||
|
|
||||||
|
# installs
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# caches
|
||||||
|
.yarn/
|
||||||
|
.cache/
|
||||||
|
.rpt2_cache
|
||||||
|
|
||||||
|
# builds
|
||||||
dist/
|
dist/
|
||||||
dist_rust/
|
dist_*/
|
||||||
rust/target/
|
|
||||||
deno.lock
|
# AI
|
||||||
*.log
|
.claude/
|
||||||
.env
|
.serena/
|
||||||
.DS_Store
|
|
||||||
|
#------# custom
|
||||||
|
rust/target
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 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)
|
## 2026-02-10 - 2.3.0 - feat(mailer-smtp)
|
||||||
add in-process security pipeline for SMTP delivery (DKIM/SPF/DMARC, content scanning, IP reputation)
|
add in-process security pipeline for SMTP delivery (DKIM/SPF/DMARC, content scanning, IP reputation)
|
||||||
|
|
||||||
|
|||||||
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.2.1',
|
|
||||||
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
11
dist_ts/mail/delivery/index.d.ts
vendored
11
dist_ts/mail/delivery/index.d.ts
vendored
@@ -1,11 +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';
|
|
||||||
export { smtpClientMod };
|
|
||||||
@@ -1,17 +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';
|
|
||||||
export { smtpClientMod };
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL2RlbGl2ZXJ5L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDRCQUE0QjtBQUM1QixjQUFjLDJCQUEyQixDQUFDO0FBQzFDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyw4QkFBOEIsQ0FBQztBQUU3Qyx1Q0FBdUM7QUFDdkMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUU5RCw2Q0FBNkM7QUFDN0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBR3ZELHVCQUF1QjtBQUN2QixjQUFjLG1DQUFtQyxDQUFDO0FBRWxELGdDQUFnQztBQUNoQyxjQUFjLHlCQUF5QixDQUFDO0FBRXhDLGtFQUFrRTtBQUNsRSxPQUFPLEtBQUssYUFBYSxNQUFNLHVCQUF1QixDQUFDO0FBRXZELE9BQU8sRUFBRSxhQUFhLEVBQUUsQ0FBQyJ9
|
|
||||||
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
7
dist_ts/mail/index.d.ts
vendored
7
dist_ts/mail/index.d.ts
vendored
@@ -1,7 +0,0 @@
|
|||||||
export * from './routing/index.js';
|
|
||||||
export * from './security/index.js';
|
|
||||||
import * as Core from './core/index.js';
|
|
||||||
import * as Delivery from './delivery/index.js';
|
|
||||||
export { Core, Delivery };
|
|
||||||
import { Email } from './core/classes.email.js';
|
|
||||||
export { Email, };
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
// Export all mail modules for simplified imports
|
|
||||||
export * from './routing/index.js';
|
|
||||||
export * from './security/index.js';
|
|
||||||
// Make the core and delivery modules accessible
|
|
||||||
import * as Core from './core/index.js';
|
|
||||||
import * as Delivery from './delivery/index.js';
|
|
||||||
export { Core, Delivery };
|
|
||||||
// For direct imports
|
|
||||||
import { Email } from './core/classes.email.js';
|
|
||||||
// Re-export commonly used classes
|
|
||||||
export { Email, };
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tYWlsL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGlEQUFpRDtBQUNqRCxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMscUJBQXFCLENBQUM7QUFFcEMsZ0RBQWdEO0FBQ2hELE9BQU8sS0FBSyxJQUFJLE1BQU0saUJBQWlCLENBQUM7QUFDeEMsT0FBTyxLQUFLLFFBQVEsTUFBTSxxQkFBcUIsQ0FBQztBQUVoRCxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDO0FBRTFCLHFCQUFxQjtBQUNyQixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFaEQsa0NBQWtDO0FBQ2xDLE9BQU8sRUFDTCxLQUFLLEdBQ04sQ0FBQyJ9
|
|
||||||
79
dist_ts/mail/routing/classes.dns.manager.d.ts
vendored
79
dist_ts/mail/routing/classes.dns.manager.d.ts
vendored
@@ -1,79 +0,0 @@
|
|||||||
import type { IEmailDomainConfig } from './interfaces.js';
|
|
||||||
/** External DcRouter interface shape used by DnsManager */
|
|
||||||
interface IDcRouterLike {
|
|
||||||
storageManager: IStorageManagerLike;
|
|
||||||
dnsServer?: any;
|
|
||||||
options?: {
|
|
||||||
dnsNsDomains?: string[];
|
|
||||||
dnsScopes?: string[];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/** External StorageManager interface shape used by DnsManager */
|
|
||||||
interface IStorageManagerLike {
|
|
||||||
get(key: string): Promise<string | null>;
|
|
||||||
set(key: string, value: string): Promise<void>;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* DNS validation result
|
|
||||||
*/
|
|
||||||
export interface IDnsValidationResult {
|
|
||||||
valid: boolean;
|
|
||||||
errors: string[];
|
|
||||||
warnings: string[];
|
|
||||||
requiredChanges: string[];
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Manages DNS configuration for email domains
|
|
||||||
* Handles both validation and creation of DNS records
|
|
||||||
*/
|
|
||||||
export declare class DnsManager {
|
|
||||||
private dcRouter;
|
|
||||||
private storageManager;
|
|
||||||
constructor(dcRouter: IDcRouterLike);
|
|
||||||
/**
|
|
||||||
* Validate all domain configurations
|
|
||||||
*/
|
|
||||||
validateAllDomains(domainConfigs: IEmailDomainConfig[]): Promise<Map<string, IDnsValidationResult>>;
|
|
||||||
/**
|
|
||||||
* Validate a single domain configuration
|
|
||||||
*/
|
|
||||||
validateDomain(config: IEmailDomainConfig): Promise<IDnsValidationResult>;
|
|
||||||
/**
|
|
||||||
* Validate forward mode configuration
|
|
||||||
*/
|
|
||||||
private validateForwardMode;
|
|
||||||
/**
|
|
||||||
* Validate internal DNS mode configuration
|
|
||||||
*/
|
|
||||||
private validateInternalDnsMode;
|
|
||||||
/**
|
|
||||||
* Validate external DNS mode configuration
|
|
||||||
*/
|
|
||||||
private validateExternalDnsMode;
|
|
||||||
/**
|
|
||||||
* Check DNS records for a domain
|
|
||||||
*/
|
|
||||||
private checkDnsRecords;
|
|
||||||
/**
|
|
||||||
* Resolve NS records for a domain
|
|
||||||
*/
|
|
||||||
private resolveNs;
|
|
||||||
/**
|
|
||||||
* Get base domain from email domain (e.g., mail.example.com -> example.com)
|
|
||||||
*/
|
|
||||||
private getBaseDomain;
|
|
||||||
/**
|
|
||||||
* Ensure all DNS records are created for configured domains
|
|
||||||
* This is the main entry point for DNS record management
|
|
||||||
*/
|
|
||||||
ensureDnsRecords(domainConfigs: IEmailDomainConfig[], dkimCreator?: any): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Create DNS records for internal-dns mode domains
|
|
||||||
*/
|
|
||||||
private createInternalDnsRecords;
|
|
||||||
/**
|
|
||||||
* Create DKIM DNS records for all domains
|
|
||||||
*/
|
|
||||||
private createDkimRecords;
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
File diff suppressed because one or more lines are too long
165
dist_ts/mail/routing/classes.dnsmanager.d.ts
vendored
165
dist_ts/mail/routing/classes.dnsmanager.d.ts
vendored
@@ -1,165 +0,0 @@
|
|||||||
import * as plugins from '../../plugins.js';
|
|
||||||
import { DKIMCreator } from '../security/classes.dkimcreator.js';
|
|
||||||
/**
|
|
||||||
* Interface for DNS record information
|
|
||||||
*/
|
|
||||||
export interface IDnsRecord {
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
value: string;
|
|
||||||
ttl?: number;
|
|
||||||
dnsSecEnabled?: boolean;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Interface for DNS lookup options
|
|
||||||
*/
|
|
||||||
export interface IDnsLookupOptions {
|
|
||||||
/** Cache time to live in milliseconds, 0 to disable caching */
|
|
||||||
cacheTtl?: number;
|
|
||||||
/** Timeout for DNS queries in milliseconds */
|
|
||||||
timeout?: number;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Interface for DNS verification result
|
|
||||||
*/
|
|
||||||
export interface IDnsVerificationResult {
|
|
||||||
record: string;
|
|
||||||
found: boolean;
|
|
||||||
valid: boolean;
|
|
||||||
value?: string;
|
|
||||||
expectedValue?: string;
|
|
||||||
error?: string;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Manager for DNS-related operations, including record lookups, verification, and generation
|
|
||||||
*/
|
|
||||||
export declare class DNSManager {
|
|
||||||
dkimCreator: DKIMCreator;
|
|
||||||
private cache;
|
|
||||||
private defaultOptions;
|
|
||||||
constructor(dkimCreatorArg: DKIMCreator, options?: IDnsLookupOptions);
|
|
||||||
/**
|
|
||||||
* Lookup MX records for a domain
|
|
||||||
* @param domain Domain to look up
|
|
||||||
* @param options Lookup options
|
|
||||||
* @returns Array of MX records sorted by priority
|
|
||||||
*/
|
|
||||||
lookupMx(domain: string, options?: IDnsLookupOptions): Promise<plugins.dns.MxRecord[]>;
|
|
||||||
/**
|
|
||||||
* Lookup TXT records for a domain
|
|
||||||
* @param domain Domain to look up
|
|
||||||
* @param options Lookup options
|
|
||||||
* @returns Array of TXT records
|
|
||||||
*/
|
|
||||||
lookupTxt(domain: string, options?: IDnsLookupOptions): Promise<string[][]>;
|
|
||||||
/**
|
|
||||||
* Find specific TXT record by subdomain and prefix
|
|
||||||
* @param domain Base domain
|
|
||||||
* @param subdomain Subdomain prefix (e.g., "dkim._domainkey")
|
|
||||||
* @param prefix Record prefix to match (e.g., "v=DKIM1")
|
|
||||||
* @param options Lookup options
|
|
||||||
* @returns Matching TXT record or null if not found
|
|
||||||
*/
|
|
||||||
findTxtRecord(domain: string, subdomain?: string, prefix?: string, options?: IDnsLookupOptions): Promise<string | null>;
|
|
||||||
/**
|
|
||||||
* Verify if a domain has a valid SPF record
|
|
||||||
* @param domain Domain to verify
|
|
||||||
* @returns Verification result
|
|
||||||
*/
|
|
||||||
verifySpfRecord(domain: string): Promise<IDnsVerificationResult>;
|
|
||||||
/**
|
|
||||||
* Verify if a domain has a valid DKIM record
|
|
||||||
* @param domain Domain to verify
|
|
||||||
* @param selector DKIM selector (usually "mta" in our case)
|
|
||||||
* @returns Verification result
|
|
||||||
*/
|
|
||||||
verifyDkimRecord(domain: string, selector?: string): Promise<IDnsVerificationResult>;
|
|
||||||
/**
|
|
||||||
* Verify if a domain has a valid DMARC record
|
|
||||||
* @param domain Domain to verify
|
|
||||||
* @returns Verification result
|
|
||||||
*/
|
|
||||||
verifyDmarcRecord(domain: string): Promise<IDnsVerificationResult>;
|
|
||||||
/**
|
|
||||||
* Check all email authentication records (SPF, DKIM, DMARC) for a domain
|
|
||||||
* @param domain Domain to check
|
|
||||||
* @param dkimSelector DKIM selector
|
|
||||||
* @returns Object with verification results for each record type
|
|
||||||
*/
|
|
||||||
verifyEmailAuthRecords(domain: string, dkimSelector?: string): Promise<{
|
|
||||||
spf: IDnsVerificationResult;
|
|
||||||
dkim: IDnsVerificationResult;
|
|
||||||
dmarc: IDnsVerificationResult;
|
|
||||||
}>;
|
|
||||||
/**
|
|
||||||
* Generate a recommended SPF record for a domain
|
|
||||||
* @param domain Domain name
|
|
||||||
* @param options Configuration options for the SPF record
|
|
||||||
* @returns Generated SPF record
|
|
||||||
*/
|
|
||||||
generateSpfRecord(domain: string, options?: {
|
|
||||||
includeMx?: boolean;
|
|
||||||
includeA?: boolean;
|
|
||||||
includeIps?: string[];
|
|
||||||
includeSpf?: string[];
|
|
||||||
policy?: 'none' | 'neutral' | 'softfail' | 'fail' | 'reject';
|
|
||||||
}): IDnsRecord;
|
|
||||||
/**
|
|
||||||
* Generate a recommended DMARC record for a domain
|
|
||||||
* @param domain Domain name
|
|
||||||
* @param options Configuration options for the DMARC record
|
|
||||||
* @returns Generated DMARC record
|
|
||||||
*/
|
|
||||||
generateDmarcRecord(domain: string, options?: {
|
|
||||||
policy?: 'none' | 'quarantine' | 'reject';
|
|
||||||
subdomainPolicy?: 'none' | 'quarantine' | 'reject';
|
|
||||||
pct?: number;
|
|
||||||
rua?: string;
|
|
||||||
ruf?: string;
|
|
||||||
daysInterval?: number;
|
|
||||||
}): IDnsRecord;
|
|
||||||
/**
|
|
||||||
* Save DNS record recommendations to a file
|
|
||||||
* @param domain Domain name
|
|
||||||
* @param records DNS records to save
|
|
||||||
*/
|
|
||||||
saveDnsRecommendations(domain: string, records: IDnsRecord[]): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Get cache key value
|
|
||||||
* @param key Cache key
|
|
||||||
* @returns Cached value or undefined if not found or expired
|
|
||||||
*/
|
|
||||||
private getFromCache;
|
|
||||||
/**
|
|
||||||
* Set cache key value
|
|
||||||
* @param key Cache key
|
|
||||||
* @param data Data to cache
|
|
||||||
* @param ttl TTL in milliseconds
|
|
||||||
*/
|
|
||||||
private setInCache;
|
|
||||||
/**
|
|
||||||
* Clear the DNS cache
|
|
||||||
* @param key Optional specific key to clear, or all cache if not provided
|
|
||||||
*/
|
|
||||||
clearCache(key?: string): void;
|
|
||||||
/**
|
|
||||||
* Promise-based wrapper for dns.resolveMx
|
|
||||||
* @param domain Domain to resolve
|
|
||||||
* @param timeout Timeout in milliseconds
|
|
||||||
* @returns Promise resolving to MX records
|
|
||||||
*/
|
|
||||||
private dnsResolveMx;
|
|
||||||
/**
|
|
||||||
* Promise-based wrapper for dns.resolveTxt
|
|
||||||
* @param domain Domain to resolve
|
|
||||||
* @param timeout Timeout in milliseconds
|
|
||||||
* @returns Promise resolving to TXT records
|
|
||||||
*/
|
|
||||||
private dnsResolveTxt;
|
|
||||||
/**
|
|
||||||
* Generate all recommended DNS records for proper email authentication
|
|
||||||
* @param domain Domain to generate records for
|
|
||||||
* @returns Array of recommended DNS records
|
|
||||||
*/
|
|
||||||
generateAllRecommendedRecords(domain: string): Promise<IDnsRecord[]>;
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,54 +0,0 @@
|
|||||||
import type { IEmailDomainConfig } from './interfaces.js';
|
|
||||||
/**
|
|
||||||
* Registry for email domain configurations
|
|
||||||
* Provides fast lookups and validation for domains
|
|
||||||
*/
|
|
||||||
export declare class DomainRegistry {
|
|
||||||
private domains;
|
|
||||||
private defaults;
|
|
||||||
constructor(domainConfigs: IEmailDomainConfig[], defaults?: {
|
|
||||||
dnsMode?: 'forward' | 'internal-dns' | 'external-dns';
|
|
||||||
dkim?: IEmailDomainConfig['dkim'];
|
|
||||||
rateLimits?: IEmailDomainConfig['rateLimits'];
|
|
||||||
});
|
|
||||||
/**
|
|
||||||
* Get default DKIM configuration
|
|
||||||
*/
|
|
||||||
private getDefaultDkimConfig;
|
|
||||||
/**
|
|
||||||
* Apply defaults to a domain configuration
|
|
||||||
*/
|
|
||||||
private applyDefaults;
|
|
||||||
/**
|
|
||||||
* Check if a domain is registered
|
|
||||||
*/
|
|
||||||
isDomainRegistered(domain: string): boolean;
|
|
||||||
/**
|
|
||||||
* Check if an email address belongs to a registered domain
|
|
||||||
*/
|
|
||||||
isEmailRegistered(email: string): boolean;
|
|
||||||
/**
|
|
||||||
* Get domain configuration
|
|
||||||
*/
|
|
||||||
getDomainConfig(domain: string): IEmailDomainConfig | undefined;
|
|
||||||
/**
|
|
||||||
* Get domain configuration for an email address
|
|
||||||
*/
|
|
||||||
getEmailDomainConfig(email: string): IEmailDomainConfig | undefined;
|
|
||||||
/**
|
|
||||||
* Extract domain from email address
|
|
||||||
*/
|
|
||||||
private extractDomain;
|
|
||||||
/**
|
|
||||||
* Get all registered domains
|
|
||||||
*/
|
|
||||||
getAllDomains(): string[];
|
|
||||||
/**
|
|
||||||
* Get all domain configurations
|
|
||||||
*/
|
|
||||||
getAllConfigs(): IEmailDomainConfig[];
|
|
||||||
/**
|
|
||||||
* Get domains by DNS mode
|
|
||||||
*/
|
|
||||||
getDomainsByMode(mode: 'forward' | 'internal-dns' | 'external-dns'): IEmailDomainConfig[];
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
import { logger } from '../../logger.js';
|
|
||||||
/**
|
|
||||||
* Registry for email domain configurations
|
|
||||||
* Provides fast lookups and validation for domains
|
|
||||||
*/
|
|
||||||
export class DomainRegistry {
|
|
||||||
domains = new Map();
|
|
||||||
defaults;
|
|
||||||
constructor(domainConfigs, defaults) {
|
|
||||||
// Set defaults
|
|
||||||
this.defaults = {
|
|
||||||
dnsMode: defaults?.dnsMode || 'external-dns',
|
|
||||||
...this.getDefaultDkimConfig(),
|
|
||||||
...defaults?.dkim,
|
|
||||||
rateLimits: defaults?.rateLimits
|
|
||||||
};
|
|
||||||
// Process and store domain configurations
|
|
||||||
for (const config of domainConfigs) {
|
|
||||||
const processedConfig = this.applyDefaults(config);
|
|
||||||
this.domains.set(config.domain.toLowerCase(), processedConfig);
|
|
||||||
logger.log('info', `Registered domain: ${config.domain} with DNS mode: ${processedConfig.dnsMode}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get default DKIM configuration
|
|
||||||
*/
|
|
||||||
getDefaultDkimConfig() {
|
|
||||||
return {
|
|
||||||
selector: 'default',
|
|
||||||
keySize: 2048,
|
|
||||||
rotateKeys: false,
|
|
||||||
rotationInterval: 90
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Apply defaults to a domain configuration
|
|
||||||
*/
|
|
||||||
applyDefaults(config) {
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
dnsMode: config.dnsMode || this.defaults.dnsMode,
|
|
||||||
dkim: {
|
|
||||||
...this.getDefaultDkimConfig(),
|
|
||||||
...this.defaults,
|
|
||||||
...config.dkim
|
|
||||||
},
|
|
||||||
rateLimits: {
|
|
||||||
...this.defaults.rateLimits,
|
|
||||||
...config.rateLimits,
|
|
||||||
outbound: {
|
|
||||||
...this.defaults.rateLimits?.outbound,
|
|
||||||
...config.rateLimits?.outbound
|
|
||||||
},
|
|
||||||
inbound: {
|
|
||||||
...this.defaults.rateLimits?.inbound,
|
|
||||||
...config.rateLimits?.inbound
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Check if a domain is registered
|
|
||||||
*/
|
|
||||||
isDomainRegistered(domain) {
|
|
||||||
return this.domains.has(domain.toLowerCase());
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Check if an email address belongs to a registered domain
|
|
||||||
*/
|
|
||||||
isEmailRegistered(email) {
|
|
||||||
const domain = this.extractDomain(email);
|
|
||||||
if (!domain)
|
|
||||||
return false;
|
|
||||||
return this.isDomainRegistered(domain);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get domain configuration
|
|
||||||
*/
|
|
||||||
getDomainConfig(domain) {
|
|
||||||
return this.domains.get(domain.toLowerCase());
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get domain configuration for an email address
|
|
||||||
*/
|
|
||||||
getEmailDomainConfig(email) {
|
|
||||||
const domain = this.extractDomain(email);
|
|
||||||
if (!domain)
|
|
||||||
return undefined;
|
|
||||||
return this.getDomainConfig(domain);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Extract domain from email address
|
|
||||||
*/
|
|
||||||
extractDomain(email) {
|
|
||||||
const parts = email.toLowerCase().split('@');
|
|
||||||
if (parts.length !== 2)
|
|
||||||
return null;
|
|
||||||
return parts[1];
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get all registered domains
|
|
||||||
*/
|
|
||||||
getAllDomains() {
|
|
||||||
return Array.from(this.domains.keys());
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get all domain configurations
|
|
||||||
*/
|
|
||||||
getAllConfigs() {
|
|
||||||
return Array.from(this.domains.values());
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get domains by DNS mode
|
|
||||||
*/
|
|
||||||
getDomainsByMode(mode) {
|
|
||||||
return Array.from(this.domains.values()).filter(config => config.dnsMode === mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kb21haW4ucmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL3JvdXRpbmcvY2xhc3Nlcy5kb21haW4ucmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXpDOzs7R0FHRztBQUNILE1BQU0sT0FBTyxjQUFjO0lBQ2pCLE9BQU8sR0FBb0MsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNyRCxRQUFRLENBR2Q7SUFFRixZQUNFLGFBQW1DLEVBQ25DLFFBSUM7UUFFRCxlQUFlO1FBQ2YsSUFBSSxDQUFDLFFBQVEsR0FBRztZQUNkLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxJQUFJLGNBQWM7WUFDNUMsR0FBRyxJQUFJLENBQUMsb0JBQW9CLEVBQUU7WUFDOUIsR0FBRyxRQUFRLEVBQUUsSUFBSTtZQUNqQixVQUFVLEVBQUUsUUFBUSxFQUFFLFVBQVU7U0FDakMsQ0FBQztRQUVGLDBDQUEwQztRQUMxQyxLQUFLLE1BQU0sTUFBTSxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ25DLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbkQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFBRSxlQUFlLENBQUMsQ0FBQztZQUMvRCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxzQkFBc0IsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLGVBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3RHLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxvQkFBb0I7UUFDMUIsT0FBTztZQUNMLFFBQVEsRUFBRSxTQUFTO1lBQ25CLE9BQU8sRUFBRSxJQUFJO1lBQ2IsVUFBVSxFQUFFLEtBQUs7WUFDakIsZ0JBQWdCLEVBQUUsRUFBRTtTQUNyQixDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ssYUFBYSxDQUFDLE1BQTBCO1FBQzlDLE9BQU87WUFDTCxHQUFHLE1BQU07WUFDVCxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQVE7WUFDakQsSUFBSSxFQUFFO2dCQUNKLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixFQUFFO2dCQUM5QixHQUFHLElBQUksQ0FBQyxRQUFRO2dCQUNoQixHQUFHLE1BQU0sQ0FBQyxJQUFJO2FBQ2Y7WUFDRCxVQUFVLEVBQUU7Z0JBQ1YsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVU7Z0JBQzNCLEdBQUcsTUFBTSxDQUFDLFVBQVU7Z0JBQ3BCLFFBQVEsRUFBRTtvQkFDUixHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLFFBQVE7b0JBQ3JDLEdBQUcsTUFBTSxDQUFDLFVBQVUsRUFBRSxRQUFRO2lCQUMvQjtnQkFDRCxPQUFPLEVBQUU7b0JBQ1AsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxPQUFPO29CQUNwQyxHQUFHLE1BQU0sQ0FBQyxVQUFVLEVBQUUsT0FBTztpQkFDOUI7YUFDRjtTQUNGLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxrQkFBa0IsQ0FBQyxNQUFjO1FBQy9CLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsaUJBQWlCLENBQUMsS0FBYTtRQUM3QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFDMUIsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsZUFBZSxDQUFDLE1BQWM7UUFDNUIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxvQkFBb0IsQ0FBQyxLQUFhO1FBQ2hDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLFNBQVMsQ0FBQztRQUM5QixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVEOztPQUVHO0lBQ0ssYUFBYSxDQUFDLEtBQWE7UUFDakMsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM3QyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ3BDLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7T0FFRztJQUNILGFBQWE7UUFDWCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRDs7T0FFRztJQUNILGFBQWE7UUFDWCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRDs7T0FFRztJQUNILGdCQUFnQixDQUFDLElBQWlEO1FBQ2hFLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sS0FBSyxJQUFJLENBQUMsQ0FBQztJQUNyRixDQUFDO0NBQ0YifQ==
|
|
||||||
64
dist_ts/mail/routing/classes.email.config.d.ts
vendored
64
dist_ts/mail/routing/classes.email.config.d.ts
vendored
@@ -1,64 +0,0 @@
|
|||||||
import type { EmailProcessingMode } from '../delivery/interfaces.js';
|
|
||||||
export type { EmailProcessingMode };
|
|
||||||
/**
|
|
||||||
* Domain rule interface for pattern-based routing
|
|
||||||
*/
|
|
||||||
export interface IDomainRule {
|
|
||||||
pattern: string;
|
|
||||||
mode: EmailProcessingMode;
|
|
||||||
target?: {
|
|
||||||
server: string;
|
|
||||||
port?: number;
|
|
||||||
useTls?: boolean;
|
|
||||||
authentication?: {
|
|
||||||
user?: string;
|
|
||||||
pass?: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
mtaOptions?: IMtaOptions;
|
|
||||||
contentScanning?: boolean;
|
|
||||||
scanners?: IContentScanner[];
|
|
||||||
transformations?: ITransformation[];
|
|
||||||
rateLimits?: {
|
|
||||||
maxMessagesPerMinute?: number;
|
|
||||||
maxRecipientsPerMessage?: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* MTA options interface
|
|
||||||
*/
|
|
||||||
export interface IMtaOptions {
|
|
||||||
domain?: string;
|
|
||||||
allowLocalDelivery?: boolean;
|
|
||||||
localDeliveryPath?: string;
|
|
||||||
dkimSign?: boolean;
|
|
||||||
dkimOptions?: {
|
|
||||||
domainName: string;
|
|
||||||
keySelector: string;
|
|
||||||
privateKey?: string;
|
|
||||||
};
|
|
||||||
smtpBanner?: string;
|
|
||||||
maxConnections?: number;
|
|
||||||
connTimeout?: number;
|
|
||||||
spoolDir?: string;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Content scanner interface
|
|
||||||
*/
|
|
||||||
export interface IContentScanner {
|
|
||||||
type: 'spam' | 'virus' | 'attachment';
|
|
||||||
threshold?: number;
|
|
||||||
action: 'tag' | 'reject';
|
|
||||||
blockedExtensions?: string[];
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Transformation interface
|
|
||||||
*/
|
|
||||||
export interface ITransformation {
|
|
||||||
type: string;
|
|
||||||
header?: string;
|
|
||||||
value?: string;
|
|
||||||
domains?: string[];
|
|
||||||
append?: boolean;
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export {};
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5lbWFpbC5jb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL3JvdXRpbmcvY2xhc3Nlcy5lbWFpbC5jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
|
|
||||||
171
dist_ts/mail/routing/classes.email.router.d.ts
vendored
171
dist_ts/mail/routing/classes.email.router.d.ts
vendored
@@ -1,171 +0,0 @@
|
|||||||
import { EventEmitter } from 'node:events';
|
|
||||||
import type { IEmailRoute, IEmailContext } from './interfaces.js';
|
|
||||||
/**
|
|
||||||
* Email router that evaluates routes and determines actions
|
|
||||||
*/
|
|
||||||
export declare class EmailRouter extends EventEmitter {
|
|
||||||
private routes;
|
|
||||||
private patternCache;
|
|
||||||
private storageManager?;
|
|
||||||
private persistChanges;
|
|
||||||
/**
|
|
||||||
* Create a new email router
|
|
||||||
* @param routes Array of email routes
|
|
||||||
* @param options Router options
|
|
||||||
*/
|
|
||||||
constructor(routes: IEmailRoute[], options?: {
|
|
||||||
storageManager?: any;
|
|
||||||
persistChanges?: boolean;
|
|
||||||
});
|
|
||||||
/**
|
|
||||||
* Sort routes by priority (higher priority first)
|
|
||||||
* @param routes Routes to sort
|
|
||||||
* @returns Sorted routes
|
|
||||||
*/
|
|
||||||
private sortRoutesByPriority;
|
|
||||||
/**
|
|
||||||
* Get all configured routes
|
|
||||||
* @returns Array of routes
|
|
||||||
*/
|
|
||||||
getRoutes(): IEmailRoute[];
|
|
||||||
/**
|
|
||||||
* Update routes
|
|
||||||
* @param routes New routes
|
|
||||||
* @param persist Whether to persist changes (defaults to persistChanges setting)
|
|
||||||
*/
|
|
||||||
updateRoutes(routes: IEmailRoute[], persist?: boolean): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Set routes (alias for updateRoutes)
|
|
||||||
* @param routes New routes
|
|
||||||
* @param persist Whether to persist changes
|
|
||||||
*/
|
|
||||||
setRoutes(routes: IEmailRoute[], persist?: boolean): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Clear the pattern cache
|
|
||||||
*/
|
|
||||||
clearCache(): void;
|
|
||||||
/**
|
|
||||||
* Evaluate routes and find the first match
|
|
||||||
* @param context Email context
|
|
||||||
* @returns Matched route or null
|
|
||||||
*/
|
|
||||||
evaluateRoutes(context: IEmailContext): Promise<IEmailRoute | null>;
|
|
||||||
/**
|
|
||||||
* Check if a route matches the context
|
|
||||||
* @param route Route to check
|
|
||||||
* @param context Email context
|
|
||||||
* @returns True if route matches
|
|
||||||
*/
|
|
||||||
private matchesRoute;
|
|
||||||
/**
|
|
||||||
* Check if email recipients match patterns
|
|
||||||
* @param email Email to check
|
|
||||||
* @param patterns Patterns to match
|
|
||||||
* @returns True if any recipient matches
|
|
||||||
*/
|
|
||||||
private matchesRecipients;
|
|
||||||
/**
|
|
||||||
* Check if email sender matches patterns
|
|
||||||
* @param email Email to check
|
|
||||||
* @param patterns Patterns to match
|
|
||||||
* @returns True if sender matches
|
|
||||||
*/
|
|
||||||
private matchesSenders;
|
|
||||||
/**
|
|
||||||
* Check if client IP matches patterns
|
|
||||||
* @param context Email context
|
|
||||||
* @param patterns IP patterns to match
|
|
||||||
* @returns True if IP matches
|
|
||||||
*/
|
|
||||||
private matchesClientIp;
|
|
||||||
/**
|
|
||||||
* Check if email headers match patterns
|
|
||||||
* @param email Email to check
|
|
||||||
* @param headerPatterns Header patterns to match
|
|
||||||
* @returns True if headers match
|
|
||||||
*/
|
|
||||||
private matchesHeaders;
|
|
||||||
/**
|
|
||||||
* Check if email size matches range
|
|
||||||
* @param email Email to check
|
|
||||||
* @param sizeRange Size range to match
|
|
||||||
* @returns True if size is in range
|
|
||||||
*/
|
|
||||||
private matchesSize;
|
|
||||||
/**
|
|
||||||
* Check if email subject matches pattern
|
|
||||||
* @param email Email to check
|
|
||||||
* @param pattern Pattern to match
|
|
||||||
* @returns True if subject matches
|
|
||||||
*/
|
|
||||||
private matchesSubject;
|
|
||||||
/**
|
|
||||||
* Check if a string matches a glob pattern
|
|
||||||
* @param str String to check
|
|
||||||
* @param pattern Glob pattern
|
|
||||||
* @returns True if matches
|
|
||||||
*/
|
|
||||||
private matchesPattern;
|
|
||||||
/**
|
|
||||||
* Convert glob pattern to RegExp
|
|
||||||
* @param pattern Glob pattern
|
|
||||||
* @returns Regular expression
|
|
||||||
*/
|
|
||||||
private globToRegExp;
|
|
||||||
/**
|
|
||||||
* Check if IP is in CIDR range
|
|
||||||
* @param ip IP address to check
|
|
||||||
* @param cidr CIDR notation (e.g., '192.168.0.0/16')
|
|
||||||
* @returns True if IP is in range
|
|
||||||
*/
|
|
||||||
private ipInCidr;
|
|
||||||
/**
|
|
||||||
* Convert IP address to number
|
|
||||||
* @param ip IP address
|
|
||||||
* @returns Number representation
|
|
||||||
*/
|
|
||||||
private ipToNumber;
|
|
||||||
/**
|
|
||||||
* Calculate approximate email size in bytes
|
|
||||||
* @param email Email to measure
|
|
||||||
* @returns Size in bytes
|
|
||||||
*/
|
|
||||||
private calculateEmailSize;
|
|
||||||
/**
|
|
||||||
* Save current routes to storage
|
|
||||||
*/
|
|
||||||
saveRoutes(): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Load routes from storage
|
|
||||||
* @param options Load options
|
|
||||||
*/
|
|
||||||
loadRoutes(options?: {
|
|
||||||
merge?: boolean;
|
|
||||||
replace?: boolean;
|
|
||||||
}): Promise<IEmailRoute[]>;
|
|
||||||
/**
|
|
||||||
* Add a route
|
|
||||||
* @param route Route to add
|
|
||||||
* @param persist Whether to persist changes
|
|
||||||
*/
|
|
||||||
addRoute(route: IEmailRoute, persist?: boolean): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Remove a route by name
|
|
||||||
* @param name Route name
|
|
||||||
* @param persist Whether to persist changes
|
|
||||||
*/
|
|
||||||
removeRoute(name: string, persist?: boolean): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Update a route
|
|
||||||
* @param name Route name
|
|
||||||
* @param route Updated route data
|
|
||||||
* @param persist Whether to persist changes
|
|
||||||
*/
|
|
||||||
updateRoute(name: string, route: IEmailRoute, persist?: boolean): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Get a route by name
|
|
||||||
* @param name Route name
|
|
||||||
* @returns Route or undefined
|
|
||||||
*/
|
|
||||||
getRoute(name: string): IEmailRoute | undefined;
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,451 +0,0 @@
|
|||||||
import { EventEmitter } from 'events';
|
|
||||||
import { DKIMCreator } from '../security/classes.dkimcreator.js';
|
|
||||||
interface IIPWarmupConfig {
|
|
||||||
enabled?: boolean;
|
|
||||||
ips?: string[];
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
interface IReputationMonitorConfig {
|
|
||||||
enabled?: boolean;
|
|
||||||
domains?: string[];
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
import type { IEmailRoute, IEmailDomainConfig } from './interfaces.js';
|
|
||||||
import { Email } from '../core/classes.email.js';
|
|
||||||
import { DomainRegistry } from './classes.domain.registry.js';
|
|
||||||
import { BounceType, BounceCategory } from '../core/classes.bouncemanager.js';
|
|
||||||
import type { SmtpClient } from '../delivery/smtpclient/smtp-client.js';
|
|
||||||
import { MultiModeDeliverySystem } from '../delivery/classes.delivery.system.js';
|
|
||||||
import { UnifiedDeliveryQueue } from '../delivery/classes.delivery.queue.js';
|
|
||||||
import { UnifiedRateLimiter, type IHierarchicalRateLimits } from '../delivery/classes.unified.rate.limiter.js';
|
|
||||||
import type { EmailProcessingMode, ISmtpSession as IBaseSmtpSession } from '../delivery/interfaces.js';
|
|
||||||
/** External DcRouter interface shape used by UnifiedEmailServer */
|
|
||||||
interface DcRouter {
|
|
||||||
storageManager: any;
|
|
||||||
dnsServer?: any;
|
|
||||||
options?: any;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Extended SMTP session interface with route information
|
|
||||||
*/
|
|
||||||
export interface IExtendedSmtpSession extends ISmtpSession {
|
|
||||||
/**
|
|
||||||
* Matched route for this session
|
|
||||||
*/
|
|
||||||
matchedRoute?: IEmailRoute;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Options for the unified email server
|
|
||||||
*/
|
|
||||||
export interface IUnifiedEmailServerOptions {
|
|
||||||
ports: number[];
|
|
||||||
hostname: string;
|
|
||||||
domains: IEmailDomainConfig[];
|
|
||||||
banner?: string;
|
|
||||||
debug?: boolean;
|
|
||||||
useSocketHandler?: boolean;
|
|
||||||
auth?: {
|
|
||||||
required?: boolean;
|
|
||||||
methods?: ('PLAIN' | 'LOGIN' | 'OAUTH2')[];
|
|
||||||
users?: Array<{
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
}>;
|
|
||||||
};
|
|
||||||
tls?: {
|
|
||||||
certPath?: string;
|
|
||||||
keyPath?: string;
|
|
||||||
caPath?: string;
|
|
||||||
minVersion?: string;
|
|
||||||
ciphers?: string;
|
|
||||||
};
|
|
||||||
maxMessageSize?: number;
|
|
||||||
maxClients?: number;
|
|
||||||
maxConnections?: number;
|
|
||||||
connectionTimeout?: number;
|
|
||||||
socketTimeout?: number;
|
|
||||||
routes: IEmailRoute[];
|
|
||||||
defaults?: {
|
|
||||||
dnsMode?: 'forward' | 'internal-dns' | 'external-dns';
|
|
||||||
dkim?: IEmailDomainConfig['dkim'];
|
|
||||||
rateLimits?: IEmailDomainConfig['rateLimits'];
|
|
||||||
};
|
|
||||||
outbound?: {
|
|
||||||
maxConnections?: number;
|
|
||||||
connectionTimeout?: number;
|
|
||||||
socketTimeout?: number;
|
|
||||||
retryAttempts?: number;
|
|
||||||
defaultFrom?: string;
|
|
||||||
};
|
|
||||||
rateLimits?: IHierarchicalRateLimits;
|
|
||||||
ipWarmupConfig?: IIPWarmupConfig;
|
|
||||||
reputationMonitorConfig?: IReputationMonitorConfig;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Extended SMTP session interface for UnifiedEmailServer
|
|
||||||
*/
|
|
||||||
export interface ISmtpSession extends IBaseSmtpSession {
|
|
||||||
/**
|
|
||||||
* User information if authenticated
|
|
||||||
*/
|
|
||||||
user?: {
|
|
||||||
username: string;
|
|
||||||
[key: string]: any;
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Matched route for this session
|
|
||||||
*/
|
|
||||||
matchedRoute?: IEmailRoute;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Authentication data for SMTP
|
|
||||||
*/
|
|
||||||
import type { ISmtpAuth } from '../delivery/interfaces.js';
|
|
||||||
export type IAuthData = ISmtpAuth;
|
|
||||||
/**
|
|
||||||
* Server statistics
|
|
||||||
*/
|
|
||||||
export interface IServerStats {
|
|
||||||
startTime: Date;
|
|
||||||
connections: {
|
|
||||||
current: number;
|
|
||||||
total: number;
|
|
||||||
};
|
|
||||||
messages: {
|
|
||||||
processed: number;
|
|
||||||
delivered: number;
|
|
||||||
failed: number;
|
|
||||||
};
|
|
||||||
processingTime: {
|
|
||||||
avg: number;
|
|
||||||
max: number;
|
|
||||||
min: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Unified email server that handles all email traffic with pattern-based routing
|
|
||||||
*/
|
|
||||||
export declare class UnifiedEmailServer extends EventEmitter {
|
|
||||||
private dcRouter;
|
|
||||||
private options;
|
|
||||||
private emailRouter;
|
|
||||||
domainRegistry: DomainRegistry;
|
|
||||||
private servers;
|
|
||||||
private stats;
|
|
||||||
dkimCreator: DKIMCreator;
|
|
||||||
private rustBridge;
|
|
||||||
private ipReputationChecker;
|
|
||||||
private bounceManager;
|
|
||||||
private ipWarmupManager;
|
|
||||||
private senderReputationMonitor;
|
|
||||||
deliveryQueue: UnifiedDeliveryQueue;
|
|
||||||
deliverySystem: MultiModeDeliverySystem;
|
|
||||||
private rateLimiter;
|
|
||||||
private dkimKeys;
|
|
||||||
private smtpClients;
|
|
||||||
constructor(dcRouter: DcRouter, options: IUnifiedEmailServerOptions);
|
|
||||||
/**
|
|
||||||
* Get or create an SMTP client for the given host and port
|
|
||||||
* Uses connection pooling for efficiency
|
|
||||||
*/
|
|
||||||
getSmtpClient(host: string, port?: number): SmtpClient;
|
|
||||||
/**
|
|
||||||
* Start the unified email server
|
|
||||||
*/
|
|
||||||
start(): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Stop the unified email server
|
|
||||||
*/
|
|
||||||
stop(): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Handle an emailReceived event from the Rust SMTP server.
|
|
||||||
* Decodes the email data, processes it through the routing system,
|
|
||||||
* and sends back the result via the correlation-ID callback.
|
|
||||||
*/
|
|
||||||
private handleRustEmailReceived;
|
|
||||||
/**
|
|
||||||
* Handle an authRequest event from the Rust SMTP server.
|
|
||||||
* Validates credentials and sends back the result.
|
|
||||||
*/
|
|
||||||
private handleRustAuthRequest;
|
|
||||||
/**
|
|
||||||
* Verify inbound email security (DKIM/SPF/DMARC) using pre-computed Rust results
|
|
||||||
* or falling back to IPC call if no pre-computed results are available.
|
|
||||||
*/
|
|
||||||
private verifyInboundSecurity;
|
|
||||||
/**
|
|
||||||
* Process email based on routing rules
|
|
||||||
*/
|
|
||||||
processEmailByMode(emailData: Email | Buffer, session: IExtendedSmtpSession): Promise<Email>;
|
|
||||||
/**
|
|
||||||
* Execute action based on route configuration
|
|
||||||
*/
|
|
||||||
private executeAction;
|
|
||||||
/**
|
|
||||||
* Handle forward action
|
|
||||||
*/
|
|
||||||
private handleForwardAction;
|
|
||||||
/**
|
|
||||||
* Handle process action
|
|
||||||
*/
|
|
||||||
private handleProcessAction;
|
|
||||||
/**
|
|
||||||
* Handle deliver action
|
|
||||||
*/
|
|
||||||
private handleDeliverAction;
|
|
||||||
/**
|
|
||||||
* Handle reject action
|
|
||||||
*/
|
|
||||||
private handleRejectAction;
|
|
||||||
/**
|
|
||||||
* Handle email in MTA mode (programmatic processing)
|
|
||||||
*/
|
|
||||||
private _handleMtaMode;
|
|
||||||
/**
|
|
||||||
* Handle email in process mode (store-and-forward with scanning)
|
|
||||||
*/
|
|
||||||
private _handleProcessMode;
|
|
||||||
/**
|
|
||||||
* Get file extension from filename
|
|
||||||
*/
|
|
||||||
private getFileExtension;
|
|
||||||
/**
|
|
||||||
* Set up DKIM configuration for all domains
|
|
||||||
*/
|
|
||||||
private setupDkimForDomains;
|
|
||||||
/**
|
|
||||||
* Apply per-domain rate limits from domain configurations
|
|
||||||
*/
|
|
||||||
private applyDomainRateLimits;
|
|
||||||
/**
|
|
||||||
* Check and rotate DKIM keys if needed
|
|
||||||
*/
|
|
||||||
private checkAndRotateDkimKeys;
|
|
||||||
/**
|
|
||||||
* Generate SmartProxy routes for email ports
|
|
||||||
*/
|
|
||||||
generateProxyRoutes(portMapping?: Record<number, number>): any[];
|
|
||||||
/**
|
|
||||||
* Update server configuration
|
|
||||||
*/
|
|
||||||
updateOptions(options: Partial<IUnifiedEmailServerOptions>): void;
|
|
||||||
/**
|
|
||||||
* Update email routes
|
|
||||||
*/
|
|
||||||
updateEmailRoutes(routes: IEmailRoute[]): void;
|
|
||||||
/**
|
|
||||||
* Get server statistics
|
|
||||||
*/
|
|
||||||
getStats(): IServerStats;
|
|
||||||
/**
|
|
||||||
* Get domain registry
|
|
||||||
*/
|
|
||||||
getDomainRegistry(): DomainRegistry;
|
|
||||||
/**
|
|
||||||
* Update email routes dynamically
|
|
||||||
*/
|
|
||||||
updateRoutes(routes: IEmailRoute[]): void;
|
|
||||||
/**
|
|
||||||
* Send an email through the delivery system
|
|
||||||
* @param email The email to send
|
|
||||||
* @param mode The processing mode to use
|
|
||||||
* @param rule Optional rule to apply
|
|
||||||
* @param options Optional sending options
|
|
||||||
* @returns The ID of the queued email
|
|
||||||
*/
|
|
||||||
sendEmail(email: Email, mode?: EmailProcessingMode, route?: IEmailRoute, options?: {
|
|
||||||
skipSuppressionCheck?: boolean;
|
|
||||||
ipAddress?: string;
|
|
||||||
isTransactional?: boolean;
|
|
||||||
}): Promise<string>;
|
|
||||||
/**
|
|
||||||
* Handle DKIM signing for an email
|
|
||||||
* @param email The email to sign
|
|
||||||
* @param domain The domain to sign with
|
|
||||||
* @param selector The DKIM selector
|
|
||||||
*/
|
|
||||||
private handleDkimSigning;
|
|
||||||
/**
|
|
||||||
* Process a bounce notification email
|
|
||||||
* @param bounceEmail The email containing bounce notification information
|
|
||||||
* @returns Processed bounce record or null if not a bounce
|
|
||||||
*/
|
|
||||||
processBounceNotification(bounceEmail: Email): Promise<boolean>;
|
|
||||||
/**
|
|
||||||
* Process an SMTP failure as a bounce
|
|
||||||
* @param recipient Recipient email that failed
|
|
||||||
* @param smtpResponse SMTP error response
|
|
||||||
* @param options Additional options for bounce processing
|
|
||||||
* @returns Processed bounce record
|
|
||||||
*/
|
|
||||||
processSmtpFailure(recipient: string, smtpResponse: string, options?: {
|
|
||||||
sender?: string;
|
|
||||||
originalEmailId?: string;
|
|
||||||
statusCode?: string;
|
|
||||||
headers?: Record<string, string>;
|
|
||||||
}): Promise<boolean>;
|
|
||||||
/**
|
|
||||||
* Check if an email address is suppressed (has bounced previously)
|
|
||||||
* @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;
|
|
||||||
/**
|
|
||||||
* Get bounce history information for an email
|
|
||||||
* @param email Email address to check
|
|
||||||
* @returns Bounce history or null if no bounces
|
|
||||||
*/
|
|
||||||
getBounceHistory(email: string): {
|
|
||||||
lastBounce: number;
|
|
||||||
count: number;
|
|
||||||
type: BounceType;
|
|
||||||
category: BounceCategory;
|
|
||||||
} | null;
|
|
||||||
/**
|
|
||||||
* Get all suppressed email addresses
|
|
||||||
* @returns Array of suppressed email addresses
|
|
||||||
*/
|
|
||||||
getSuppressionList(): string[];
|
|
||||||
/**
|
|
||||||
* Get all hard bounced email addresses
|
|
||||||
* @returns Array of hard bounced email addresses
|
|
||||||
*/
|
|
||||||
getHardBouncedAddresses(): string[];
|
|
||||||
/**
|
|
||||||
* Add an email to the suppression list
|
|
||||||
* @param email Email address to suppress
|
|
||||||
* @param reason Reason for suppression
|
|
||||||
* @param expiresAt Optional expiration time (undefined for permanent)
|
|
||||||
*/
|
|
||||||
addToSuppressionList(email: string, reason: string, expiresAt?: number): void;
|
|
||||||
/**
|
|
||||||
* Remove an email from the suppression list
|
|
||||||
* @param email Email address to remove from suppression
|
|
||||||
*/
|
|
||||||
removeFromSuppressionList(email: string): void;
|
|
||||||
/**
|
|
||||||
* Get the status of IP warmup process
|
|
||||||
* @param ipAddress Optional specific IP to check
|
|
||||||
* @returns Status of IP warmup
|
|
||||||
*/
|
|
||||||
getIPWarmupStatus(ipAddress?: string): any;
|
|
||||||
/**
|
|
||||||
* Add a new IP address to the warmup process
|
|
||||||
* @param ipAddress IP address to add
|
|
||||||
*/
|
|
||||||
addIPToWarmup(ipAddress: string): void;
|
|
||||||
/**
|
|
||||||
* Remove an IP address from the warmup process
|
|
||||||
* @param ipAddress IP address to remove
|
|
||||||
*/
|
|
||||||
removeIPFromWarmup(ipAddress: string): void;
|
|
||||||
/**
|
|
||||||
* Update metrics for an IP in the warmup process
|
|
||||||
* @param ipAddress IP address
|
|
||||||
* @param metrics Metrics to update
|
|
||||||
*/
|
|
||||||
updateIPWarmupMetrics(ipAddress: string, metrics: {
|
|
||||||
openRate?: number;
|
|
||||||
bounceRate?: number;
|
|
||||||
complaintRate?: number;
|
|
||||||
}): void;
|
|
||||||
/**
|
|
||||||
* Check if an IP can send more emails today
|
|
||||||
* @param ipAddress IP address to check
|
|
||||||
* @returns Whether the IP can send more today
|
|
||||||
*/
|
|
||||||
canIPSendMoreToday(ipAddress: string): boolean;
|
|
||||||
/**
|
|
||||||
* Check if an IP can send more emails in the current hour
|
|
||||||
* @param ipAddress IP address to check
|
|
||||||
* @returns Whether the IP can send more this hour
|
|
||||||
*/
|
|
||||||
canIPSendMoreThisHour(ipAddress: string): boolean;
|
|
||||||
/**
|
|
||||||
* Get the best IP to use for sending an email based on warmup status
|
|
||||||
* @param emailInfo Information about the email being sent
|
|
||||||
* @returns Best IP to use or null
|
|
||||||
*/
|
|
||||||
getBestIPForSending(emailInfo: {
|
|
||||||
from: string;
|
|
||||||
to: string[];
|
|
||||||
domain: string;
|
|
||||||
isTransactional?: boolean;
|
|
||||||
}): string | null;
|
|
||||||
/**
|
|
||||||
* Set the active IP allocation policy for warmup
|
|
||||||
* @param policyName Name of the policy to set
|
|
||||||
*/
|
|
||||||
setIPAllocationPolicy(policyName: string): void;
|
|
||||||
/**
|
|
||||||
* Record that an email was sent using a specific IP
|
|
||||||
* @param ipAddress IP address used for sending
|
|
||||||
*/
|
|
||||||
recordIPSend(ipAddress: string): void;
|
|
||||||
/**
|
|
||||||
* Get reputation data for a domain
|
|
||||||
* @param domain Domain to get reputation for
|
|
||||||
* @returns Domain reputation metrics
|
|
||||||
*/
|
|
||||||
getDomainReputationData(domain: string): any;
|
|
||||||
/**
|
|
||||||
* Get summary reputation data for all monitored domains
|
|
||||||
* @returns Summary data for all domains
|
|
||||||
*/
|
|
||||||
getReputationSummary(): any;
|
|
||||||
/**
|
|
||||||
* Add a domain to the reputation monitoring system
|
|
||||||
* @param domain Domain to add
|
|
||||||
*/
|
|
||||||
addDomainToMonitoring(domain: string): void;
|
|
||||||
/**
|
|
||||||
* Remove a domain from the reputation monitoring system
|
|
||||||
* @param domain Domain to remove
|
|
||||||
*/
|
|
||||||
removeDomainFromMonitoring(domain: string): void;
|
|
||||||
/**
|
|
||||||
* Record an email event for domain reputation tracking
|
|
||||||
* @param domain Domain sending the email
|
|
||||||
* @param event Event details
|
|
||||||
*/
|
|
||||||
recordReputationEvent(domain: string, event: {
|
|
||||||
type: 'sent' | 'delivered' | 'bounce' | 'complaint' | 'open' | 'click';
|
|
||||||
count?: number;
|
|
||||||
hardBounce?: boolean;
|
|
||||||
receivingDomain?: string;
|
|
||||||
}): void;
|
|
||||||
/**
|
|
||||||
* Check if DKIM key exists for a domain
|
|
||||||
* @param domain Domain to check
|
|
||||||
*/
|
|
||||||
hasDkimKey(domain: string): boolean;
|
|
||||||
/**
|
|
||||||
* Record successful email delivery
|
|
||||||
* @param domain Sending domain
|
|
||||||
*/
|
|
||||||
recordDelivery(domain: string): void;
|
|
||||||
/**
|
|
||||||
* Record email bounce
|
|
||||||
* @param domain Sending domain
|
|
||||||
* @param receivingDomain Receiving domain that bounced
|
|
||||||
* @param bounceType Type of bounce (hard/soft)
|
|
||||||
* @param reason Bounce reason
|
|
||||||
*/
|
|
||||||
recordBounce(domain: string, receivingDomain: string, bounceType: 'hard' | 'soft', reason: string): void;
|
|
||||||
/**
|
|
||||||
* Get the rate limiter instance
|
|
||||||
* @returns The unified rate limiter
|
|
||||||
*/
|
|
||||||
getRateLimiter(): UnifiedRateLimiter;
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
File diff suppressed because one or more lines are too long
5
dist_ts/mail/routing/index.d.ts
vendored
5
dist_ts/mail/routing/index.d.ts
vendored
@@ -1,5 +0,0 @@
|
|||||||
export * from './classes.email.router.js';
|
|
||||||
export * from './classes.unified.email.server.js';
|
|
||||||
export * from './classes.dns.manager.js';
|
|
||||||
export * from './interfaces.js';
|
|
||||||
export * from './classes.domain.registry.js';
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
// Email routing components
|
|
||||||
export * from './classes.email.router.js';
|
|
||||||
export * from './classes.unified.email.server.js';
|
|
||||||
export * from './classes.dns.manager.js';
|
|
||||||
export * from './interfaces.js';
|
|
||||||
export * from './classes.domain.registry.js';
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL3JvdXRpbmcvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsMkJBQTJCO0FBQzNCLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyxtQ0FBbUMsQ0FBQztBQUNsRCxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyw4QkFBOEIsQ0FBQyJ9
|
|
||||||
187
dist_ts/mail/routing/interfaces.d.ts
vendored
187
dist_ts/mail/routing/interfaces.d.ts
vendored
@@ -1,187 +0,0 @@
|
|||||||
import type { Email } from '../core/classes.email.js';
|
|
||||||
import type { IExtendedSmtpSession } from './classes.unified.email.server.js';
|
|
||||||
/**
|
|
||||||
* Route configuration for email routing
|
|
||||||
*/
|
|
||||||
export interface IEmailRoute {
|
|
||||||
/** Route identifier */
|
|
||||||
name: string;
|
|
||||||
/** Order of evaluation (higher priority evaluated first, default: 0) */
|
|
||||||
priority?: number;
|
|
||||||
/** Conditions to match */
|
|
||||||
match: IEmailMatch;
|
|
||||||
/** Action to take when matched */
|
|
||||||
action: IEmailAction;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Match criteria for email routing
|
|
||||||
*/
|
|
||||||
export interface IEmailMatch {
|
|
||||||
/** Email patterns to match recipients: "*@example.com", "admin@*" */
|
|
||||||
recipients?: string | string[];
|
|
||||||
/** Email patterns to match senders */
|
|
||||||
senders?: string | string[];
|
|
||||||
/** IP addresses or CIDR ranges to match */
|
|
||||||
clientIp?: string | string[];
|
|
||||||
/** Require authentication status */
|
|
||||||
authenticated?: boolean;
|
|
||||||
/** Headers to match */
|
|
||||||
headers?: Record<string, string | RegExp>;
|
|
||||||
/** Message size range */
|
|
||||||
sizeRange?: {
|
|
||||||
min?: number;
|
|
||||||
max?: number;
|
|
||||||
};
|
|
||||||
/** Subject line patterns */
|
|
||||||
subject?: string | RegExp;
|
|
||||||
/** Has attachments */
|
|
||||||
hasAttachments?: boolean;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Action to take when route matches
|
|
||||||
*/
|
|
||||||
export interface IEmailAction {
|
|
||||||
/** Type of action to perform */
|
|
||||||
type: 'forward' | 'deliver' | 'reject' | 'process';
|
|
||||||
/** Forward action configuration */
|
|
||||||
forward?: {
|
|
||||||
/** Target host to forward to */
|
|
||||||
host: string;
|
|
||||||
/** Target port (default: 25) */
|
|
||||||
port?: number;
|
|
||||||
/** Authentication credentials */
|
|
||||||
auth?: {
|
|
||||||
user: string;
|
|
||||||
pass: string;
|
|
||||||
};
|
|
||||||
/** Preserve original headers */
|
|
||||||
preserveHeaders?: boolean;
|
|
||||||
/** Additional headers to add */
|
|
||||||
addHeaders?: Record<string, string>;
|
|
||||||
};
|
|
||||||
/** Reject action configuration */
|
|
||||||
reject?: {
|
|
||||||
/** SMTP response code */
|
|
||||||
code: number;
|
|
||||||
/** SMTP response message */
|
|
||||||
message: string;
|
|
||||||
};
|
|
||||||
/** Process action configuration */
|
|
||||||
process?: {
|
|
||||||
/** Enable content scanning */
|
|
||||||
scan?: boolean;
|
|
||||||
/** Enable DKIM signing */
|
|
||||||
dkim?: boolean;
|
|
||||||
/** Delivery queue priority */
|
|
||||||
queue?: 'normal' | 'priority' | 'bulk';
|
|
||||||
};
|
|
||||||
/** Options for various action types */
|
|
||||||
options?: {
|
|
||||||
/** MTA specific options */
|
|
||||||
mtaOptions?: {
|
|
||||||
domain?: string;
|
|
||||||
allowLocalDelivery?: boolean;
|
|
||||||
localDeliveryPath?: string;
|
|
||||||
dkimSign?: boolean;
|
|
||||||
dkimOptions?: {
|
|
||||||
domainName: string;
|
|
||||||
keySelector: string;
|
|
||||||
privateKey?: string;
|
|
||||||
};
|
|
||||||
smtpBanner?: string;
|
|
||||||
maxConnections?: number;
|
|
||||||
connTimeout?: number;
|
|
||||||
spoolDir?: string;
|
|
||||||
};
|
|
||||||
/** Content scanning configuration */
|
|
||||||
contentScanning?: boolean;
|
|
||||||
scanners?: Array<{
|
|
||||||
type: 'spam' | 'virus' | 'attachment';
|
|
||||||
threshold?: number;
|
|
||||||
action: 'tag' | 'reject';
|
|
||||||
blockedExtensions?: string[];
|
|
||||||
}>;
|
|
||||||
/** Email transformations */
|
|
||||||
transformations?: Array<{
|
|
||||||
type: string;
|
|
||||||
header?: string;
|
|
||||||
value?: string;
|
|
||||||
domains?: string[];
|
|
||||||
append?: boolean;
|
|
||||||
[key: string]: any;
|
|
||||||
}>;
|
|
||||||
};
|
|
||||||
/** Delivery options (applies to forward/process/deliver) */
|
|
||||||
delivery?: {
|
|
||||||
/** Rate limit (messages per minute) */
|
|
||||||
rateLimit?: number;
|
|
||||||
/** Number of retry attempts */
|
|
||||||
retries?: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Context for route evaluation
|
|
||||||
*/
|
|
||||||
export interface IEmailContext {
|
|
||||||
/** The email being routed */
|
|
||||||
email: Email;
|
|
||||||
/** The SMTP session */
|
|
||||||
session: IExtendedSmtpSession;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Email domain configuration
|
|
||||||
*/
|
|
||||||
export interface IEmailDomainConfig {
|
|
||||||
/** Domain name */
|
|
||||||
domain: string;
|
|
||||||
/** DNS handling mode */
|
|
||||||
dnsMode: 'forward' | 'internal-dns' | 'external-dns';
|
|
||||||
/** DNS configuration based on mode */
|
|
||||||
dns?: {
|
|
||||||
/** For 'forward' mode */
|
|
||||||
forward?: {
|
|
||||||
/** Skip DNS validation (default: false) */
|
|
||||||
skipDnsValidation?: boolean;
|
|
||||||
/** Target server's expected domain */
|
|
||||||
targetDomain?: string;
|
|
||||||
};
|
|
||||||
/** For 'internal-dns' mode */
|
|
||||||
internal?: {
|
|
||||||
/** TTL for DNS records in seconds (default: 3600) */
|
|
||||||
ttl?: number;
|
|
||||||
/** MX record priority (default: 10) */
|
|
||||||
mxPriority?: number;
|
|
||||||
};
|
|
||||||
/** For 'external-dns' mode */
|
|
||||||
external?: {
|
|
||||||
/** Custom DNS servers (default: system DNS) */
|
|
||||||
servers?: string[];
|
|
||||||
/** Which records to validate (default: ['MX', 'SPF', 'DKIM', 'DMARC']) */
|
|
||||||
requiredRecords?: ('MX' | 'SPF' | 'DKIM' | 'DMARC')[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
/** Per-domain DKIM settings (DKIM always enabled) */
|
|
||||||
dkim?: {
|
|
||||||
/** DKIM selector (default: 'default') */
|
|
||||||
selector?: string;
|
|
||||||
/** Key size in bits (default: 2048) */
|
|
||||||
keySize?: number;
|
|
||||||
/** Automatically rotate keys (default: false) */
|
|
||||||
rotateKeys?: boolean;
|
|
||||||
/** Days between key rotations (default: 90) */
|
|
||||||
rotationInterval?: number;
|
|
||||||
};
|
|
||||||
/** Per-domain rate limits */
|
|
||||||
rateLimits?: {
|
|
||||||
outbound?: {
|
|
||||||
messagesPerMinute?: number;
|
|
||||||
messagesPerHour?: number;
|
|
||||||
messagesPerDay?: number;
|
|
||||||
};
|
|
||||||
inbound?: {
|
|
||||||
messagesPerMinute?: number;
|
|
||||||
connectionsPerIp?: number;
|
|
||||||
recipientsPerMessage?: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export {};
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL21haWwvcm91dGluZy9pbnRlcmZhY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
|
|
||||||
68
dist_ts/mail/security/classes.dkimcreator.d.ts
vendored
68
dist_ts/mail/security/classes.dkimcreator.d.ts
vendored
@@ -1,68 +0,0 @@
|
|||||||
import * as plugins from '../../plugins.js';
|
|
||||||
import { Email } from '../core/classes.email.js';
|
|
||||||
export interface IKeyPaths {
|
|
||||||
privateKeyPath: string;
|
|
||||||
publicKeyPath: string;
|
|
||||||
}
|
|
||||||
export interface IDkimKeyMetadata {
|
|
||||||
domain: string;
|
|
||||||
selector: string;
|
|
||||||
createdAt: number;
|
|
||||||
rotatedAt?: number;
|
|
||||||
previousSelector?: string;
|
|
||||||
keySize: number;
|
|
||||||
}
|
|
||||||
export declare class DKIMCreator {
|
|
||||||
private keysDir;
|
|
||||||
private storageManager?;
|
|
||||||
constructor(keysDir?: string, storageManager?: any);
|
|
||||||
getKeyPathsForDomain(domainArg: string): Promise<IKeyPaths>;
|
|
||||||
handleDKIMKeysForDomain(domainArg: string): Promise<void>;
|
|
||||||
handleDKIMKeysForEmail(email: Email): Promise<void>;
|
|
||||||
readDKIMKeys(domainArg: string): Promise<{
|
|
||||||
privateKey: string;
|
|
||||||
publicKey: string;
|
|
||||||
}>;
|
|
||||||
createDKIMKeys(): Promise<{
|
|
||||||
privateKey: string;
|
|
||||||
publicKey: string;
|
|
||||||
}>;
|
|
||||||
storeDKIMKeys(privateKey: string, publicKey: string, privateKeyPath: string, publicKeyPath: string): Promise<void>;
|
|
||||||
createAndStoreDKIMKeys(domain: string): Promise<void>;
|
|
||||||
getDNSRecordForDomain(domainArg: string): Promise<plugins.tsclass.network.IDnsRecord>;
|
|
||||||
/**
|
|
||||||
* Get DKIM key metadata for a domain
|
|
||||||
*/
|
|
||||||
private getKeyMetadata;
|
|
||||||
/**
|
|
||||||
* Save DKIM key metadata
|
|
||||||
*/
|
|
||||||
private saveKeyMetadata;
|
|
||||||
/**
|
|
||||||
* Check if DKIM keys need rotation
|
|
||||||
*/
|
|
||||||
needsRotation(domain: string, selector?: string, rotationIntervalDays?: number): Promise<boolean>;
|
|
||||||
/**
|
|
||||||
* Rotate DKIM keys for a domain
|
|
||||||
*/
|
|
||||||
rotateDkimKeys(domain: string, currentSelector?: string, keySize?: number): Promise<string>;
|
|
||||||
/**
|
|
||||||
* Get key paths for a specific selector
|
|
||||||
*/
|
|
||||||
getKeyPathsForSelector(domain: string, selector: string): Promise<IKeyPaths>;
|
|
||||||
/**
|
|
||||||
* Read DKIM keys for a specific selector
|
|
||||||
*/
|
|
||||||
readDKIMKeysForSelector(domain: string, selector: string): Promise<{
|
|
||||||
privateKey: string;
|
|
||||||
publicKey: string;
|
|
||||||
}>;
|
|
||||||
/**
|
|
||||||
* Get DNS record for a specific selector
|
|
||||||
*/
|
|
||||||
getDNSRecordForSelector(domain: string, selector: string): Promise<plugins.tsclass.network.IDnsRecord>;
|
|
||||||
/**
|
|
||||||
* Clean up old DKIM keys after grace period
|
|
||||||
*/
|
|
||||||
cleanupOldKeys(domain: string, gracePeriodDays?: number): Promise<void>;
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
29
dist_ts/mail/security/classes.dkimverifier.d.ts
vendored
29
dist_ts/mail/security/classes.dkimverifier.d.ts
vendored
@@ -1,29 +0,0 @@
|
|||||||
/**
|
|
||||||
* Result of a DKIM verification
|
|
||||||
*/
|
|
||||||
export interface IDkimVerificationResult {
|
|
||||||
isValid: boolean;
|
|
||||||
domain?: string;
|
|
||||||
selector?: string;
|
|
||||||
status?: string;
|
|
||||||
details?: any;
|
|
||||||
errorMessage?: string;
|
|
||||||
signatureFields?: Record<string, string>;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* DKIM verifier — delegates to the Rust security bridge.
|
|
||||||
*/
|
|
||||||
export declare class DKIMVerifier {
|
|
||||||
constructor();
|
|
||||||
/**
|
|
||||||
* Verify DKIM signature for an email via Rust bridge
|
|
||||||
*/
|
|
||||||
verify(emailData: string, options?: {
|
|
||||||
useCache?: boolean;
|
|
||||||
returnDetails?: boolean;
|
|
||||||
}): Promise<IDkimVerificationResult>;
|
|
||||||
/** No-op — Rust bridge handles its own caching */
|
|
||||||
clearCache(): void;
|
|
||||||
/** Always 0 — cache is managed by the Rust side */
|
|
||||||
getCacheSize(): number;
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import { logger } from '../../logger.js';
|
|
||||||
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js';
|
|
||||||
import { RustSecurityBridge } from '../../security/classes.rustsecuritybridge.js';
|
|
||||||
/**
|
|
||||||
* DKIM verifier — delegates to the Rust security bridge.
|
|
||||||
*/
|
|
||||||
export class DKIMVerifier {
|
|
||||||
constructor() { }
|
|
||||||
/**
|
|
||||||
* Verify DKIM signature for an email via Rust bridge
|
|
||||||
*/
|
|
||||||
async verify(emailData, options = {}) {
|
|
||||||
try {
|
|
||||||
const bridge = RustSecurityBridge.getInstance();
|
|
||||||
const results = await bridge.verifyDkim(emailData);
|
|
||||||
const first = results[0];
|
|
||||||
const result = {
|
|
||||||
isValid: first?.is_valid ?? false,
|
|
||||||
domain: first?.domain ?? undefined,
|
|
||||||
selector: first?.selector ?? undefined,
|
|
||||||
status: first?.status ?? 'none',
|
|
||||||
details: options.returnDetails ? results : undefined,
|
|
||||||
};
|
|
||||||
SecurityLogger.getInstance().logEvent({
|
|
||||||
level: result.isValid ? SecurityLogLevel.INFO : SecurityLogLevel.WARN,
|
|
||||||
type: SecurityEventType.DKIM,
|
|
||||||
message: `DKIM verification ${result.isValid ? 'passed' : 'failed'} for domain ${result.domain || 'unknown'}`,
|
|
||||||
details: { selector: result.selector, status: result.status },
|
|
||||||
domain: result.domain || 'unknown',
|
|
||||||
success: result.isValid
|
|
||||||
});
|
|
||||||
logger.log(result.isValid ? 'info' : 'warn', `DKIM verification: ${result.status} for domain ${result.domain || 'unknown'}`);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
logger.log('error', `DKIM verification failed: ${error.message}`);
|
|
||||||
SecurityLogger.getInstance().logEvent({
|
|
||||||
level: SecurityLogLevel.ERROR,
|
|
||||||
type: SecurityEventType.DKIM,
|
|
||||||
message: `DKIM verification error`,
|
|
||||||
details: { error: error.message },
|
|
||||||
success: false
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
isValid: false,
|
|
||||||
status: 'temperror',
|
|
||||||
errorMessage: `Verification error: ${error.message}`
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/** No-op — Rust bridge handles its own caching */
|
|
||||||
clearCache() { }
|
|
||||||
/** Always 0 — cache is managed by the Rust side */
|
|
||||||
getCacheSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ka2ltdmVyaWZpZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL3NlY3VyaXR5L2NsYXNzZXMuZGtpbXZlcmlmaWVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOENBQThDLENBQUM7QUFlbEY7O0dBRUc7QUFDSCxNQUFNLE9BQU8sWUFBWTtJQUN2QixnQkFBZSxDQUFDO0lBRWhCOztPQUVHO0lBQ0ksS0FBSyxDQUFDLE1BQU0sQ0FDakIsU0FBaUIsRUFDakIsVUFHSSxFQUFFO1FBRU4sSUFBSSxDQUFDO1lBQ0gsTUFBTSxNQUFNLEdBQUcsa0JBQWtCLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDaEQsTUFBTSxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ25ELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUV6QixNQUFNLE1BQU0sR0FBNEI7Z0JBQ3RDLE9BQU8sRUFBRSxLQUFLLEVBQUUsUUFBUSxJQUFJLEtBQUs7Z0JBQ2pDLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxJQUFJLFNBQVM7Z0JBQ2xDLFFBQVEsRUFBRSxLQUFLLEVBQUUsUUFBUSxJQUFJLFNBQVM7Z0JBQ3RDLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxJQUFJLE1BQU07Z0JBQy9CLE9BQU8sRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVM7YUFDckQsQ0FBQztZQUVGLGNBQWMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBQ3BDLEtBQUssRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLElBQUk7Z0JBQ3JFLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxJQUFJO2dCQUM1QixPQUFPLEVBQUUscUJBQXFCLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxlQUFlLE1BQU0sQ0FBQyxNQUFNLElBQUksU0FBUyxFQUFFO2dCQUM3RyxPQUFPLEVBQUUsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sRUFBRTtnQkFDN0QsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLElBQUksU0FBUztnQkFDbEMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO2FBQ3hCLENBQUMsQ0FBQztZQUVILE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQ3pDLHNCQUFzQixNQUFNLENBQUMsTUFBTSxlQUFlLE1BQU0sQ0FBQyxNQUFNLElBQUksU0FBUyxFQUFFLENBQUMsQ0FBQztZQUVsRixPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLDZCQUE2QixLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUVsRSxjQUFjLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQUNwQyxLQUFLLEVBQUUsZ0JBQWdCLENBQUMsS0FBSztnQkFDN0IsSUFBSSxFQUFFLGlCQUFpQixDQUFDLElBQUk7Z0JBQzVCLE9BQU8sRUFBRSx5QkFBeUI7Z0JBQ2xDLE9BQU8sRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsT0FBTyxFQUFFO2dCQUNqQyxPQUFPLEVBQUUsS0FBSzthQUNmLENBQUMsQ0FBQztZQUVILE9BQU87Z0JBQ0wsT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsTUFBTSxFQUFFLFdBQVc7Z0JBQ25CLFlBQVksRUFBRSx1QkFBdUIsS0FBSyxDQUFDLE9BQU8sRUFBRTthQUNyRCxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFRCxrREFBa0Q7SUFDM0MsVUFBVSxLQUFVLENBQUM7SUFFNUIsbURBQW1EO0lBQzVDLFlBQVk7UUFDakIsT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDO0NBQ0YifQ==
|
|
||||||
123
dist_ts/mail/security/classes.dmarcverifier.d.ts
vendored
123
dist_ts/mail/security/classes.dmarcverifier.d.ts
vendored
@@ -1,123 +0,0 @@
|
|||||||
import type { Email } from '../core/classes.email.js';
|
|
||||||
/**
|
|
||||||
* DMARC policy types
|
|
||||||
*/
|
|
||||||
export declare enum DmarcPolicy {
|
|
||||||
NONE = "none",
|
|
||||||
QUARANTINE = "quarantine",
|
|
||||||
REJECT = "reject"
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* DMARC alignment modes
|
|
||||||
*/
|
|
||||||
export declare enum DmarcAlignment {
|
|
||||||
RELAXED = "r",
|
|
||||||
STRICT = "s"
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* DMARC record fields
|
|
||||||
*/
|
|
||||||
export interface DmarcRecord {
|
|
||||||
version: string;
|
|
||||||
policy: DmarcPolicy;
|
|
||||||
subdomainPolicy?: DmarcPolicy;
|
|
||||||
pct?: number;
|
|
||||||
adkim?: DmarcAlignment;
|
|
||||||
aspf?: DmarcAlignment;
|
|
||||||
reportInterval?: number;
|
|
||||||
failureOptions?: string;
|
|
||||||
reportUriAggregate?: string[];
|
|
||||||
reportUriForensic?: string[];
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* DMARC verification result
|
|
||||||
*/
|
|
||||||
export interface DmarcResult {
|
|
||||||
hasDmarc: boolean;
|
|
||||||
record?: DmarcRecord;
|
|
||||||
spfDomainAligned: boolean;
|
|
||||||
dkimDomainAligned: boolean;
|
|
||||||
spfPassed: boolean;
|
|
||||||
dkimPassed: boolean;
|
|
||||||
policyEvaluated: DmarcPolicy;
|
|
||||||
actualPolicy: DmarcPolicy;
|
|
||||||
appliedPercentage: number;
|
|
||||||
action: 'pass' | 'quarantine' | 'reject';
|
|
||||||
details: string;
|
|
||||||
error?: string;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Class for verifying and enforcing DMARC policies
|
|
||||||
*/
|
|
||||||
export declare class DmarcVerifier {
|
|
||||||
private dnsManager?;
|
|
||||||
constructor(dnsManager?: any);
|
|
||||||
/**
|
|
||||||
* Parse a DMARC record from a TXT record string
|
|
||||||
* @param record DMARC TXT record string
|
|
||||||
* @returns Parsed DMARC record or null if invalid
|
|
||||||
*/
|
|
||||||
parseDmarcRecord(record: string): DmarcRecord | null;
|
|
||||||
/**
|
|
||||||
* Check if domains are aligned according to DMARC policy
|
|
||||||
* @param headerDomain Domain from header (From)
|
|
||||||
* @param authDomain Domain from authentication (SPF, DKIM)
|
|
||||||
* @param alignment Alignment mode
|
|
||||||
* @returns Whether the domains are aligned
|
|
||||||
*/
|
|
||||||
private isDomainAligned;
|
|
||||||
/**
|
|
||||||
* Extract domain from an email address
|
|
||||||
* @param email Email address
|
|
||||||
* @returns Domain part of the email
|
|
||||||
*/
|
|
||||||
private getDomainFromEmail;
|
|
||||||
/**
|
|
||||||
* Check if DMARC verification should be applied based on percentage
|
|
||||||
* @param record DMARC record
|
|
||||||
* @returns Whether DMARC verification should be applied
|
|
||||||
*/
|
|
||||||
private shouldApplyDmarc;
|
|
||||||
/**
|
|
||||||
* Determine the action to take based on DMARC policy
|
|
||||||
* @param policy DMARC policy
|
|
||||||
* @returns Action to take
|
|
||||||
*/
|
|
||||||
private determineAction;
|
|
||||||
/**
|
|
||||||
* Verify DMARC for an incoming email
|
|
||||||
* @param email Email to verify
|
|
||||||
* @param spfResult SPF verification result
|
|
||||||
* @param dkimResult DKIM verification result
|
|
||||||
* @returns DMARC verification result
|
|
||||||
*/
|
|
||||||
verify(email: Email, spfResult: {
|
|
||||||
domain: string;
|
|
||||||
result: boolean;
|
|
||||||
}, dkimResult: {
|
|
||||||
domain: string;
|
|
||||||
result: boolean;
|
|
||||||
}): Promise<DmarcResult>;
|
|
||||||
/**
|
|
||||||
* Apply DMARC policy to an email
|
|
||||||
* @param email Email to apply policy to
|
|
||||||
* @param dmarcResult DMARC verification result
|
|
||||||
* @returns Whether the email should be accepted
|
|
||||||
*/
|
|
||||||
applyPolicy(email: Email, dmarcResult: DmarcResult): boolean;
|
|
||||||
/**
|
|
||||||
* End-to-end DMARC verification and policy application
|
|
||||||
* This method should be called after SPF and DKIM verification
|
|
||||||
* @param email Email to verify
|
|
||||||
* @param spfResult SPF verification result
|
|
||||||
* @param dkimResult DKIM verification result
|
|
||||||
* @returns Whether the email should be accepted
|
|
||||||
*/
|
|
||||||
verifyAndApply(email: Email, spfResult: {
|
|
||||||
domain: string;
|
|
||||||
result: boolean;
|
|
||||||
}, dkimResult: {
|
|
||||||
domain: string;
|
|
||||||
result: boolean;
|
|
||||||
}): Promise<boolean>;
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
71
dist_ts/mail/security/classes.spfverifier.d.ts
vendored
71
dist_ts/mail/security/classes.spfverifier.d.ts
vendored
@@ -1,71 +0,0 @@
|
|||||||
import type { Email } from '../core/classes.email.js';
|
|
||||||
/**
|
|
||||||
* SPF result qualifiers
|
|
||||||
*/
|
|
||||||
export declare enum SpfQualifier {
|
|
||||||
PASS = "+",
|
|
||||||
NEUTRAL = "?",
|
|
||||||
SOFTFAIL = "~",
|
|
||||||
FAIL = "-"
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* SPF mechanism types
|
|
||||||
*/
|
|
||||||
export declare enum SpfMechanismType {
|
|
||||||
ALL = "all",
|
|
||||||
INCLUDE = "include",
|
|
||||||
A = "a",
|
|
||||||
MX = "mx",
|
|
||||||
IP4 = "ip4",
|
|
||||||
IP6 = "ip6",
|
|
||||||
EXISTS = "exists",
|
|
||||||
REDIRECT = "redirect",
|
|
||||||
EXP = "exp"
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* SPF mechanism definition
|
|
||||||
*/
|
|
||||||
export interface SpfMechanism {
|
|
||||||
qualifier: SpfQualifier;
|
|
||||||
type: SpfMechanismType;
|
|
||||||
value?: string;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* SPF record parsed data
|
|
||||||
*/
|
|
||||||
export interface SpfRecord {
|
|
||||||
version: string;
|
|
||||||
mechanisms: SpfMechanism[];
|
|
||||||
modifiers: Record<string, string>;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* SPF verification result
|
|
||||||
*/
|
|
||||||
export interface SpfResult {
|
|
||||||
result: 'pass' | 'neutral' | 'softfail' | 'fail' | 'temperror' | 'permerror' | 'none';
|
|
||||||
explanation?: string;
|
|
||||||
domain: string;
|
|
||||||
ip: string;
|
|
||||||
record?: string;
|
|
||||||
error?: string;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Class for verifying SPF records.
|
|
||||||
* Delegates actual SPF evaluation to the Rust security bridge.
|
|
||||||
* Retains parseSpfRecord() for lightweight local parsing.
|
|
||||||
*/
|
|
||||||
export declare class SpfVerifier {
|
|
||||||
constructor(_dnsManager?: any);
|
|
||||||
/**
|
|
||||||
* Parse SPF record from TXT record (pure string parsing, no DNS)
|
|
||||||
*/
|
|
||||||
parseSpfRecord(record: string): SpfRecord | null;
|
|
||||||
/**
|
|
||||||
* Verify SPF for a given email — delegates to Rust bridge
|
|
||||||
*/
|
|
||||||
verify(email: Email, ip: string, heloDomain: string): Promise<SpfResult>;
|
|
||||||
/**
|
|
||||||
* Check if email passes SPF verification and apply headers
|
|
||||||
*/
|
|
||||||
verifyAndApply(email: Email, ip: string, heloDomain: string): Promise<boolean>;
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
4
dist_ts/mail/security/index.d.ts
vendored
4
dist_ts/mail/security/index.d.ts
vendored
@@ -1,4 +0,0 @@
|
|||||||
export * from './classes.dkimcreator.js';
|
|
||||||
export * from './classes.dkimverifier.js';
|
|
||||||
export * from './classes.dmarcverifier.js';
|
|
||||||
export * from './classes.spfverifier.js';
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
// Email security components
|
|
||||||
export * from './classes.dkimcreator.js';
|
|
||||||
export * from './classes.dkimverifier.js';
|
|
||||||
export * from './classes.dmarcverifier.js';
|
|
||||||
export * from './classes.spfverifier.js';
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL3NlY3VyaXR5L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDRCQUE0QjtBQUM1QixjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDBCQUEwQixDQUFDIn0=
|
|
||||||
14
dist_ts/paths.d.ts
vendored
14
dist_ts/paths.d.ts
vendored
@@ -1,14 +0,0 @@
|
|||||||
export declare const baseDir: string;
|
|
||||||
export declare const packageDir: string;
|
|
||||||
export declare const distServe: string;
|
|
||||||
export declare const dataDir: string;
|
|
||||||
export declare const keysDir: string;
|
|
||||||
export declare const dnsRecordsDir: string;
|
|
||||||
export declare const sentEmailsDir: string;
|
|
||||||
export declare const receivedEmailsDir: string;
|
|
||||||
export declare const failedEmailsDir: string;
|
|
||||||
export declare const logsDir: string;
|
|
||||||
export declare const emailTemplatesDir: string;
|
|
||||||
export declare const MtaAttachmentsDir: string;
|
|
||||||
export declare const configPath: string;
|
|
||||||
export declare function ensureDirectories(): Promise<void>;
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import * as plugins from './plugins.js';
|
|
||||||
// Base directories
|
|
||||||
export const baseDir = process.cwd();
|
|
||||||
export const packageDir = plugins.path.join(plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url), '../');
|
|
||||||
export const distServe = plugins.path.join(packageDir, './dist_serve');
|
|
||||||
// Configure data directory with environment variable or default to .nogit/data
|
|
||||||
const DEFAULT_DATA_PATH = '.nogit/data';
|
|
||||||
export const dataDir = process.env.DATA_DIR
|
|
||||||
? process.env.DATA_DIR
|
|
||||||
: plugins.path.join(baseDir, DEFAULT_DATA_PATH);
|
|
||||||
// MTA directories
|
|
||||||
export const keysDir = plugins.path.join(dataDir, 'keys');
|
|
||||||
export const dnsRecordsDir = plugins.path.join(dataDir, 'dns');
|
|
||||||
export const sentEmailsDir = plugins.path.join(dataDir, 'emails', 'sent');
|
|
||||||
export const receivedEmailsDir = plugins.path.join(dataDir, 'emails', 'received');
|
|
||||||
export const failedEmailsDir = plugins.path.join(dataDir, 'emails', 'failed'); // For failed emails
|
|
||||||
export const logsDir = plugins.path.join(dataDir, 'logs'); // For logs
|
|
||||||
// Email template directories
|
|
||||||
export const emailTemplatesDir = plugins.path.join(dataDir, 'templates', 'email');
|
|
||||||
export const MtaAttachmentsDir = plugins.path.join(dataDir, 'attachments'); // For email attachments
|
|
||||||
// Configuration path
|
|
||||||
export const configPath = process.env.CONFIG_PATH
|
|
||||||
? process.env.CONFIG_PATH
|
|
||||||
: plugins.path.join(baseDir, 'config.json');
|
|
||||||
// Create directories if they don't exist
|
|
||||||
export async function ensureDirectories() {
|
|
||||||
// Ensure data directories
|
|
||||||
await plugins.smartfs.directory(dataDir).recursive().create();
|
|
||||||
await plugins.smartfs.directory(keysDir).recursive().create();
|
|
||||||
await plugins.smartfs.directory(dnsRecordsDir).recursive().create();
|
|
||||||
await plugins.smartfs.directory(sentEmailsDir).recursive().create();
|
|
||||||
await plugins.smartfs.directory(receivedEmailsDir).recursive().create();
|
|
||||||
await plugins.smartfs.directory(failedEmailsDir).recursive().create();
|
|
||||||
await plugins.smartfs.directory(logsDir).recursive().create();
|
|
||||||
// Ensure email template directories
|
|
||||||
await plugins.smartfs.directory(emailTemplatesDir).recursive().create();
|
|
||||||
await plugins.smartfs.directory(MtaAttachmentsDir).recursive().create();
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0aHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9wYXRocy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxtQkFBbUI7QUFDbkIsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNyQyxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQ3pDLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQy9ELEtBQUssQ0FDTixDQUFDO0FBQ0YsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxjQUFjLENBQUMsQ0FBQztBQUV2RSwrRUFBK0U7QUFDL0UsTUFBTSxpQkFBaUIsR0FBRyxhQUFhLENBQUM7QUFDeEMsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUTtJQUN6QyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRO0lBQ3RCLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztBQUVsRCxtQkFBbUI7QUFDbkIsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztBQUMxRCxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQy9ELE1BQU0sQ0FBQyxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUks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
|
|
||||||
47
dist_ts/plugins.d.ts
vendored
47
dist_ts/plugins.d.ts
vendored
@@ -1,47 +0,0 @@
|
|||||||
import * as dns from 'dns';
|
|
||||||
import * as fs from 'fs';
|
|
||||||
import * as crypto from 'crypto';
|
|
||||||
import * as http from 'http';
|
|
||||||
import * as net from 'net';
|
|
||||||
import * as os from 'os';
|
|
||||||
import * as path from 'path';
|
|
||||||
import * as tls from 'tls';
|
|
||||||
import * as util from 'util';
|
|
||||||
export { dns, fs, crypto, http, net, os, path, tls, util, };
|
|
||||||
import * as servezoneInterfaces from '@serve.zone/interfaces';
|
|
||||||
export { servezoneInterfaces };
|
|
||||||
import * as typedrequest from '@api.global/typedrequest';
|
|
||||||
import * as typedserver from '@api.global/typedserver';
|
|
||||||
import * as typedsocket from '@api.global/typedsocket';
|
|
||||||
export { typedrequest, typedserver, typedsocket, };
|
|
||||||
import * as projectinfo from '@push.rocks/projectinfo';
|
|
||||||
import * as qenv from '@push.rocks/qenv';
|
|
||||||
import * as smartacme from '@push.rocks/smartacme';
|
|
||||||
import * as smartdata from '@push.rocks/smartdata';
|
|
||||||
import * as smartdns from '@push.rocks/smartdns';
|
|
||||||
import * as smartfile from '@push.rocks/smartfile';
|
|
||||||
import { SmartFs } from '@push.rocks/smartfs';
|
|
||||||
import * as smartguard from '@push.rocks/smartguard';
|
|
||||||
import * as smartjwt from '@push.rocks/smartjwt';
|
|
||||||
import * as smartlog from '@push.rocks/smartlog';
|
|
||||||
import * as smartmail from '@push.rocks/smartmail';
|
|
||||||
import * as smartmetrics from '@push.rocks/smartmetrics';
|
|
||||||
import * as smartnetwork from '@push.rocks/smartnetwork';
|
|
||||||
import * as smartpath from '@push.rocks/smartpath';
|
|
||||||
import * as smartproxy from '@push.rocks/smartproxy';
|
|
||||||
import * as smartpromise from '@push.rocks/smartpromise';
|
|
||||||
import * as smartrequest from '@push.rocks/smartrequest';
|
|
||||||
import * as smartrule from '@push.rocks/smartrule';
|
|
||||||
import * as smartrust from '@push.rocks/smartrust';
|
|
||||||
import * as smartrx from '@push.rocks/smartrx';
|
|
||||||
import * as smartunique from '@push.rocks/smartunique';
|
|
||||||
export declare const smartfs: SmartFs;
|
|
||||||
export { projectinfo, qenv, smartacme, smartdata, smartdns, smartfile, SmartFs, smartguard, smartjwt, smartlog, smartmail, smartmetrics, smartnetwork, smartpath, smartproxy, smartpromise, smartrequest, smartrule, smartrust, smartrx, smartunique };
|
|
||||||
export type TLogLevel = 'error' | 'warn' | 'info' | 'success' | 'debug';
|
|
||||||
import * as cloudflare from '@apiclient.xyz/cloudflare';
|
|
||||||
export { cloudflare, };
|
|
||||||
import * as tsclass from '@tsclass/tsclass';
|
|
||||||
export { tsclass, };
|
|
||||||
import mailparser from 'mailparser';
|
|
||||||
import * as uuid from 'uuid';
|
|
||||||
export { mailparser, uuid, };
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
// node native
|
|
||||||
import * as dns from 'dns';
|
|
||||||
import * as fs from 'fs';
|
|
||||||
import * as crypto from 'crypto';
|
|
||||||
import * as http from 'http';
|
|
||||||
import * as net from 'net';
|
|
||||||
import * as os from 'os';
|
|
||||||
import * as path from 'path';
|
|
||||||
import * as tls from 'tls';
|
|
||||||
import * as util from 'util';
|
|
||||||
export { dns, fs, crypto, http, net, os, path, tls, util, };
|
|
||||||
// @serve.zone scope
|
|
||||||
import * as servezoneInterfaces from '@serve.zone/interfaces';
|
|
||||||
export { servezoneInterfaces };
|
|
||||||
// @api.global scope
|
|
||||||
import * as typedrequest from '@api.global/typedrequest';
|
|
||||||
import * as typedserver from '@api.global/typedserver';
|
|
||||||
import * as typedsocket from '@api.global/typedsocket';
|
|
||||||
export { typedrequest, typedserver, typedsocket, };
|
|
||||||
// @push.rocks scope
|
|
||||||
import * as projectinfo from '@push.rocks/projectinfo';
|
|
||||||
import * as qenv from '@push.rocks/qenv';
|
|
||||||
import * as smartacme from '@push.rocks/smartacme';
|
|
||||||
import * as smartdata from '@push.rocks/smartdata';
|
|
||||||
import * as smartdns from '@push.rocks/smartdns';
|
|
||||||
import * as smartfile from '@push.rocks/smartfile';
|
|
||||||
import { SmartFs, SmartFsProviderNode } from '@push.rocks/smartfs';
|
|
||||||
import * as smartguard from '@push.rocks/smartguard';
|
|
||||||
import * as smartjwt from '@push.rocks/smartjwt';
|
|
||||||
import * as smartlog from '@push.rocks/smartlog';
|
|
||||||
import * as smartmail from '@push.rocks/smartmail';
|
|
||||||
import * as smartmetrics from '@push.rocks/smartmetrics';
|
|
||||||
import * as smartnetwork from '@push.rocks/smartnetwork';
|
|
||||||
import * as smartpath from '@push.rocks/smartpath';
|
|
||||||
import * as smartproxy from '@push.rocks/smartproxy';
|
|
||||||
import * as smartpromise from '@push.rocks/smartpromise';
|
|
||||||
import * as smartrequest from '@push.rocks/smartrequest';
|
|
||||||
import * as smartrule from '@push.rocks/smartrule';
|
|
||||||
import * as smartrust from '@push.rocks/smartrust';
|
|
||||||
import * as smartrx from '@push.rocks/smartrx';
|
|
||||||
import * as smartunique from '@push.rocks/smartunique';
|
|
||||||
export const smartfs = new SmartFs(new SmartFsProviderNode());
|
|
||||||
export { projectinfo, qenv, smartacme, smartdata, smartdns, smartfile, SmartFs, smartguard, smartjwt, smartlog, smartmail, smartmetrics, smartnetwork, smartpath, smartproxy, smartpromise, smartrequest, smartrule, smartrust, smartrx, smartunique };
|
|
||||||
// apiclient.xyz scope
|
|
||||||
import * as cloudflare from '@apiclient.xyz/cloudflare';
|
|
||||||
export { cloudflare, };
|
|
||||||
// tsclass scope
|
|
||||||
import * as tsclass from '@tsclass/tsclass';
|
|
||||||
export { tsclass, };
|
|
||||||
// third party
|
|
||||||
import mailparser from 'mailparser';
|
|
||||||
import * as uuid from 'uuid';
|
|
||||||
export { mailparser, uuid, };
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYztBQUNkLE9BQU8sS0FBSyxHQUFHLE1BQU0sS0FBSyxDQUFDO0FBQzNCLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxHQUFHLE1BQU0sS0FBSyxDQUFDO0FBQzNCLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxHQUFHLE1BQU0sS0FBSyxDQUFDO0FBQzNCLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBRTdCLE9BQU8sRUFDTCxHQUFHLEVBQ0gsRUFBRSxFQUNGLE1BQU0sRUFDTixJQUFJLEVBQ0osR0FBRyxFQUNILEVBQUUsRUFDRixJQUFJLEVBQ0osR0FBRyxFQUNILElBQUksR0FDTCxDQUFBO0FBRUQsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxtQkFBbUIsTUFBTSx3QkFBd0IsQ0FBQztBQUU5RCxPQUFPLEVBQ0wsbUJBQW1CLEVBQ3BCLENBQUE7QUFFRCxvQkFBb0I7QUFDcEIsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEtBQUssV0FBVyxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFFdkQsT0FBTyxFQUNMLFlBQVksRUFDWixXQUFXLEVBQ1gsV0FBVyxHQUNaLENBQUE7QUFFRCxvQkFBb0I7QUFDcEIsT0FBTyxLQUFLLFdBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEtBQUssSUFBSSxNQUFNLGtCQUFrQixDQUFDO0FBQ3pDLE9BQU8sS0FBSyxTQUFTLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxLQUFLLFNBQVMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRCxPQUFPLEtBQUssUUFBUSxNQUFNLHNCQUFzQixDQUFDO0FBQ2pELE9BQU8sS0FBSyxTQUFTLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxFQUFFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25FLE9BQU8sS0FBSyxVQUFVLE1BQU0sd0JBQXdCLENBQUM7QUFDckQsT0FBTyxLQUFLLFFBQVEsTUFBTSxzQkFBc0IsQ0FBQztBQUNqRCxPQUFPLEtBQUssUUFBUSxNQUFNLHNCQUFzQixDQUFDO0FBQ2pELE9BQU8sS0FBSyxTQUFTLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxTQUFTLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxLQUFLLFVBQVUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxZQUFZLE1BQU0sMEJBQTBCLENBQUM7QUFDekQsT0FBTyxLQUFLLFNBQVMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRCxPQUFPLEtBQUssU0FBUyxNQUFNLHVCQUF1QixDQUFDO0FBQ25ELE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxLQUFLLFdBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUV2RCxNQUFNLENBQUMsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUMsSUFBSSxtQkFBbUIsRUFBRSxDQUFDLENBQUM7QUFFOUQsT0FBTyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFFLENBQUM7QUFLdlAsc0JBQXNCO0FBQ3RCLE9BQU8sS0FBSyxVQUFVLE1BQU0sMkJBQTJCLENBQUM7QUFFeEQsT0FBTyxFQUNMLFVBQVUsR0FDWCxDQUFBO0FBRUQsZ0JBQWdCO0FBQ2hCLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxFQUNMLE9BQU8sR0FDUixDQUFBO0FBRUQsY0FBYztBQUNkLE9BQU8sVUFBVSxNQUFNLFlBQVksQ0FBQztBQUNwQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUU3QixPQUFPLEVBQ0wsVUFBVSxFQUNWLElBQUksR0FDTCxDQUFBIn0=
|
|
||||||
130
dist_ts/security/classes.contentscanner.d.ts
vendored
130
dist_ts/security/classes.contentscanner.d.ts
vendored
@@ -1,130 +0,0 @@
|
|||||||
import { Email } from '../mail/core/classes.email.js';
|
|
||||||
/**
|
|
||||||
* Scan result information
|
|
||||||
*/
|
|
||||||
export interface IScanResult {
|
|
||||||
isClean: boolean;
|
|
||||||
threatType?: string;
|
|
||||||
threatDetails?: string;
|
|
||||||
threatScore: number;
|
|
||||||
scannedElements: string[];
|
|
||||||
timestamp: number;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Options for content scanner configuration
|
|
||||||
*/
|
|
||||||
export interface IContentScannerOptions {
|
|
||||||
maxCacheSize?: number;
|
|
||||||
cacheTTL?: number;
|
|
||||||
scanSubject?: boolean;
|
|
||||||
scanBody?: boolean;
|
|
||||||
scanAttachments?: boolean;
|
|
||||||
maxAttachmentSizeToScan?: number;
|
|
||||||
scanAttachmentNames?: boolean;
|
|
||||||
blockExecutables?: boolean;
|
|
||||||
blockMacros?: boolean;
|
|
||||||
customRules?: Array<{
|
|
||||||
pattern: string | RegExp;
|
|
||||||
type: string;
|
|
||||||
score: number;
|
|
||||||
description: string;
|
|
||||||
}>;
|
|
||||||
minThreatScore?: number;
|
|
||||||
highThreatScore?: number;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Threat categories
|
|
||||||
*/
|
|
||||||
export declare enum ThreatCategory {
|
|
||||||
SPAM = "spam",
|
|
||||||
PHISHING = "phishing",
|
|
||||||
MALWARE = "malware",
|
|
||||||
EXECUTABLE = "executable",
|
|
||||||
SUSPICIOUS_LINK = "suspicious_link",
|
|
||||||
MALICIOUS_MACRO = "malicious_macro",
|
|
||||||
XSS = "xss",
|
|
||||||
SENSITIVE_DATA = "sensitive_data",
|
|
||||||
BLACKLISTED_CONTENT = "blacklisted_content",
|
|
||||||
CUSTOM_RULE = "custom_rule"
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Content Scanner for detecting malicious email content
|
|
||||||
*/
|
|
||||||
export declare class ContentScanner {
|
|
||||||
private static instance;
|
|
||||||
private scanCache;
|
|
||||||
private options;
|
|
||||||
/**
|
|
||||||
* Default options for the content scanner
|
|
||||||
*/
|
|
||||||
private static readonly DEFAULT_OPTIONS;
|
|
||||||
/**
|
|
||||||
* Constructor for the ContentScanner
|
|
||||||
* @param options Configuration options
|
|
||||||
*/
|
|
||||||
constructor(options?: IContentScannerOptions);
|
|
||||||
/**
|
|
||||||
* Get the singleton instance of the scanner
|
|
||||||
* @param options Configuration options
|
|
||||||
* @returns Singleton scanner instance
|
|
||||||
*/
|
|
||||||
static getInstance(options?: IContentScannerOptions): ContentScanner;
|
|
||||||
/**
|
|
||||||
* Scan an email for malicious content.
|
|
||||||
* Delegates text/subject/html/filename pattern scanning to Rust.
|
|
||||||
* Binary attachment scanning (PE headers, VBA macros) stays in TS.
|
|
||||||
* @param email The email to scan
|
|
||||||
* @returns Scan result
|
|
||||||
*/
|
|
||||||
scanEmail(email: Email): Promise<IScanResult>;
|
|
||||||
/**
|
|
||||||
* Generate a cache key from an email
|
|
||||||
* @param email The email to generate a key for
|
|
||||||
* @returns Cache key
|
|
||||||
*/
|
|
||||||
private generateCacheKey;
|
|
||||||
/**
|
|
||||||
* Scan attachment binary content for PE headers and VBA macros.
|
|
||||||
* This stays in TS because it accesses raw Buffer data (too large for IPC).
|
|
||||||
* @param attachment The attachment to scan
|
|
||||||
* @param result The scan result to update
|
|
||||||
*/
|
|
||||||
private scanAttachmentBinary;
|
|
||||||
/**
|
|
||||||
* Apply custom rules (runtime-configured patterns) to the email.
|
|
||||||
* These stay in TS because they are configured at runtime.
|
|
||||||
* @param email The email to check
|
|
||||||
* @param result The scan result to update
|
|
||||||
*/
|
|
||||||
private applyCustomRules;
|
|
||||||
/**
|
|
||||||
* Extract text from a binary buffer for scanning
|
|
||||||
* @param buffer Binary content
|
|
||||||
* @returns Extracted text (may be partial)
|
|
||||||
*/
|
|
||||||
private extractTextFromBuffer;
|
|
||||||
/**
|
|
||||||
* Check if an Office document likely contains macros
|
|
||||||
* @param attachment The attachment to check
|
|
||||||
* @returns Whether the file likely contains macros
|
|
||||||
*/
|
|
||||||
private likelyContainsMacros;
|
|
||||||
/**
|
|
||||||
* Log a high threat finding to the security logger
|
|
||||||
* @param email The email containing the threat
|
|
||||||
* @param result The scan result
|
|
||||||
*/
|
|
||||||
private logHighThreatFound;
|
|
||||||
/**
|
|
||||||
* Log a threat finding to the security logger
|
|
||||||
* @param email The email containing the threat
|
|
||||||
* @param result The scan result
|
|
||||||
*/
|
|
||||||
private logThreatFound;
|
|
||||||
/**
|
|
||||||
* Get threat level description based on score
|
|
||||||
* @param score Threat score
|
|
||||||
* @returns Threat level description
|
|
||||||
*/
|
|
||||||
static getThreatLevel(score: number): 'none' | 'low' | 'medium' | 'high';
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,73 +0,0 @@
|
|||||||
/**
|
|
||||||
* Reputation check result information
|
|
||||||
*/
|
|
||||||
export interface IReputationResult {
|
|
||||||
score: number;
|
|
||||||
isSpam: boolean;
|
|
||||||
isProxy: boolean;
|
|
||||||
isTor: boolean;
|
|
||||||
isVPN: boolean;
|
|
||||||
country?: string;
|
|
||||||
asn?: string;
|
|
||||||
org?: string;
|
|
||||||
blacklists?: string[];
|
|
||||||
timestamp: number;
|
|
||||||
error?: string;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Reputation threshold scores
|
|
||||||
*/
|
|
||||||
export declare enum ReputationThreshold {
|
|
||||||
HIGH_RISK = 20,// Score below this is considered high risk
|
|
||||||
MEDIUM_RISK = 50,// Score below this is considered medium risk
|
|
||||||
LOW_RISK = 80
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* IP type classifications
|
|
||||||
*/
|
|
||||||
export declare enum IPType {
|
|
||||||
RESIDENTIAL = "residential",
|
|
||||||
DATACENTER = "datacenter",
|
|
||||||
PROXY = "proxy",
|
|
||||||
TOR = "tor",
|
|
||||||
VPN = "vpn",
|
|
||||||
UNKNOWN = "unknown"
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Options for the IP Reputation Checker
|
|
||||||
*/
|
|
||||||
export interface IIPReputationOptions {
|
|
||||||
maxCacheSize?: number;
|
|
||||||
cacheTTL?: number;
|
|
||||||
dnsblServers?: string[];
|
|
||||||
highRiskThreshold?: number;
|
|
||||||
mediumRiskThreshold?: number;
|
|
||||||
lowRiskThreshold?: number;
|
|
||||||
enableLocalCache?: boolean;
|
|
||||||
enableDNSBL?: boolean;
|
|
||||||
enableIPInfo?: boolean;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* IP reputation checker — delegates DNSBL lookups to the Rust security bridge.
|
|
||||||
* Retains LRU caching and disk persistence in TypeScript.
|
|
||||||
*/
|
|
||||||
export declare class IPReputationChecker {
|
|
||||||
private static instance;
|
|
||||||
private reputationCache;
|
|
||||||
private options;
|
|
||||||
private storageManager?;
|
|
||||||
private static readonly DEFAULT_OPTIONS;
|
|
||||||
constructor(options?: IIPReputationOptions, storageManager?: any);
|
|
||||||
static getInstance(options?: IIPReputationOptions, storageManager?: any): IPReputationChecker;
|
|
||||||
/**
|
|
||||||
* Check an IP address's reputation via the Rust bridge
|
|
||||||
*/
|
|
||||||
checkReputation(ip: string): Promise<IReputationResult>;
|
|
||||||
private createErrorResult;
|
|
||||||
private isValidIPAddress;
|
|
||||||
private logReputationCheck;
|
|
||||||
private saveCache;
|
|
||||||
private loadCache;
|
|
||||||
static getRiskLevel(score: number): 'high' | 'medium' | 'low' | 'trusted';
|
|
||||||
updateStorageManager(storageManager: any): void;
|
|
||||||
}
|
|
||||||
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