feat(rust): scaffold Rust workspace and fix TypeScript build errors
- Add @git.zone/tsrust with linux_amd64/linux_arm64 cross-compilation - Scaffold Rust workspace with 5 crates: mailer-core, mailer-smtp, mailer-security, mailer-napi, mailer-bin - Fix all TypeScript compilation errors for upgraded dependencies (smartfile v13, mailauth v4.13, smartproxy v23) - Replace smartfile.fs/memory with @push.rocks/smartfs throughout codebase - Fix .ts import extensions to .js for NodeNext module resolution - Update DKIMSignOptions usage to match mailauth v4.13 API - Add MTA error classes with permissive signatures for legacy SMTP client - Replace removed DcRouter/StorageManager/deliverability imports with local interfaces
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,8 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
.nogit/
|
.nogit/
|
||||||
dist/
|
dist/
|
||||||
|
dist_rust/
|
||||||
|
rust/target/
|
||||||
deno.lock
|
deno.lock
|
||||||
*.log
|
*.log
|
||||||
.env
|
.env
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
{}
|
{
|
||||||
|
"@git.zone/tsrust": {
|
||||||
|
"targets": ["linux_amd64", "linux_arm64"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
41
package.json
41
package.json
@@ -32,51 +32,54 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "tstest test/ --logfile --verbose --timeout 60",
|
"test": "tstest test/ --logfile --verbose --timeout 60",
|
||||||
"build": "tsbuild tsfolders",
|
"build": "tsbuild tsfolders && tsrust",
|
||||||
"check": "tsbuild check"
|
"check": "tsbuild check"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.6.8",
|
"@git.zone/tsbuild": "^4.1.2",
|
||||||
"@git.zone/tstest": "^2.3.1",
|
"@git.zone/tsrust": "^1.3.0",
|
||||||
|
"@git.zone/tstest": "^3.1.8",
|
||||||
"@types/mailparser": "^3.4.6",
|
"@types/mailparser": "^3.4.6",
|
||||||
"@types/node": "^24.0.10",
|
"@types/node": "^25.2.3",
|
||||||
"tsx": "^4.19.2"
|
"tsx": "^4.21.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@api.global/typedrequest": "^3.0.19",
|
"@api.global/typedrequest": "^3.2.5",
|
||||||
"@api.global/typedserver": "^3.0.74",
|
"@api.global/typedserver": "^8.3.0",
|
||||||
"@api.global/typedsocket": "^3.0.0",
|
"@api.global/typedsocket": "^4.1.0",
|
||||||
"@apiclient.xyz/cloudflare": "^6.4.1",
|
"@apiclient.xyz/cloudflare": "^7.1.0",
|
||||||
"@push.rocks/projectinfo": "^5.0.1",
|
"@push.rocks/projectinfo": "^5.0.1",
|
||||||
"@push.rocks/qenv": "^6.1.0",
|
"@push.rocks/qenv": "^6.1.0",
|
||||||
"@push.rocks/smartacme": "^8.0.0",
|
"@push.rocks/smartacme": "^8.0.0",
|
||||||
"@push.rocks/smartdata": "^5.15.1",
|
"@push.rocks/smartdata": "^7.0.15",
|
||||||
"@push.rocks/smartdns": "^7.5.0",
|
"@push.rocks/smartdns": "^7.5.0",
|
||||||
"@push.rocks/smartfile": "^11.2.5",
|
"@push.rocks/smartfile": "^13.1.2",
|
||||||
|
"@push.rocks/smartfs": "^1.3.1",
|
||||||
"@push.rocks/smartguard": "^3.1.0",
|
"@push.rocks/smartguard": "^3.1.0",
|
||||||
"@push.rocks/smartjwt": "^2.2.1",
|
"@push.rocks/smartjwt": "^2.2.1",
|
||||||
"@push.rocks/smartlog": "^3.1.8",
|
"@push.rocks/smartlog": "^3.1.8",
|
||||||
"@push.rocks/smartmail": "^2.1.0",
|
"@push.rocks/smartmail": "^2.2.0",
|
||||||
"@push.rocks/smartmetrics": "^2.0.10",
|
"@push.rocks/smartmetrics": "^2.0.10",
|
||||||
"@push.rocks/smartnetwork": "^4.0.2",
|
"@push.rocks/smartnetwork": "^4.0.2",
|
||||||
"@push.rocks/smartpath": "^5.0.5",
|
"@push.rocks/smartpath": "^6.0.0",
|
||||||
"@push.rocks/smartpromise": "^4.0.3",
|
"@push.rocks/smartpromise": "^4.0.3",
|
||||||
"@push.rocks/smartproxy": "^19.6.15",
|
"@push.rocks/smartproxy": "^23.1.0",
|
||||||
"@push.rocks/smartrequest": "^2.1.0",
|
"@push.rocks/smartrequest": "^5.0.1",
|
||||||
"@push.rocks/smartrule": "^2.0.1",
|
"@push.rocks/smartrule": "^2.0.1",
|
||||||
"@push.rocks/smartrx": "^3.0.10",
|
"@push.rocks/smartrx": "^3.0.10",
|
||||||
"@push.rocks/smartunique": "^3.0.9",
|
"@push.rocks/smartunique": "^3.0.9",
|
||||||
"@serve.zone/interfaces": "^5.0.4",
|
"@serve.zone/interfaces": "^5.0.4",
|
||||||
"@tsclass/tsclass": "^9.2.0",
|
"@tsclass/tsclass": "^9.2.0",
|
||||||
"ip": "^2.0.1",
|
"ip": "^2.0.1",
|
||||||
"lru-cache": "^11.1.0",
|
"lru-cache": "^11.2.5",
|
||||||
"mailauth": "^4.8.6",
|
"mailauth": "^4.13.0",
|
||||||
"mailparser": "^3.7.4",
|
"mailparser": "^3.9.3",
|
||||||
"uuid": "^11.1.0"
|
"uuid": "^13.0.0"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"bin/",
|
"bin/",
|
||||||
"scripts/install-binary.js",
|
"scripts/install-binary.js",
|
||||||
|
"dist_rust/**/*",
|
||||||
"readme.md",
|
"readme.md",
|
||||||
"license",
|
"license",
|
||||||
"changelog.md"
|
"changelog.md"
|
||||||
|
|||||||
5690
pnpm-lock.yaml
generated
5690
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
|||||||
|
# Project Hints
|
||||||
|
|
||||||
|
## Rust Workspace
|
||||||
|
- Rust code lives in `rust/` with a Cargo workspace
|
||||||
|
- Crates: `mailer-core`, `mailer-smtp`, `mailer-security`, `mailer-napi`, `mailer-bin`
|
||||||
|
- `mailer-bin` is the binary target that `tsrust` builds for cross-compilation
|
||||||
|
- `mailer-napi` is a cdylib for N-API bindings (not built by tsrust, needs separate napi-rs build pipeline)
|
||||||
|
- tsrust only supports binary targets (looks for `src/main.rs` or `[[bin]]` entries)
|
||||||
|
- Cross-compilation targets: `linux_amd64`, `linux_arm64` (configured in `npmextra.json`)
|
||||||
|
- Build output goes to `dist_rust/`
|
||||||
|
|
||||||
|
## Build
|
||||||
|
- `pnpm build` runs `tsbuild tsfolders && tsrust`
|
||||||
|
- Note: `tsbuild tsfolders` requires a `tsconfig.json` at the project root (currently missing - pre-existing issue)
|
||||||
|
- `tsrust` independently works and produces binaries in `dist_rust/`
|
||||||
|
|
||||||
|
## Key Dependencies (Rust)
|
||||||
|
- `tokio` - async runtime
|
||||||
|
- `tokio-rustls` - TLS
|
||||||
|
- `hickory-dns` (hickory-resolver) - DNS resolution
|
||||||
|
- `mail-auth` - DKIM/SPF/DMARC (by Stalwart Labs)
|
||||||
|
- `mailparse` - MIME parsing
|
||||||
|
- `napi` + `napi-derive` - Node.js bindings
|
||||||
|
- `ring` - crypto primitives
|
||||||
|
- `dashmap` - concurrent hash maps
|
||||||
|
|||||||
2
rust/.cargo/config.toml
Normal file
2
rust/.cargo/config.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[target.aarch64-unknown-linux-gnu]
|
||||||
|
linker = "aarch64-linux-gnu-gcc"
|
||||||
2354
rust/Cargo.lock
generated
Normal file
2354
rust/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
rust/Cargo.toml
Normal file
30
rust/Cargo.toml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
members = [
|
||||||
|
"crates/mailer-core",
|
||||||
|
"crates/mailer-smtp",
|
||||||
|
"crates/mailer-security",
|
||||||
|
"crates/mailer-napi",
|
||||||
|
"crates/mailer-bin",
|
||||||
|
]
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT"
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
tokio-rustls = "0.26"
|
||||||
|
hickory-dns = { version = "0.25", package = "hickory-resolver" }
|
||||||
|
mail-auth = "0.4"
|
||||||
|
mailparse = "0.15"
|
||||||
|
napi = { version = "2", features = ["napi9", "async", "serde-json"] }
|
||||||
|
napi-derive = "2"
|
||||||
|
ring = "0.17"
|
||||||
|
dashmap = "6"
|
||||||
|
thiserror = "2"
|
||||||
|
tracing = "0.1"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
bytes = "1"
|
||||||
18
rust/crates/mailer-bin/Cargo.toml
Normal file
18
rust/crates/mailer-bin/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[package]
|
||||||
|
name = "mailer-bin"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "mailer-bin"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
mailer-core = { path = "../mailer-core" }
|
||||||
|
mailer-smtp = { path = "../mailer-smtp" }
|
||||||
|
mailer-security = { path = "../mailer-security" }
|
||||||
|
tokio.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
11
rust/crates/mailer-bin/src/main.rs
Normal file
11
rust/crates/mailer-bin/src/main.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
//! mailer-bin: Standalone Rust binary for the @serve.zone/mailer network stack.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!(
|
||||||
|
"mailer-bin v{} (core: {}, smtp: {}, security: {})",
|
||||||
|
env!("CARGO_PKG_VERSION"),
|
||||||
|
mailer_core::version(),
|
||||||
|
mailer_smtp::version(),
|
||||||
|
mailer_security::version(),
|
||||||
|
);
|
||||||
|
}
|
||||||
13
rust/crates/mailer-core/Cargo.toml
Normal file
13
rust/crates/mailer-core/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "mailer-core"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
thiserror.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
bytes.workspace = true
|
||||||
|
mailparse.workspace = true
|
||||||
19
rust/crates/mailer-core/src/lib.rs
Normal file
19
rust/crates/mailer-core/src/lib.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
//! mailer-core: Email model, validation, and RFC 5322 primitives.
|
||||||
|
|
||||||
|
/// Re-export mailparse for MIME parsing.
|
||||||
|
pub use mailparse;
|
||||||
|
|
||||||
|
/// Placeholder for email address validation and data types.
|
||||||
|
pub fn version() -> &'static str {
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_version() {
|
||||||
|
assert!(!version().is_empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
21
rust/crates/mailer-napi/Cargo.toml
Normal file
21
rust/crates/mailer-napi/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
[package]
|
||||||
|
name = "mailer-napi"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
mailer-core = { path = "../mailer-core" }
|
||||||
|
mailer-smtp = { path = "../mailer-smtp" }
|
||||||
|
mailer-security = { path = "../mailer-security" }
|
||||||
|
napi.workspace = true
|
||||||
|
napi-derive.workspace = true
|
||||||
|
tokio.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
napi-build = "2"
|
||||||
5
rust/crates/mailer-napi/build.rs
Normal file
5
rust/crates/mailer-napi/build.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
extern crate napi_build;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
napi_build::setup();
|
||||||
|
}
|
||||||
15
rust/crates/mailer-napi/src/lib.rs
Normal file
15
rust/crates/mailer-napi/src/lib.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//! mailer-napi: N-API bindings exposing Rust mailer to Node.js/TypeScript.
|
||||||
|
|
||||||
|
use napi_derive::napi;
|
||||||
|
|
||||||
|
/// Returns the version of the native mailer module.
|
||||||
|
#[napi]
|
||||||
|
pub fn get_version() -> String {
|
||||||
|
format!(
|
||||||
|
"mailer-napi v{} (core: {}, smtp: {}, security: {})",
|
||||||
|
env!("CARGO_PKG_VERSION"),
|
||||||
|
mailer_core::version(),
|
||||||
|
mailer_smtp::version(),
|
||||||
|
mailer_security::version(),
|
||||||
|
)
|
||||||
|
}
|
||||||
13
rust/crates/mailer-security/Cargo.toml
Normal file
13
rust/crates/mailer-security/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "mailer-security"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
mailer-core = { path = "../mailer-core" }
|
||||||
|
mail-auth.workspace = true
|
||||||
|
ring.workspace = true
|
||||||
|
thiserror.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
18
rust/crates/mailer-security/src/lib.rs
Normal file
18
rust/crates/mailer-security/src/lib.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//! mailer-security: DKIM, SPF, and DMARC verification.
|
||||||
|
|
||||||
|
pub use mailer_core;
|
||||||
|
|
||||||
|
/// Placeholder for DKIM/SPF/DMARC implementation.
|
||||||
|
pub fn version() -> &'static str {
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_version() {
|
||||||
|
assert!(!version().is_empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
16
rust/crates/mailer-smtp/Cargo.toml
Normal file
16
rust/crates/mailer-smtp/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "mailer-smtp"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
mailer-core = { path = "../mailer-core" }
|
||||||
|
tokio.workspace = true
|
||||||
|
tokio-rustls.workspace = true
|
||||||
|
hickory-dns.workspace = true
|
||||||
|
dashmap.workspace = true
|
||||||
|
thiserror.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
bytes.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
18
rust/crates/mailer-smtp/src/lib.rs
Normal file
18
rust/crates/mailer-smtp/src/lib.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//! mailer-smtp: SMTP protocol engine (server + client).
|
||||||
|
|
||||||
|
pub use mailer_core;
|
||||||
|
|
||||||
|
/// Placeholder for the SMTP server and client implementation.
|
||||||
|
pub fn version() -> &'static str {
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_version() {
|
||||||
|
assert!(!version().is_empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
119
ts/errors/index.ts
Normal file
119
ts/errors/index.ts
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
* MTA error classes for SMTP client operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class MtaConnectionError extends Error {
|
||||||
|
public code: string;
|
||||||
|
public details?: any;
|
||||||
|
constructor(message: string, detailsOrCode?: any) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'MtaConnectionError';
|
||||||
|
if (typeof detailsOrCode === 'string') {
|
||||||
|
this.code = detailsOrCode;
|
||||||
|
} else {
|
||||||
|
this.code = 'CONNECTION_ERROR';
|
||||||
|
this.details = detailsOrCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static timeout(host: string, port: number, timeoutMs?: number): MtaConnectionError {
|
||||||
|
return new MtaConnectionError(`Connection to ${host}:${port} timed out${timeoutMs ? ` after ${timeoutMs}ms` : ''}`, 'TIMEOUT');
|
||||||
|
}
|
||||||
|
static refused(host: string, port: number): MtaConnectionError {
|
||||||
|
return new MtaConnectionError(`Connection to ${host}:${port} refused`, 'REFUSED');
|
||||||
|
}
|
||||||
|
static dnsError(host: string, err?: any): MtaConnectionError {
|
||||||
|
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 {
|
||||||
|
public code: string;
|
||||||
|
public details?: any;
|
||||||
|
constructor(message: string, detailsOrCode?: any) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'MtaAuthenticationError';
|
||||||
|
if (typeof detailsOrCode === 'string') {
|
||||||
|
this.code = detailsOrCode;
|
||||||
|
} else {
|
||||||
|
this.code = 'AUTH_ERROR';
|
||||||
|
this.details = detailsOrCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static invalidCredentials(host?: string, user?: string): MtaAuthenticationError {
|
||||||
|
const detail = host && user ? `${user}@${host}` : host || user || '';
|
||||||
|
return new MtaAuthenticationError(`Authentication failed${detail ? `: ${detail}` : ''}`, 'INVALID_CREDENTIALS');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MtaDeliveryError extends Error {
|
||||||
|
public code: string;
|
||||||
|
public responseCode?: number;
|
||||||
|
public details?: any;
|
||||||
|
constructor(message: string, detailsOrCode?: any, responseCode?: number) {
|
||||||
|
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: string, ...args: any[]): MtaDeliveryError {
|
||||||
|
return new MtaDeliveryError(message, 'TEMPORARY');
|
||||||
|
}
|
||||||
|
static permanent(message: string, ...args: any[]): MtaDeliveryError {
|
||||||
|
return new MtaDeliveryError(message, 'PERMANENT');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MtaConfigurationError extends Error {
|
||||||
|
public code: string;
|
||||||
|
public details?: any;
|
||||||
|
constructor(message: string, detailsOrCode?: any) {
|
||||||
|
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 {
|
||||||
|
public code: string;
|
||||||
|
public details?: any;
|
||||||
|
constructor(message: string, detailsOrCode?: any) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'MtaTimeoutError';
|
||||||
|
if (typeof detailsOrCode === 'string') {
|
||||||
|
this.code = detailsOrCode;
|
||||||
|
} else {
|
||||||
|
this.code = 'TIMEOUT';
|
||||||
|
this.details = detailsOrCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static commandTimeout(command: string, hostOrTimeout?: any, timeoutMs?: number): MtaTimeoutError {
|
||||||
|
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 {
|
||||||
|
public code: string;
|
||||||
|
public details?: any;
|
||||||
|
constructor(message: string, detailsOrCode?: any) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'MtaProtocolError';
|
||||||
|
if (typeof detailsOrCode === 'string') {
|
||||||
|
this.code = detailsOrCode;
|
||||||
|
} else {
|
||||||
|
this.code = 'PROTOCOL_ERROR';
|
||||||
|
this.details = detailsOrCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import * as paths from '../../paths.ts';
|
import * as paths from '../../paths.js';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.ts';
|
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js';
|
||||||
import { LRUCache } from 'lru-cache';
|
import { LRUCache } from 'lru-cache';
|
||||||
import type { Email } from './classes.email.ts';
|
import type { Email } from './classes.email.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bounce types for categorizing the reasons for bounces
|
* Bounce types for categorizing the reasons for bounces
|
||||||
@@ -650,10 +650,9 @@ export class BounceManager {
|
|||||||
await this.storageManager.set('/email/bounces/suppression-list.json', suppressionData);
|
await this.storageManager.set('/email/bounces/suppression-list.json', suppressionData);
|
||||||
} else {
|
} else {
|
||||||
// Fall back to filesystem
|
// Fall back to filesystem
|
||||||
plugins.smartfile.memory.toFsSync(
|
await plugins.smartfs.file(
|
||||||
suppressionData,
|
|
||||||
plugins.path.join(paths.dataDir, 'emails', 'suppression_list.json')
|
plugins.path.join(paths.dataDir, 'emails', 'suppression_list.json')
|
||||||
);
|
).write(suppressionData);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.log('error', `Failed to save suppression list: ${error.message}`);
|
logger.log('error', `Failed to save suppression list: ${error.message}`);
|
||||||
@@ -744,9 +743,9 @@ export class BounceManager {
|
|||||||
|
|
||||||
// Ensure directory exists
|
// Ensure directory exists
|
||||||
const bounceDir = plugins.path.join(paths.dataDir, 'emails', 'bounces');
|
const bounceDir = plugins.path.join(paths.dataDir, 'emails', 'bounces');
|
||||||
plugins.smartfile.fs.ensureDirSync(bounceDir);
|
await plugins.smartfs.directory(bounceDir).recursive().create();
|
||||||
|
|
||||||
plugins.smartfile.memory.toFsSync(bounceData, bouncePath);
|
await plugins.smartfs.file(bouncePath).write(bounceData);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.log('error', `Failed to save bounce record: ${error.message}`);
|
logger.log('error', `Failed to save bounce record: ${error.message}`);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import { EmailValidator } from './classes.emailvalidator.ts';
|
import { EmailValidator } from './classes.emailvalidator.js';
|
||||||
|
|
||||||
export interface IAttachment {
|
export interface IAttachment {
|
||||||
filename: string;
|
filename: string;
|
||||||
@@ -614,10 +614,11 @@ export class Email {
|
|||||||
|
|
||||||
// Add attachments
|
// Add attachments
|
||||||
for (const attachment of this.attachments) {
|
for (const attachment of this.attachments) {
|
||||||
const smartAttachment = await plugins.smartfile.SmartFile.fromBuffer(
|
const smartAttachment = new plugins.smartfile.SmartFile({
|
||||||
attachment.filename,
|
path: attachment.filename,
|
||||||
attachment.content
|
contentBuffer: attachment.content,
|
||||||
);
|
base: process.cwd(),
|
||||||
|
});
|
||||||
|
|
||||||
// Set content type if available
|
// Set content type if available
|
||||||
if (attachment.contentType) {
|
if (attachment.contentType) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import { LRUCache } from 'lru-cache';
|
import { LRUCache } from 'lru-cache';
|
||||||
|
|
||||||
export interface IEmailValidationResult {
|
export interface IEmailValidationResult {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import * as paths from '../../paths.ts';
|
import * as paths from '../../paths.js';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import { Email, type IEmailOptions, type IAttachment } from './classes.email.ts';
|
import { Email, type IEmailOptions, type IAttachment } from './classes.email.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Email template type definition
|
* Email template type definition
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Core email components
|
// Core email components
|
||||||
export * from './classes.email.ts';
|
export * from './classes.email.js';
|
||||||
export * from './classes.emailvalidator.ts';
|
export * from './classes.emailvalidator.js';
|
||||||
export * from './classes.templatemanager.ts';
|
export * from './classes.templatemanager.js';
|
||||||
export * from './classes.bouncemanager.ts';
|
export * from './classes.bouncemanager.js';
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
import * as path from 'node:path';
|
import * as path from 'node:path';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import { type EmailProcessingMode } from '../routing/classes.email.config.ts';
|
import { type EmailProcessingMode } from '../routing/classes.email.config.js';
|
||||||
import type { IEmailRoute } from '../routing/interfaces.ts';
|
import type { IEmailRoute } from '../routing/interfaces.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue item status
|
* Queue item status
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
import * as net from 'node:net';
|
import * as net from 'node:net';
|
||||||
import * as tls from 'node:tls';
|
import * as tls from 'node:tls';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import {
|
import {
|
||||||
SecurityLogger,
|
SecurityLogger,
|
||||||
SecurityLogLevel,
|
SecurityLogLevel,
|
||||||
SecurityEventType
|
SecurityEventType
|
||||||
} from '../../security/index.ts';
|
} from '../../security/index.js';
|
||||||
import { UnifiedDeliveryQueue, type IQueueItem } from './classes.delivery.queue.ts';
|
import { UnifiedDeliveryQueue, type IQueueItem } from './classes.delivery.queue.js';
|
||||||
import type { Email } from '../core/classes.email.ts';
|
import type { Email } from '../core/classes.email.js';
|
||||||
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.ts';
|
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.js';
|
||||||
import type { SmtpClient } from './smtpclient/smtp-client.ts';
|
import type { SmtpClient } from './smtpclient/smtp-client.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delivery status enumeration
|
* Delivery status enumeration
|
||||||
@@ -768,7 +768,11 @@ export class MultiModeDeliverySystem extends EventEmitter {
|
|||||||
const rawEmail = email.toRFC822String();
|
const rawEmail = email.toRFC822String();
|
||||||
|
|
||||||
// Sign the email
|
// Sign the email
|
||||||
|
const dkimPrivateKey = (await this.emailServer.dkimCreator.readDKIMKeys(domainName)).privateKey;
|
||||||
const signResult = await plugins.dkimSign(rawEmail, {
|
const signResult = await plugins.dkimSign(rawEmail, {
|
||||||
|
signingDomain: domainName,
|
||||||
|
selector: keySelector,
|
||||||
|
privateKey: dkimPrivateKey,
|
||||||
canonicalization: 'relaxed/relaxed',
|
canonicalization: 'relaxed/relaxed',
|
||||||
algorithm: 'rsa-sha256',
|
algorithm: 'rsa-sha256',
|
||||||
signTime: new Date(),
|
signTime: new Date(),
|
||||||
@@ -776,7 +780,7 @@ export class MultiModeDeliverySystem extends EventEmitter {
|
|||||||
{
|
{
|
||||||
signingDomain: domainName,
|
signingDomain: domainName,
|
||||||
selector: keySelector,
|
selector: keySelector,
|
||||||
privateKey: (await this.emailServer.dkimCreator.readDKIMKeys(domainName)).privateKey,
|
privateKey: dkimPrivateKey,
|
||||||
algorithm: 'rsa-sha256',
|
algorithm: 'rsa-sha256',
|
||||||
canonicalization: 'relaxed/relaxed'
|
canonicalization: 'relaxed/relaxed'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import * as paths from '../../paths.ts';
|
import * as paths from '../../paths.js';
|
||||||
import { Email } from '../core/classes.email.ts';
|
import { Email } from '../core/classes.email.js';
|
||||||
import { EmailSignJob } from './classes.emailsignjob.ts';
|
import { EmailSignJob } from './classes.emailsignjob.js';
|
||||||
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.ts';
|
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.js';
|
||||||
import type { SmtpClient } from './smtpclient/smtp-client.ts';
|
import type { SmtpClient } from './smtpclient/smtp-client.js';
|
||||||
import type { ISmtpSendResult } from './smtpclient/interfaces.ts';
|
import type { ISmtpSendResult } from './smtpclient/interfaces.js';
|
||||||
|
|
||||||
// Configuration options for email sending
|
// Configuration options for email sending
|
||||||
export interface IEmailSendOptions {
|
export interface IEmailSendOptions {
|
||||||
@@ -400,13 +400,13 @@ export class EmailSendJob {
|
|||||||
const fileName = `${Date.now()}_${this.email.from}_to_${this.email.to[0]}_success.eml`;
|
const fileName = `${Date.now()}_${this.email.from}_to_${this.email.to[0]}_success.eml`;
|
||||||
const filePath = plugins.path.join(paths.sentEmailsDir, fileName);
|
const filePath = plugins.path.join(paths.sentEmailsDir, fileName);
|
||||||
|
|
||||||
await plugins.smartfile.fs.ensureDir(paths.sentEmailsDir);
|
await plugins.smartfs.directory(paths.sentEmailsDir).recursive().create();
|
||||||
await plugins.smartfile.memory.toFs(emailContent, filePath);
|
await plugins.smartfs.file(filePath).write(emailContent);
|
||||||
|
|
||||||
// Also save delivery info
|
// Also save delivery info
|
||||||
const infoFileName = `${Date.now()}_${this.email.from}_to_${this.email.to[0]}_info.json`;
|
const infoFileName = `${Date.now()}_${this.email.from}_to_${this.email.to[0]}_info.json`;
|
||||||
const infoPath = plugins.path.join(paths.sentEmailsDir, infoFileName);
|
const infoPath = plugins.path.join(paths.sentEmailsDir, infoFileName);
|
||||||
await plugins.smartfile.memory.toFs(JSON.stringify(this.deliveryInfo, null, 2), infoPath);
|
await plugins.smartfs.file(infoPath).write(JSON.stringify(this.deliveryInfo, null, 2));
|
||||||
|
|
||||||
this.log(`Email saved to ${fileName}`);
|
this.log(`Email saved to ${fileName}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -424,13 +424,13 @@ export class EmailSendJob {
|
|||||||
const fileName = `${Date.now()}_${this.email.from}_to_${this.email.to[0]}_failed.eml`;
|
const fileName = `${Date.now()}_${this.email.from}_to_${this.email.to[0]}_failed.eml`;
|
||||||
const filePath = plugins.path.join(paths.failedEmailsDir, fileName);
|
const filePath = plugins.path.join(paths.failedEmailsDir, fileName);
|
||||||
|
|
||||||
await plugins.smartfile.fs.ensureDir(paths.failedEmailsDir);
|
await plugins.smartfs.directory(paths.failedEmailsDir).recursive().create();
|
||||||
await plugins.smartfile.memory.toFs(emailContent, filePath);
|
await plugins.smartfs.file(filePath).write(emailContent);
|
||||||
|
|
||||||
// Also save delivery info with error details
|
// Also save delivery info with error details
|
||||||
const infoFileName = `${Date.now()}_${this.email.from}_to_${this.email.to[0]}_error.json`;
|
const infoFileName = `${Date.now()}_${this.email.from}_to_${this.email.to[0]}_error.json`;
|
||||||
const infoPath = plugins.path.join(paths.failedEmailsDir, infoFileName);
|
const infoPath = plugins.path.join(paths.failedEmailsDir, infoFileName);
|
||||||
await plugins.smartfile.memory.toFs(JSON.stringify(this.deliveryInfo, null, 2), infoPath);
|
await plugins.smartfs.file(infoPath).write(JSON.stringify(this.deliveryInfo, null, 2));
|
||||||
|
|
||||||
this.log(`Failed email saved to ${fileName}`);
|
this.log(`Failed email saved to ${fileName}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.ts';
|
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.js';
|
||||||
|
|
||||||
interface Headers {
|
interface Headers {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
@@ -27,37 +27,21 @@ export class EmailSignJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getSignatureHeader(emailMessage: string): Promise<string> {
|
public async getSignatureHeader(emailMessage: string): Promise<string> {
|
||||||
|
const privateKey = await this.loadPrivateKey();
|
||||||
const signResult = await plugins.dkimSign(emailMessage, {
|
const signResult = await plugins.dkimSign(emailMessage, {
|
||||||
// Optional, default canonicalization, default is "relaxed/relaxed"
|
signingDomain: this.jobOptions.domain,
|
||||||
canonicalization: 'relaxed/relaxed', // c=
|
selector: this.jobOptions.selector,
|
||||||
|
privateKey,
|
||||||
// Optional, default signing and hashing algorithm
|
canonicalization: 'relaxed/relaxed',
|
||||||
// Mostly useful when you want to use rsa-sha1, otherwise no need to set
|
|
||||||
algorithm: 'rsa-sha256',
|
algorithm: 'rsa-sha256',
|
||||||
|
signTime: new Date(),
|
||||||
// Optional, default is current time
|
|
||||||
signTime: new Date(), // t=
|
|
||||||
|
|
||||||
// Keys for one or more signatures
|
|
||||||
// Different signatures can use different algorithms (mostly useful when
|
|
||||||
// you want to sign a message both with RSA and Ed25519)
|
|
||||||
signatureData: [
|
signatureData: [
|
||||||
{
|
{
|
||||||
signingDomain: this.jobOptions.domain, // d=
|
signingDomain: this.jobOptions.domain,
|
||||||
selector: this.jobOptions.selector, // s=
|
selector: this.jobOptions.selector,
|
||||||
// supported key types: RSA, Ed25519
|
privateKey,
|
||||||
privateKey: await this.loadPrivateKey(), // k=
|
|
||||||
|
|
||||||
// Optional algorithm, default is derived from the key.
|
|
||||||
// Overrides whatever was set in parent object
|
|
||||||
algorithm: 'rsa-sha256',
|
algorithm: 'rsa-sha256',
|
||||||
|
canonicalization: 'relaxed/relaxed',
|
||||||
// Optional signature specifc canonicalization, overrides whatever was set in parent object
|
|
||||||
canonicalization: 'relaxed/relaxed', // c=
|
|
||||||
|
|
||||||
// Maximum number of canonicalized body bytes to sign (eg. the "l=" tag).
|
|
||||||
// Do not use though. This is available only for compatibility testing.
|
|
||||||
// maxBodyLength: 12345
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import * as paths from '../../paths.ts';
|
import * as paths from '../../paths.js';
|
||||||
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.ts';
|
import type { UnifiedEmailServer } from '../routing/classes.unified.email.server.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures email server storage settings
|
* Configures email server storage settings
|
||||||
* @param emailServer Reference to the unified email server
|
* @param emailServer Reference to the unified email server
|
||||||
* @param options Configuration options containing storage paths
|
* @param options Configuration options containing storage paths
|
||||||
*/
|
*/
|
||||||
export function configureEmailStorage(emailServer: UnifiedEmailServer, options: any): void {
|
export async function configureEmailStorage(emailServer: UnifiedEmailServer, options: any): Promise<void> {
|
||||||
// Extract the receivedEmailsPath if available
|
// Extract the receivedEmailsPath if available
|
||||||
if (options?.emailPortConfig?.receivedEmailsPath) {
|
if (options?.emailPortConfig?.receivedEmailsPath) {
|
||||||
const receivedEmailsPath = options.emailPortConfig.receivedEmailsPath;
|
const receivedEmailsPath = options.emailPortConfig.receivedEmailsPath;
|
||||||
|
|
||||||
// Ensure the directory exists
|
// Ensure the directory exists
|
||||||
plugins.smartfile.fs.ensureDirSync(receivedEmailsPath);
|
await plugins.smartfs.directory(receivedEmailsPath).recursive().create();
|
||||||
|
|
||||||
// Set path for received emails
|
// Set path for received emails
|
||||||
if (emailServer) {
|
if (emailServer) {
|
||||||
// Storage paths are now handled by the unified email server system
|
// Storage paths are now handled by the unified email server system
|
||||||
plugins.smartfile.fs.ensureDirSync(paths.receivedEmailsDir);
|
await plugins.smartfs.directory(paths.receivedEmailsDir).recursive().create();
|
||||||
|
|
||||||
console.log(`Configured email server to store received emails to: ${receivedEmailsPath}`);
|
console.log(`Configured email server to store received emails to: ${receivedEmailsPath}`);
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ export function configureEmailStorage(emailServer: UnifiedEmailServer, options:
|
|||||||
* @param emailServer Reference to the unified email server
|
* @param emailServer Reference to the unified email server
|
||||||
* @param config Configuration settings for email server
|
* @param config Configuration settings for email server
|
||||||
*/
|
*/
|
||||||
export function configureEmailServer(
|
export async function configureEmailServer(
|
||||||
emailServer: UnifiedEmailServer,
|
emailServer: UnifiedEmailServer,
|
||||||
config: {
|
config: {
|
||||||
ports?: number[];
|
ports?: number[];
|
||||||
@@ -42,7 +42,7 @@ export function configureEmailServer(
|
|||||||
};
|
};
|
||||||
storagePath?: string;
|
storagePath?: string;
|
||||||
}
|
}
|
||||||
): boolean {
|
): Promise<boolean> {
|
||||||
if (!emailServer) {
|
if (!emailServer) {
|
||||||
console.error('Email server not available');
|
console.error('Email server not available');
|
||||||
return false;
|
return false;
|
||||||
@@ -62,7 +62,7 @@ export function configureEmailServer(
|
|||||||
|
|
||||||
// Set up storage path if provided
|
// Set up storage path if provided
|
||||||
if (config.storagePath) {
|
if (config.storagePath) {
|
||||||
configureEmailStorage(emailServer, {
|
await configureEmailStorage(emailServer, {
|
||||||
emailPortConfig: {
|
emailPortConfig: {
|
||||||
receivedEmailsPath: config.storagePath
|
receivedEmailsPath: config.storagePath
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration options for rate limiter
|
* Configuration options for rate limiter
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import {
|
import {
|
||||||
SecurityLogger,
|
SecurityLogger,
|
||||||
SecurityLogLevel,
|
SecurityLogLevel,
|
||||||
SecurityEventType
|
SecurityEventType
|
||||||
} from '../../security/index.ts';
|
} from '../../security/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MtaConnectionError,
|
MtaConnectionError,
|
||||||
@@ -13,10 +13,10 @@ import {
|
|||||||
MtaConfigurationError,
|
MtaConfigurationError,
|
||||||
MtaTimeoutError,
|
MtaTimeoutError,
|
||||||
MtaProtocolError
|
MtaProtocolError
|
||||||
} from '../../errors/index.ts';
|
} from '../../errors/index.js';
|
||||||
|
|
||||||
import { Email } from '../core/classes.email.ts';
|
import { Email } from '../core/classes.email.js';
|
||||||
import type { EmailProcessingMode } from './interfaces.ts';
|
import type { EmailProcessingMode } from './interfaces.js';
|
||||||
|
|
||||||
// Custom error type extension
|
// Custom error type extension
|
||||||
interface NodeNetworkError extends Error {
|
interface NodeNetworkError extends Error {
|
||||||
@@ -851,22 +851,33 @@ export class SmtpClient {
|
|||||||
|
|
||||||
// Sign email
|
// Sign email
|
||||||
const signOptions = {
|
const signOptions = {
|
||||||
domainName: this.options.dkim.domain,
|
signingDomain: this.options.dkim.domain,
|
||||||
keySelector: this.options.dkim.selector,
|
selector: this.options.dkim.selector,
|
||||||
privateKey: this.options.dkim.privateKey,
|
privateKey: this.options.dkim.privateKey,
|
||||||
headerFieldNames: this.options.dkim.headers || [
|
canonicalization: 'relaxed/relaxed' as const,
|
||||||
'from', 'to', 'subject', 'date', 'message-id'
|
algorithm: 'rsa-sha256' as const,
|
||||||
|
signTime: new Date(),
|
||||||
|
signatureData: [
|
||||||
|
{
|
||||||
|
signingDomain: this.options.dkim.domain,
|
||||||
|
selector: this.options.dkim.selector,
|
||||||
|
privateKey: this.options.dkim.privateKey,
|
||||||
|
algorithm: 'rsa-sha256',
|
||||||
|
canonicalization: 'relaxed/relaxed',
|
||||||
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
const signedEmail = await dkimSign(emailContent, signOptions);
|
const signResult = await dkimSign(emailContent, signOptions);
|
||||||
|
|
||||||
// Replace headers in original email
|
// Add DKIM-Signature header from the signing result
|
||||||
const dkimHeader = signedEmail.substring(0, signedEmail.indexOf('\r\n\r\n')).split('\r\n')
|
if (signResult.signatures) {
|
||||||
.find(line => line.startsWith('DKIM-Signature: '));
|
const dkimHeader = signResult.signatures.split('\r\n')
|
||||||
|
.find(line => line.startsWith('DKIM-Signature: '));
|
||||||
|
|
||||||
if (dkimHeader) {
|
if (dkimHeader) {
|
||||||
email.addHeader('DKIM-Signature', dkimHeader.substring('DKIM-Signature: '.length));
|
email.addHeader('DKIM-Signature', dkimHeader.substring('DKIM-Signature: '.length));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log('debug', 'DKIM signature applied successfully');
|
logger.log('debug', 'DKIM signature applied successfully');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.ts';
|
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for rate limit configuration
|
* Interface for rate limit configuration
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
// Email delivery components
|
// Email delivery components
|
||||||
export * from './classes.emailsignjob.ts';
|
export * from './classes.emailsignjob.js';
|
||||||
export * from './classes.delivery.queue.ts';
|
export * from './classes.delivery.queue.js';
|
||||||
export * from './classes.delivery.system.ts';
|
export * from './classes.delivery.system.js';
|
||||||
|
|
||||||
// Handle exports with naming conflicts
|
// Handle exports with naming conflicts
|
||||||
export { EmailSendJob } from './classes.emailsendjob.ts';
|
export { EmailSendJob } from './classes.emailsendjob.js';
|
||||||
export { DeliveryStatus } from './classes.delivery.system.ts';
|
export { DeliveryStatus } from './classes.delivery.system.js';
|
||||||
|
|
||||||
// Rate limiter exports - fix naming conflict
|
// Rate limiter exports - fix naming conflict
|
||||||
export { RateLimiter } from './classes.ratelimiter.ts';
|
export { RateLimiter } from './classes.ratelimiter.js';
|
||||||
export type { IRateLimitConfig } from './classes.ratelimiter.ts';
|
export type { IRateLimitConfig } from './classes.ratelimiter.js';
|
||||||
|
|
||||||
// Unified rate limiter
|
// Unified rate limiter
|
||||||
export * from './classes.unified.rate.limiter.ts';
|
export * from './classes.unified.rate.limiter.js';
|
||||||
|
|
||||||
// SMTP client and configuration
|
// SMTP client and configuration
|
||||||
export * from './classes.mta.config.ts';
|
export * from './classes.mta.config.js';
|
||||||
|
|
||||||
// Import and export SMTP modules as namespaces to avoid conflicts
|
// Import and export SMTP modules as namespaces to avoid conflicts
|
||||||
import * as smtpClientMod from './smtpclient/index.ts';
|
import * as smtpClientMod from './smtpclient/index.js';
|
||||||
import * as smtpServerMod from './smtpserver/index.ts';
|
import * as smtpServerMod from './smtpserver/index.js';
|
||||||
|
|
||||||
export { smtpClientMod, smtpServerMod };
|
export { smtpClientMod, smtpServerMod };
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* SMTP and email delivery interface definitions
|
* SMTP and email delivery interface definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Email } from '../core/classes.email.ts';
|
import type { Email } from '../core/classes.email.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SMTP session state enumeration
|
* SMTP session state enumeration
|
||||||
|
|||||||
@@ -3,22 +3,22 @@
|
|||||||
* Authentication mechanisms implementation
|
* Authentication mechanisms implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AUTH_METHODS } from './constants.ts';
|
import { AUTH_METHODS } from './constants.js';
|
||||||
import type {
|
import type {
|
||||||
ISmtpConnection,
|
ISmtpConnection,
|
||||||
ISmtpAuthOptions,
|
ISmtpAuthOptions,
|
||||||
ISmtpClientOptions,
|
ISmtpClientOptions,
|
||||||
ISmtpResponse,
|
ISmtpResponse,
|
||||||
IOAuth2Options
|
IOAuth2Options
|
||||||
} from './interfaces.ts';
|
} from './interfaces.js';
|
||||||
import {
|
import {
|
||||||
encodeAuthPlain,
|
encodeAuthPlain,
|
||||||
encodeAuthLogin,
|
encodeAuthLogin,
|
||||||
generateOAuth2String,
|
generateOAuth2String,
|
||||||
isSuccessCode
|
isSuccessCode
|
||||||
} from './utils/helpers.ts';
|
} from './utils/helpers.js';
|
||||||
import { logAuthentication, logDebug } from './utils/logging.ts';
|
import { logAuthentication, logDebug } from './utils/logging.js';
|
||||||
import type { CommandHandler } from './command-handler.ts';
|
import type { CommandHandler } from './command-handler.js';
|
||||||
|
|
||||||
export class AuthHandler {
|
export class AuthHandler {
|
||||||
private options: ISmtpClientOptions;
|
private options: ISmtpClientOptions;
|
||||||
|
|||||||
@@ -4,20 +4,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
import { SMTP_COMMANDS, SMTP_CODES, LINE_ENDINGS } from './constants.ts';
|
import { SMTP_COMMANDS, SMTP_CODES, LINE_ENDINGS } from './constants.js';
|
||||||
import type {
|
import type {
|
||||||
ISmtpConnection,
|
ISmtpConnection,
|
||||||
ISmtpResponse,
|
ISmtpResponse,
|
||||||
ISmtpClientOptions,
|
ISmtpClientOptions,
|
||||||
ISmtpCapabilities
|
ISmtpCapabilities
|
||||||
} from './interfaces.ts';
|
} from './interfaces.js';
|
||||||
import {
|
import {
|
||||||
parseSmtpResponse,
|
parseSmtpResponse,
|
||||||
parseEhloResponse,
|
parseEhloResponse,
|
||||||
formatCommand,
|
formatCommand,
|
||||||
isSuccessCode
|
isSuccessCode
|
||||||
} from './utils/helpers.ts';
|
} from './utils/helpers.js';
|
||||||
import { logCommand, logDebug } from './utils/logging.ts';
|
import { logCommand, logDebug } from './utils/logging.js';
|
||||||
|
|
||||||
export class CommandHandler extends EventEmitter {
|
export class CommandHandler extends EventEmitter {
|
||||||
private options: ISmtpClientOptions;
|
private options: ISmtpClientOptions;
|
||||||
|
|||||||
@@ -6,15 +6,15 @@
|
|||||||
import * as net from 'node:net';
|
import * as net from 'node:net';
|
||||||
import * as tls from 'node:tls';
|
import * as tls from 'node:tls';
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
import { DEFAULTS, CONNECTION_STATES } from './constants.ts';
|
import { DEFAULTS, CONNECTION_STATES } from './constants.js';
|
||||||
import type {
|
import type {
|
||||||
ISmtpClientOptions,
|
ISmtpClientOptions,
|
||||||
ISmtpConnection,
|
ISmtpConnection,
|
||||||
IConnectionPoolStatus,
|
IConnectionPoolStatus,
|
||||||
ConnectionState
|
ConnectionState
|
||||||
} from './interfaces.ts';
|
} from './interfaces.js';
|
||||||
import { logConnection, logDebug } from './utils/logging.ts';
|
import { logConnection, logDebug } from './utils/logging.js';
|
||||||
import { generateConnectionId } from './utils/helpers.ts';
|
import { generateConnectionId } from './utils/helpers.js';
|
||||||
|
|
||||||
export class ConnectionManager extends EventEmitter {
|
export class ConnectionManager extends EventEmitter {
|
||||||
private options: ISmtpClientOptions;
|
private options: ISmtpClientOptions;
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
* Factory function for client creation and dependency injection
|
* Factory function for client creation and dependency injection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SmtpClient } from './smtp-client.ts';
|
import { SmtpClient } from './smtp-client.js';
|
||||||
import { ConnectionManager } from './connection-manager.ts';
|
import { ConnectionManager } from './connection-manager.js';
|
||||||
import { CommandHandler } from './command-handler.ts';
|
import { CommandHandler } from './command-handler.js';
|
||||||
import { AuthHandler } from './auth-handler.ts';
|
import { AuthHandler } from './auth-handler.js';
|
||||||
import { TlsHandler } from './tls-handler.ts';
|
import { TlsHandler } from './tls-handler.js';
|
||||||
import { SmtpErrorHandler } from './error-handler.ts';
|
import { SmtpErrorHandler } from './error-handler.js';
|
||||||
import type { ISmtpClientOptions } from './interfaces.ts';
|
import type { ISmtpClientOptions } from './interfaces.js';
|
||||||
import { validateClientOptions } from './utils/validation.ts';
|
import { validateClientOptions } from './utils/validation.js';
|
||||||
import { DEFAULTS } from './constants.ts';
|
import { DEFAULTS } from './constants.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a complete SMTP client with all components
|
* Create a complete SMTP client with all components
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* Error classification and recovery strategies
|
* Error classification and recovery strategies
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SmtpErrorType } from './constants.ts';
|
import { SmtpErrorType } from './constants.js';
|
||||||
import type { ISmtpResponse, ISmtpErrorContext, ISmtpClientOptions } from './interfaces.ts';
|
import type { ISmtpResponse, ISmtpErrorContext, ISmtpClientOptions } from './interfaces.js';
|
||||||
import { logDebug } from './utils/logging.ts';
|
import { logDebug } from './utils/logging.js';
|
||||||
|
|
||||||
export class SmtpErrorHandler {
|
export class SmtpErrorHandler {
|
||||||
private options: ISmtpClientOptions;
|
private options: ISmtpClientOptions;
|
||||||
|
|||||||
@@ -4,21 +4,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Main client class and factory
|
// Main client class and factory
|
||||||
export * from './smtp-client.ts';
|
export * from './smtp-client.js';
|
||||||
export * from './create-client.ts';
|
export * from './create-client.js';
|
||||||
|
|
||||||
// Core handlers
|
// Core handlers
|
||||||
export * from './connection-manager.ts';
|
export * from './connection-manager.js';
|
||||||
export * from './command-handler.ts';
|
export * from './command-handler.js';
|
||||||
export * from './auth-handler.ts';
|
export * from './auth-handler.js';
|
||||||
export * from './tls-handler.ts';
|
export * from './tls-handler.js';
|
||||||
export * from './error-handler.ts';
|
export * from './error-handler.js';
|
||||||
|
|
||||||
// Interfaces and types
|
// Interfaces and types
|
||||||
export * from './interfaces.ts';
|
export * from './interfaces.js';
|
||||||
export * from './constants.ts';
|
export * from './constants.js';
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
export * from './utils/validation.ts';
|
export * from './utils/validation.js';
|
||||||
export * from './utils/logging.ts';
|
export * from './utils/logging.js';
|
||||||
export * from './utils/helpers.ts';
|
export * from './utils/helpers.js';
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import type * as tls from 'node:tls';
|
import type * as tls from 'node:tls';
|
||||||
import type * as net from 'node:net';
|
import type * as net from 'node:net';
|
||||||
import type { Email } from '../../core/classes.email.ts';
|
import type { Email } from '../../core/classes.email.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SMTP client connection options
|
* SMTP client connection options
|
||||||
|
|||||||
@@ -4,22 +4,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
import type { Email } from '../../core/classes.email.ts';
|
import type { Email } from '../../core/classes.email.js';
|
||||||
import type {
|
import type {
|
||||||
ISmtpClientOptions,
|
ISmtpClientOptions,
|
||||||
ISmtpSendResult,
|
ISmtpSendResult,
|
||||||
ISmtpConnection,
|
ISmtpConnection,
|
||||||
IConnectionPoolStatus,
|
IConnectionPoolStatus,
|
||||||
ConnectionState
|
ConnectionState
|
||||||
} from './interfaces.ts';
|
} from './interfaces.js';
|
||||||
import { CONNECTION_STATES, SmtpErrorType } from './constants.ts';
|
import { CONNECTION_STATES, SmtpErrorType } from './constants.js';
|
||||||
import type { ConnectionManager } from './connection-manager.ts';
|
import type { ConnectionManager } from './connection-manager.js';
|
||||||
import type { CommandHandler } from './command-handler.ts';
|
import type { CommandHandler } from './command-handler.js';
|
||||||
import type { AuthHandler } from './auth-handler.ts';
|
import type { AuthHandler } from './auth-handler.js';
|
||||||
import type { TlsHandler } from './tls-handler.ts';
|
import type { TlsHandler } from './tls-handler.js';
|
||||||
import type { SmtpErrorHandler } from './error-handler.ts';
|
import type { SmtpErrorHandler } from './error-handler.js';
|
||||||
import { validateSender, validateRecipients } from './utils/validation.ts';
|
import { validateSender, validateRecipients } from './utils/validation.js';
|
||||||
import { logEmailSend, logPerformance, logDebug } from './utils/logging.ts';
|
import { logEmailSend, logPerformance, logDebug } from './utils/logging.js';
|
||||||
|
|
||||||
interface ISmtpClientDependencies {
|
interface ISmtpClientDependencies {
|
||||||
options: ISmtpClientOptions;
|
options: ISmtpClientOptions;
|
||||||
|
|||||||
@@ -5,16 +5,16 @@
|
|||||||
|
|
||||||
import * as tls from 'node:tls';
|
import * as tls from 'node:tls';
|
||||||
import * as net from 'node:net';
|
import * as net from 'node:net';
|
||||||
import { DEFAULTS } from './constants.ts';
|
import { DEFAULTS } from './constants.js';
|
||||||
import type {
|
import type {
|
||||||
ISmtpConnection,
|
ISmtpConnection,
|
||||||
ISmtpClientOptions,
|
ISmtpClientOptions,
|
||||||
ConnectionState
|
ConnectionState
|
||||||
} from './interfaces.ts';
|
} from './interfaces.js';
|
||||||
import { CONNECTION_STATES } from './constants.ts';
|
import { CONNECTION_STATES } from './constants.js';
|
||||||
import { logTLS, logDebug } from './utils/logging.ts';
|
import { logTLS, logDebug } from './utils/logging.js';
|
||||||
import { isSuccessCode } from './utils/helpers.ts';
|
import { isSuccessCode } from './utils/helpers.js';
|
||||||
import type { CommandHandler } from './command-handler.ts';
|
import type { CommandHandler } from './command-handler.js';
|
||||||
|
|
||||||
export class TlsHandler {
|
export class TlsHandler {
|
||||||
private options: ISmtpClientOptions;
|
private options: ISmtpClientOptions;
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
* Protocol helper functions and utilities
|
* Protocol helper functions and utilities
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SMTP_CODES, REGEX_PATTERNS, LINE_ENDINGS } from '../constants.ts';
|
import { SMTP_CODES, REGEX_PATTERNS, LINE_ENDINGS } from '../constants.js';
|
||||||
import type { ISmtpResponse, ISmtpCapabilities } from '../interfaces.ts';
|
import type { ISmtpResponse, ISmtpCapabilities } from '../interfaces.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse SMTP server response
|
* Parse SMTP server response
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
* Client-side logging utilities for SMTP operations
|
* Client-side logging utilities for SMTP operations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { logger } from '../../../../logger.ts';
|
import { logger } from '../../../../logger.js';
|
||||||
import type { ISmtpResponse, ISmtpClientOptions } from '../interfaces.ts';
|
import type { ISmtpResponse, ISmtpClientOptions } from '../interfaces.js';
|
||||||
|
|
||||||
export interface ISmtpClientLogData {
|
export interface ISmtpClientLogData {
|
||||||
component: string;
|
component: string;
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
* Input validation functions for SMTP client operations
|
* Input validation functions for SMTP client operations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { REGEX_PATTERNS } from '../constants.ts';
|
import { REGEX_PATTERNS } from '../constants.js';
|
||||||
import type { ISmtpClientOptions, ISmtpAuthOptions } from '../interfaces.ts';
|
import type { ISmtpClientOptions, ISmtpAuthOptions } from '../interfaces.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate email address format
|
* Validate email address format
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as tls from 'tls';
|
import * as tls from 'tls';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Certificate data
|
* Certificate data
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
* Responsible for parsing and handling SMTP commands
|
* Responsible for parsing and handling SMTP commands
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import { SmtpState } from './interfaces.ts';
|
import { SmtpState } from './interfaces.js';
|
||||||
import type { ISmtpSession, IEnvelopeRecipient } from './interfaces.ts';
|
import type { ISmtpSession, IEnvelopeRecipient } from './interfaces.js';
|
||||||
import type { ICommandHandler, ISmtpServer } from './interfaces.ts';
|
import type { ICommandHandler, ISmtpServer } from './interfaces.js';
|
||||||
import { SmtpCommand, SmtpResponseCode, SMTP_DEFAULTS, SMTP_EXTENSIONS } from './constants.ts';
|
import { SmtpCommand, SmtpResponseCode, SMTP_DEFAULTS, SMTP_EXTENSIONS } from './constants.js';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
import { adaptiveLogger } from './utils/adaptive-logging.ts';
|
import { adaptiveLogger } from './utils/adaptive-logging.js';
|
||||||
import { extractCommandName, extractCommandArgs, formatMultilineResponse } from './utils/helpers.ts';
|
import { extractCommandName, extractCommandArgs, formatMultilineResponse } from './utils/helpers.js';
|
||||||
import { validateEhlo, validateMailFrom, validateRcptTo, isValidCommandSequence } from './utils/validation.ts';
|
import { validateEhlo, validateMailFrom, validateRcptTo, isValidCommandSequence } from './utils/validation.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles SMTP commands and responses
|
* Handles SMTP commands and responses
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
* Responsible for managing socket connections to the SMTP server
|
* Responsible for managing socket connections to the SMTP server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import type { IConnectionManager, ISmtpServer } from './interfaces.ts';
|
import type { IConnectionManager, ISmtpServer } from './interfaces.js';
|
||||||
import { SmtpResponseCode, SMTP_DEFAULTS, SmtpState } from './constants.ts';
|
import { SmtpResponseCode, SMTP_DEFAULTS, SmtpState } from './constants.js';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
import { adaptiveLogger } from './utils/adaptive-logging.ts';
|
import { adaptiveLogger } from './utils/adaptive-logging.js';
|
||||||
import { getSocketDetails, formatMultilineResponse } from './utils/helpers.ts';
|
import { getSocketDetails, formatMultilineResponse } from './utils/helpers.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager for SMTP connections
|
* Manager for SMTP connections
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* This file contains all constants and enums used by the SMTP server
|
* This file contains all constants and enums used by the SMTP server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SmtpState } from '../interfaces.ts';
|
import { SmtpState } from '../interfaces.js';
|
||||||
|
|
||||||
// Re-export SmtpState enum from the main interfaces file
|
// Re-export SmtpState enum from the main interfaces file
|
||||||
export { SmtpState };
|
export { SmtpState };
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
* Provides a simple way to create a complete SMTP server
|
* Provides a simple way to create a complete SMTP server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SmtpServer } from './smtp-server.ts';
|
import { SmtpServer } from './smtp-server.js';
|
||||||
import { SessionManager } from './session-manager.ts';
|
import { SessionManager } from './session-manager.js';
|
||||||
import { ConnectionManager } from './connection-manager.ts';
|
import { ConnectionManager } from './connection-manager.js';
|
||||||
import { CommandHandler } from './command-handler.ts';
|
import { CommandHandler } from './command-handler.js';
|
||||||
import { DataHandler } from './data-handler.ts';
|
import { DataHandler } from './data-handler.js';
|
||||||
import { TlsHandler } from './tls-handler.ts';
|
import { TlsHandler } from './tls-handler.js';
|
||||||
import { SecurityHandler } from './security-handler.ts';
|
import { SecurityHandler } from './security-handler.js';
|
||||||
import type { ISmtpServerOptions } from './interfaces.ts';
|
import type { ISmtpServerOptions } from './interfaces.js';
|
||||||
import { UnifiedEmailServer } from '../../routing/classes.unified.email.server.ts';
|
import { UnifiedEmailServer } from '../../routing/classes.unified.email.server.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a complete SMTP server with all components
|
* Create a complete SMTP server with all components
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
* Responsible for processing email data during and after DATA command
|
* Responsible for processing email data during and after DATA command
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { SmtpState } from './interfaces.ts';
|
import { SmtpState } from './interfaces.js';
|
||||||
import type { ISmtpSession, ISmtpTransactionResult } from './interfaces.ts';
|
import type { ISmtpSession, ISmtpTransactionResult } from './interfaces.js';
|
||||||
import type { IDataHandler, ISmtpServer } from './interfaces.ts';
|
import type { IDataHandler, ISmtpServer } from './interfaces.js';
|
||||||
import { SmtpResponseCode, SMTP_PATTERNS, SMTP_DEFAULTS } from './constants.ts';
|
import { SmtpResponseCode, SMTP_PATTERNS, SMTP_DEFAULTS } from './constants.js';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
import { detectHeaderInjection } from './utils/validation.ts';
|
import { detectHeaderInjection } from './utils/validation.js';
|
||||||
import { Email } from '../../core/classes.email.ts';
|
import { Email } from '../../core/classes.email.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles SMTP DATA command and email data processing
|
* Handles SMTP DATA command and email data processing
|
||||||
|
|||||||
@@ -4,29 +4,29 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Export interfaces
|
// Export interfaces
|
||||||
export * from './interfaces.ts';
|
export * from './interfaces.js';
|
||||||
|
|
||||||
// Export server classes
|
// Export server classes
|
||||||
export { SmtpServer } from './smtp-server.ts';
|
export { SmtpServer } from './smtp-server.js';
|
||||||
export { SessionManager } from './session-manager.ts';
|
export { SessionManager } from './session-manager.js';
|
||||||
export { ConnectionManager } from './connection-manager.ts';
|
export { ConnectionManager } from './connection-manager.js';
|
||||||
export { CommandHandler } from './command-handler.ts';
|
export { CommandHandler } from './command-handler.js';
|
||||||
export { DataHandler } from './data-handler.ts';
|
export { DataHandler } from './data-handler.js';
|
||||||
export { TlsHandler } from './tls-handler.ts';
|
export { TlsHandler } from './tls-handler.js';
|
||||||
export { SecurityHandler } from './security-handler.ts';
|
export { SecurityHandler } from './security-handler.js';
|
||||||
|
|
||||||
// Export constants
|
// Export constants
|
||||||
export * from './constants.ts';
|
export * from './constants.js';
|
||||||
|
|
||||||
// Export utilities
|
// Export utilities
|
||||||
export { SmtpLogger } from './utils/logging.ts';
|
export { SmtpLogger } from './utils/logging.js';
|
||||||
export * from './utils/validation.ts';
|
export * from './utils/validation.js';
|
||||||
export * from './utils/helpers.ts';
|
export * from './utils/helpers.js';
|
||||||
|
|
||||||
// Export TLS and certificate utilities
|
// Export TLS and certificate utilities
|
||||||
export * from './certificate-utils.ts';
|
export * from './certificate-utils.js';
|
||||||
export * from './secure-server.ts';
|
export * from './secure-server.js';
|
||||||
export * from './starttls-handler.ts';
|
export * from './starttls-handler.js';
|
||||||
|
|
||||||
// Factory function to create a complete SMTP server with default components
|
// Factory function to create a complete SMTP server with default components
|
||||||
export { createSmtpServer } from './create-server.ts';
|
export { createSmtpServer } from './create-server.js';
|
||||||
@@ -3,15 +3,15 @@
|
|||||||
* Defines all the interfaces used by the SMTP server implementation
|
* Defines all the interfaces used by the SMTP server implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import type { Email } from '../../core/classes.email.ts';
|
import type { Email } from '../../core/classes.email.js';
|
||||||
import type { UnifiedEmailServer } from '../../routing/classes.unified.email.server.ts';
|
import type { UnifiedEmailServer } from '../../routing/classes.unified.email.server.js';
|
||||||
|
|
||||||
// Re-export types from other modules
|
// Re-export types from other modules
|
||||||
import { SmtpState } from '../interfaces.ts';
|
import { SmtpState } from '../interfaces.js';
|
||||||
import { SmtpCommand } from './constants.ts';
|
import { SmtpCommand } from './constants.js';
|
||||||
export { SmtpState, SmtpCommand };
|
export { SmtpState, SmtpCommand };
|
||||||
export type { IEnvelopeRecipient } from '../interfaces.ts';
|
export type { IEnvelopeRecipient } from '../interfaces.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for components that need cleanup
|
* Interface for components that need cleanup
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
* Provides helper functions for creating and managing secure TLS server
|
* Provides helper functions for creating and managing secure TLS server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import {
|
import {
|
||||||
loadCertificatesFromString,
|
loadCertificatesFromString,
|
||||||
generateSelfSignedCertificates,
|
generateSelfSignedCertificates,
|
||||||
createTlsOptions,
|
createTlsOptions,
|
||||||
type ICertificateData
|
type ICertificateData
|
||||||
} from './certificate-utils.ts';
|
} from './certificate-utils.js';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a secure TLS server for direct TLS connections
|
* Create a secure TLS server for direct TLS connections
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
* email validation, and authentication
|
* email validation, and authentication
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import type { ISmtpSession, ISmtpAuth } from './interfaces.ts';
|
import type { ISmtpSession, ISmtpAuth } from './interfaces.js';
|
||||||
import type { ISecurityHandler, ISmtpServer } from './interfaces.ts';
|
import type { ISecurityHandler, ISmtpServer } from './interfaces.js';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
import { SecurityEventType, SecurityLogLevel } from './constants.ts';
|
import { SecurityEventType, SecurityLogLevel } from './constants.js';
|
||||||
import { isValidEmail } from './utils/validation.ts';
|
import { isValidEmail } from './utils/validation.js';
|
||||||
import { getSocketDetails, getTlsDetails } from './utils/helpers.ts';
|
import { getSocketDetails, getTlsDetails } from './utils/helpers.js';
|
||||||
import { IPReputationChecker } from '../../../security/classes.ipreputationchecker.ts';
|
import { IPReputationChecker } from '../../../security/classes.ipreputationchecker.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for IP denylist entry
|
* Interface for IP denylist entry
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
* Responsible for creating, managing, and cleaning up SMTP sessions
|
* Responsible for creating, managing, and cleaning up SMTP sessions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import { SmtpState } from './interfaces.ts';
|
import { SmtpState } from './interfaces.js';
|
||||||
import type { ISmtpSession, ISmtpEnvelope } from './interfaces.ts';
|
import type { ISmtpSession, ISmtpEnvelope } from './interfaces.js';
|
||||||
import type { ISessionManager, ISessionEvents } from './interfaces.ts';
|
import type { ISessionManager, ISessionEvents } from './interfaces.js';
|
||||||
import { SMTP_DEFAULTS } from './constants.ts';
|
import { SMTP_DEFAULTS } from './constants.js';
|
||||||
import { generateSessionId, getSocketDetails } from './utils/helpers.ts';
|
import { generateSessionId, getSocketDetails } from './utils/helpers.js';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager for SMTP sessions
|
* Manager for SMTP sessions
|
||||||
|
|||||||
@@ -3,21 +3,21 @@
|
|||||||
* Core implementation for the refactored SMTP server
|
* Core implementation for the refactored SMTP server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import { SmtpState } from './interfaces.ts';
|
import { SmtpState } from './interfaces.js';
|
||||||
import type { ISmtpServerOptions } from './interfaces.ts';
|
import type { ISmtpServerOptions } from './interfaces.js';
|
||||||
import type { ISmtpServer, ISmtpServerConfig, ISessionManager, IConnectionManager, ICommandHandler, IDataHandler, ITlsHandler, ISecurityHandler } from './interfaces.ts';
|
import type { ISmtpServer, ISmtpServerConfig, ISessionManager, IConnectionManager, ICommandHandler, IDataHandler, ITlsHandler, ISecurityHandler } from './interfaces.js';
|
||||||
import { SessionManager } from './session-manager.ts';
|
import { SessionManager } from './session-manager.js';
|
||||||
import { ConnectionManager } from './connection-manager.ts';
|
import { ConnectionManager } from './connection-manager.js';
|
||||||
import { CommandHandler } from './command-handler.ts';
|
import { CommandHandler } from './command-handler.js';
|
||||||
import { DataHandler } from './data-handler.ts';
|
import { DataHandler } from './data-handler.js';
|
||||||
import { TlsHandler } from './tls-handler.ts';
|
import { TlsHandler } from './tls-handler.js';
|
||||||
import { SecurityHandler } from './security-handler.ts';
|
import { SecurityHandler } from './security-handler.js';
|
||||||
import { SMTP_DEFAULTS } from './constants.ts';
|
import { SMTP_DEFAULTS } from './constants.js';
|
||||||
import { mergeWithDefaults } from './utils/helpers.ts';
|
import { mergeWithDefaults } from './utils/helpers.js';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
import { adaptiveLogger } from './utils/adaptive-logging.ts';
|
import { adaptiveLogger } from './utils/adaptive-logging.js';
|
||||||
import { UnifiedEmailServer } from '../../routing/classes.unified.email.server.ts';
|
import { UnifiedEmailServer } from '../../routing/classes.unified.email.server.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SMTP Server implementation
|
* SMTP Server implementation
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
* Provides an improved implementation for STARTTLS upgrades
|
* Provides an improved implementation for STARTTLS upgrades
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
import {
|
import {
|
||||||
loadCertificatesFromString,
|
loadCertificatesFromString,
|
||||||
createTlsOptions,
|
createTlsOptions,
|
||||||
type ICertificateData
|
type ICertificateData
|
||||||
} from './certificate-utils.ts';
|
} from './certificate-utils.js';
|
||||||
import { getSocketDetails } from './utils/helpers.ts';
|
import { getSocketDetails } from './utils/helpers.js';
|
||||||
import type { ISmtpSession, ISessionManager, IConnectionManager } from './interfaces.ts';
|
import type { ISmtpSession, ISessionManager, IConnectionManager } from './interfaces.js';
|
||||||
import { SmtpState } from '../interfaces.ts';
|
import { SmtpState } from '../interfaces.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enhanced STARTTLS handler for more reliable TLS upgrades
|
* Enhanced STARTTLS handler for more reliable TLS upgrades
|
||||||
|
|||||||
@@ -3,18 +3,18 @@
|
|||||||
* Responsible for handling TLS-related SMTP functionality
|
* Responsible for handling TLS-related SMTP functionality
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../plugins.ts';
|
import * as plugins from '../../../plugins.js';
|
||||||
import type { ITlsHandler, ISmtpServer, ISmtpSession } from './interfaces.ts';
|
import type { ITlsHandler, ISmtpServer, ISmtpSession } from './interfaces.js';
|
||||||
import { SmtpResponseCode, SecurityEventType, SecurityLogLevel } from './constants.ts';
|
import { SmtpResponseCode, SecurityEventType, SecurityLogLevel } from './constants.js';
|
||||||
import { SmtpLogger } from './utils/logging.ts';
|
import { SmtpLogger } from './utils/logging.js';
|
||||||
import { getSocketDetails, getTlsDetails } from './utils/helpers.ts';
|
import { getSocketDetails, getTlsDetails } from './utils/helpers.js';
|
||||||
import {
|
import {
|
||||||
loadCertificatesFromString,
|
loadCertificatesFromString,
|
||||||
generateSelfSignedCertificates,
|
generateSelfSignedCertificates,
|
||||||
createTlsOptions,
|
createTlsOptions,
|
||||||
type ICertificateData
|
type ICertificateData
|
||||||
} from './certificate-utils.ts';
|
} from './certificate-utils.js';
|
||||||
import { SmtpState } from '../interfaces.ts';
|
import { SmtpState } from '../interfaces.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles TLS functionality for SMTP server
|
* Handles TLS functionality for SMTP server
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
* to maintain performance during high-concurrency scenarios
|
* to maintain performance during high-concurrency scenarios
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../../plugins.ts';
|
import * as plugins from '../../../../plugins.js';
|
||||||
import { logger } from '../../../../logger.ts';
|
import { logger } from '../../../../logger.js';
|
||||||
import { SecurityLogLevel, SecurityEventType } from '../constants.ts';
|
import { SecurityLogLevel, SecurityEventType } from '../constants.js';
|
||||||
import type { ISmtpSession } from '../interfaces.ts';
|
import type { ISmtpSession } from '../interfaces.js';
|
||||||
import type { LogLevel, ISmtpLogOptions } from './logging.ts';
|
import type { LogLevel, ISmtpLogOptions } from './logging.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log modes based on server load
|
* Log modes based on server load
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* Provides utility functions for SMTP server implementation
|
* Provides utility functions for SMTP server implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../../plugins.ts';
|
import * as plugins from '../../../../plugins.js';
|
||||||
import { SMTP_DEFAULTS } from '../constants.ts';
|
import { SMTP_DEFAULTS } from '../constants.js';
|
||||||
import type { ISmtpSession, ISmtpServerOptions } from '../interfaces.ts';
|
import type { ISmtpSession, ISmtpServerOptions } from '../interfaces.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a multi-line SMTP response according to RFC 5321
|
* Formats a multi-line SMTP response according to RFC 5321
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
* Provides structured logging for SMTP server components
|
* Provides structured logging for SMTP server components
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as plugins from '../../../../plugins.ts';
|
import * as plugins from '../../../../plugins.js';
|
||||||
import { logger } from '../../../../logger.ts';
|
import { logger } from '../../../../logger.js';
|
||||||
import { SecurityLogLevel, SecurityEventType } from '../constants.ts';
|
import { SecurityLogLevel, SecurityEventType } from '../constants.js';
|
||||||
import type { ISmtpSession } from '../interfaces.ts';
|
import type { ISmtpSession } from '../interfaces.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SMTP connection metadata to include in logs
|
* SMTP connection metadata to include in logs
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
* Provides validation functions for SMTP server
|
* Provides validation functions for SMTP server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SmtpState } from '../interfaces.ts';
|
import { SmtpState } from '../interfaces.js';
|
||||||
import { SMTP_PATTERNS } from '../constants.ts';
|
import { SMTP_PATTERNS } from '../constants.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Header injection patterns to detect malicious input
|
* Header injection patterns to detect malicious input
|
||||||
@@ -88,7 +88,7 @@ export function sanitizeInput(input: string): string {
|
|||||||
.replace(/%0[aAdD]/gi, '') // Remove URL encoded CRLF
|
.replace(/%0[aAdD]/gi, '') // Remove URL encoded CRLF
|
||||||
.trim();
|
.trim();
|
||||||
}
|
}
|
||||||
import { SmtpLogger } from './logging.ts';
|
import { SmtpLogger } from './logging.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates an email address
|
* Validates an email address
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
// Export all mail modules for simplified imports
|
// Export all mail modules for simplified imports
|
||||||
export * from './routing/index.ts';
|
export * from './routing/index.js';
|
||||||
export * from './security/index.ts';
|
export * from './security/index.js';
|
||||||
|
|
||||||
// Make the core and delivery modules accessible
|
// Make the core and delivery modules accessible
|
||||||
import * as Core from './core/index.ts';
|
import * as Core from './core/index.js';
|
||||||
import * as Delivery from './delivery/index.ts';
|
import * as Delivery from './delivery/index.js';
|
||||||
|
|
||||||
export { Core, Delivery };
|
export { Core, Delivery };
|
||||||
|
|
||||||
// For direct imports
|
// For direct imports
|
||||||
import { Email } from './core/classes.email.ts';
|
import { Email } from './core/classes.email.js';
|
||||||
import { DcRouter } from '../classes.dcrouter.ts';
|
|
||||||
|
|
||||||
// Re-export commonly used classes
|
// Re-export commonly used classes
|
||||||
export {
|
export {
|
||||||
Email,
|
Email,
|
||||||
DcRouter
|
|
||||||
};
|
};
|
||||||
@@ -1,8 +1,18 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import type { IEmailDomainConfig } from './interfaces.ts';
|
import type { IEmailDomainConfig } from './interfaces.js';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import type { DcRouter } from '../../classes.dcrouter.ts';
|
/** External DcRouter interface shape used by DnsManager */
|
||||||
import type { StorageManager } from '../../storage/index.ts';
|
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
|
* DNS validation result
|
||||||
@@ -30,10 +40,10 @@ interface IDnsRecords {
|
|||||||
* Handles both validation and creation of DNS records
|
* Handles both validation and creation of DNS records
|
||||||
*/
|
*/
|
||||||
export class DnsManager {
|
export class DnsManager {
|
||||||
private dcRouter: DcRouter;
|
private dcRouter: IDcRouterLike;
|
||||||
private storageManager: StorageManager;
|
private storageManager: IStorageManagerLike;
|
||||||
|
|
||||||
constructor(dcRouter: DcRouter) {
|
constructor(dcRouter: IDcRouterLike) {
|
||||||
this.dcRouter = dcRouter;
|
this.dcRouter = dcRouter;
|
||||||
this.storageManager = dcRouter.storageManager;
|
this.storageManager = dcRouter.storageManager;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import * as paths from '../../paths.ts';
|
import * as paths from '../../paths.js';
|
||||||
import { DKIMCreator } from '../security/classes.dkimcreator.ts';
|
import { DKIMCreator } from '../security/classes.dkimcreator.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for DNS record information
|
* Interface for DNS record information
|
||||||
@@ -57,7 +57,7 @@ export class DNSManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the DNS records directory exists
|
// Ensure the DNS records directory exists
|
||||||
plugins.smartfile.fs.ensureDirSync(paths.dnsRecordsDir);
|
plugins.fs.mkdirSync(paths.dnsRecordsDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -417,7 +417,7 @@ export class DNSManager {
|
|||||||
public async saveDnsRecommendations(domain: string, records: IDnsRecord[]): Promise<void> {
|
public async saveDnsRecommendations(domain: string, records: IDnsRecord[]): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const filePath = plugins.path.join(paths.dnsRecordsDir, `${domain}.recommendations.json`);
|
const filePath = plugins.path.join(paths.dnsRecordsDir, `${domain}.recommendations.json`);
|
||||||
plugins.smartfile.memory.toFsSync(JSON.stringify(records, null, 2), filePath);
|
await plugins.smartfs.file(filePath).write(JSON.stringify(records, null, 2));
|
||||||
console.log(`DNS recommendations for ${domain} saved to ${filePath}`);
|
console.log(`DNS recommendations for ${domain} saved to ${filePath}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error saving DNS recommendations for ${domain}:`, error);
|
console.error(`Error saving DNS recommendations for ${domain}:`, error);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { IEmailDomainConfig } from './interfaces.ts';
|
import type { IEmailDomainConfig } from './interfaces.js';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registry for email domain configurations
|
* Registry for email domain configurations
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { EmailProcessingMode } from '../delivery/interfaces.ts';
|
import type { EmailProcessingMode } from '../delivery/interfaces.js';
|
||||||
|
|
||||||
// Re-export EmailProcessingMode type
|
// Re-export EmailProcessingMode type
|
||||||
export type { EmailProcessingMode };
|
export type { EmailProcessingMode };
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
import type { IEmailRoute, IEmailMatch, IEmailAction, IEmailContext } from './interfaces.ts';
|
import type { IEmailRoute, IEmailMatch, IEmailAction, IEmailContext } from './interfaces.js';
|
||||||
import type { Email } from '../core/classes.email.ts';
|
import type { Email } from '../core/classes.email.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Email router that evaluates routes and determines actions
|
* Email router that evaluates routes and determines actions
|
||||||
|
|||||||
@@ -1,35 +1,63 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import * as paths from '../../paths.ts';
|
import * as paths from '../../paths.js';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import {
|
import {
|
||||||
SecurityLogger,
|
SecurityLogger,
|
||||||
SecurityLogLevel,
|
SecurityLogLevel,
|
||||||
SecurityEventType
|
SecurityEventType
|
||||||
} from '../../security/index.ts';
|
} from '../../security/index.js';
|
||||||
import { DKIMCreator } from '../security/classes.dkimcreator.ts';
|
import { DKIMCreator } from '../security/classes.dkimcreator.js';
|
||||||
import { IPReputationChecker } from '../../security/classes.ipreputationchecker.ts';
|
import { IPReputationChecker } from '../../security/classes.ipreputationchecker.js';
|
||||||
import {
|
// Deliverability types (IPWarmupManager and SenderReputationMonitor are optional external modules)
|
||||||
IPWarmupManager,
|
interface IIPWarmupConfig {
|
||||||
type IIPWarmupConfig,
|
enabled?: boolean;
|
||||||
SenderReputationMonitor,
|
ips?: string[];
|
||||||
type IReputationMonitorConfig
|
[key: string]: any;
|
||||||
} from '../../deliverability/index.ts';
|
}
|
||||||
import { EmailRouter } from './classes.email.router.ts';
|
interface IReputationMonitorConfig {
|
||||||
import type { IEmailRoute, IEmailAction, IEmailContext, IEmailDomainConfig } from './interfaces.ts';
|
enabled?: boolean;
|
||||||
import { Email } from '../core/classes.email.ts';
|
domains?: string[];
|
||||||
import { DomainRegistry } from './classes.domain.registry.ts';
|
[key: string]: any;
|
||||||
import { DnsManager } from './classes.dns.manager.ts';
|
}
|
||||||
import { BounceManager, BounceType, BounceCategory } from '../core/classes.bouncemanager.ts';
|
interface IPWarmupManager {
|
||||||
import { createSmtpServer } from '../delivery/smtpserver/index.ts';
|
getWarmupStatus(ip: string): any;
|
||||||
import { createPooledSmtpClient } from '../delivery/smtpclient/create-client.ts';
|
addIPToWarmup(ip: string, config?: any): void;
|
||||||
import type { SmtpClient } from '../delivery/smtpclient/smtp-client.ts';
|
removeIPFromWarmup(ip: string): void;
|
||||||
import { MultiModeDeliverySystem, type IMultiModeDeliveryOptions } from '../delivery/classes.delivery.system.ts';
|
updateMetrics(ip: string, metrics: any): void;
|
||||||
import { UnifiedDeliveryQueue, type IQueueOptions } from '../delivery/classes.delivery.queue.ts';
|
canSendMoreToday(ip: string): boolean;
|
||||||
import { UnifiedRateLimiter, type IHierarchicalRateLimits } from '../delivery/classes.unified.rate.limiter.ts';
|
canSendMoreThisHour(ip: string): boolean;
|
||||||
import { SmtpState } from '../delivery/interfaces.ts';
|
getBestIPForSending(...args: any[]): string | null;
|
||||||
import type { EmailProcessingMode, ISmtpSession as IBaseSmtpSession } from '../delivery/interfaces.ts';
|
setActiveAllocationPolicy(policy: string): void;
|
||||||
import type { DcRouter } from '../../classes.dcrouter.ts';
|
recordSend(...args: any[]): void;
|
||||||
|
}
|
||||||
|
interface SenderReputationMonitor {
|
||||||
|
getReputationData(domain: string): any;
|
||||||
|
getReputationSummary(): any;
|
||||||
|
addDomain(domain: string): void;
|
||||||
|
removeDomain(domain: string): void;
|
||||||
|
recordSendEvent(domain: string, event: any): void;
|
||||||
|
}
|
||||||
|
import { EmailRouter } from './classes.email.router.js';
|
||||||
|
import type { IEmailRoute, IEmailAction, IEmailContext, IEmailDomainConfig } from './interfaces.js';
|
||||||
|
import { Email } from '../core/classes.email.js';
|
||||||
|
import { DomainRegistry } from './classes.domain.registry.js';
|
||||||
|
import { DnsManager } from './classes.dns.manager.js';
|
||||||
|
import { BounceManager, BounceType, BounceCategory } from '../core/classes.bouncemanager.js';
|
||||||
|
import { createSmtpServer } from '../delivery/smtpserver/index.js';
|
||||||
|
import { createPooledSmtpClient } from '../delivery/smtpclient/create-client.js';
|
||||||
|
import type { SmtpClient } from '../delivery/smtpclient/smtp-client.js';
|
||||||
|
import { MultiModeDeliverySystem, type IMultiModeDeliveryOptions } from '../delivery/classes.delivery.system.js';
|
||||||
|
import { UnifiedDeliveryQueue, type IQueueOptions } from '../delivery/classes.delivery.queue.js';
|
||||||
|
import { UnifiedRateLimiter, type IHierarchicalRateLimits } from '../delivery/classes.unified.rate.limiter.js';
|
||||||
|
import { SmtpState } from '../delivery/interfaces.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
|
* Extended SMTP session interface with route information
|
||||||
@@ -127,7 +155,7 @@ export interface ISmtpSession extends IBaseSmtpSession {
|
|||||||
/**
|
/**
|
||||||
* Authentication data for SMTP
|
* Authentication data for SMTP
|
||||||
*/
|
*/
|
||||||
import type { ISmtpAuth } from '../delivery/interfaces.ts';
|
import type { ISmtpAuth } from '../delivery/interfaces.js';
|
||||||
export type IAuthData = ISmtpAuth;
|
export type IAuthData = ISmtpAuth;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,8 +194,8 @@ export class UnifiedEmailServer extends EventEmitter {
|
|||||||
public dkimCreator: DKIMCreator;
|
public dkimCreator: DKIMCreator;
|
||||||
private ipReputationChecker: IPReputationChecker; // TODO: Implement IP reputation checks in processEmailByMode
|
private ipReputationChecker: IPReputationChecker; // TODO: Implement IP reputation checks in processEmailByMode
|
||||||
private bounceManager: BounceManager;
|
private bounceManager: BounceManager;
|
||||||
private ipWarmupManager: IPWarmupManager;
|
private ipWarmupManager: IPWarmupManager | null;
|
||||||
private senderReputationMonitor: SenderReputationMonitor;
|
private senderReputationMonitor: SenderReputationMonitor | null;
|
||||||
public deliveryQueue: UnifiedDeliveryQueue;
|
public deliveryQueue: UnifiedDeliveryQueue;
|
||||||
public deliverySystem: MultiModeDeliverySystem;
|
public deliverySystem: MultiModeDeliverySystem;
|
||||||
private rateLimiter: UnifiedRateLimiter; // TODO: Implement rate limiting in SMTP server handlers
|
private rateLimiter: UnifiedRateLimiter; // TODO: Implement rate limiting in SMTP server handlers
|
||||||
@@ -206,21 +234,10 @@ export class UnifiedEmailServer extends EventEmitter {
|
|||||||
storageManager: dcRouter.storageManager
|
storageManager: dcRouter.storageManager
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize IP warmup manager
|
// IP warmup manager and sender reputation monitor are optional
|
||||||
this.ipWarmupManager = IPWarmupManager.getInstance(options.ipWarmupConfig || {
|
// They will be initialized when the deliverability module is available
|
||||||
enabled: true,
|
this.ipWarmupManager = null;
|
||||||
ipAddresses: [],
|
this.senderReputationMonitor = null;
|
||||||
targetDomains: []
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize sender reputation monitor with storage manager
|
|
||||||
this.senderReputationMonitor = SenderReputationMonitor.getInstance(
|
|
||||||
options.reputationMonitorConfig || {
|
|
||||||
enabled: true,
|
|
||||||
domains: []
|
|
||||||
},
|
|
||||||
dcRouter.storageManager
|
|
||||||
);
|
|
||||||
|
|
||||||
// Initialize domain registry
|
// Initialize domain registry
|
||||||
this.domainRegistry = new DomainRegistry(options.domains, options.defaults);
|
this.domainRegistry = new DomainRegistry(options.domains, options.defaults);
|
||||||
@@ -836,15 +853,21 @@ export class UnifiedEmailServer extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sign the email
|
// Sign the email
|
||||||
|
const dkimDomain = options.dkimOptions.domainName;
|
||||||
|
const dkimSelector = options.dkimOptions.keySelector || 'mta';
|
||||||
|
const dkimPrivateKey = (await this.dkimCreator.readDKIMKeys(dkimDomain)).privateKey;
|
||||||
const signResult = await plugins.dkimSign(rawEmail, {
|
const signResult = await plugins.dkimSign(rawEmail, {
|
||||||
|
signingDomain: dkimDomain,
|
||||||
|
selector: dkimSelector,
|
||||||
|
privateKey: dkimPrivateKey,
|
||||||
canonicalization: 'relaxed/relaxed',
|
canonicalization: 'relaxed/relaxed',
|
||||||
algorithm: 'rsa-sha256',
|
algorithm: 'rsa-sha256',
|
||||||
signTime: new Date(),
|
signTime: new Date(),
|
||||||
signatureData: [
|
signatureData: [
|
||||||
{
|
{
|
||||||
signingDomain: options.dkimOptions.domainName,
|
signingDomain: dkimDomain,
|
||||||
selector: options.dkimOptions.keySelector || 'mta',
|
selector: dkimSelector,
|
||||||
privateKey: (await this.dkimCreator.readDKIMKeys(options.dkimOptions.domainName)).privateKey,
|
privateKey: dkimPrivateKey,
|
||||||
algorithm: 'rsa-sha256',
|
algorithm: 'rsa-sha256',
|
||||||
canonicalization: 'relaxed/relaxed'
|
canonicalization: 'relaxed/relaxed'
|
||||||
}
|
}
|
||||||
@@ -1435,6 +1458,9 @@ export class UnifiedEmailServer extends EventEmitter {
|
|||||||
|
|
||||||
// Sign the email
|
// Sign the email
|
||||||
const signResult = await plugins.dkimSign(rawEmail, {
|
const signResult = await plugins.dkimSign(rawEmail, {
|
||||||
|
signingDomain: domain,
|
||||||
|
selector: selector,
|
||||||
|
privateKey: privateKey,
|
||||||
canonicalization: 'relaxed/relaxed',
|
canonicalization: 'relaxed/relaxed',
|
||||||
algorithm: 'rsa-sha256',
|
algorithm: 'rsa-sha256',
|
||||||
signTime: new Date(),
|
signTime: new Date(),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Email routing components
|
// Email routing components
|
||||||
export * from './classes.email.router.ts';
|
export * from './classes.email.router.js';
|
||||||
export * from './classes.unified.email.server.ts';
|
export * from './classes.unified.email.server.js';
|
||||||
export * from './classes.dns.manager.ts';
|
export * from './classes.dns.manager.js';
|
||||||
export * from './interfaces.ts';
|
export * from './interfaces.js';
|
||||||
export * from './classes.domain.registry.ts';
|
export * from './classes.domain.registry.js';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Email } from '../core/classes.email.ts';
|
import type { Email } from '../core/classes.email.js';
|
||||||
import type { IExtendedSmtpSession } from './classes.unified.email.server.ts';
|
import type { IExtendedSmtpSession } from './classes.unified.email.server.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route configuration for email routing
|
* Route configuration for email routing
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import * as paths from '../../paths.ts';
|
import * as paths from '../../paths.js';
|
||||||
|
|
||||||
import { Email } from '../core/classes.email.ts';
|
import { Email } from '../core/classes.email.js';
|
||||||
// MtaService reference removed
|
// MtaService reference removed
|
||||||
|
|
||||||
const readFile = plugins.util.promisify(plugins.fs.readFile);
|
const readFile = plugins.util.promisify(plugins.fs.readFile);
|
||||||
@@ -46,8 +46,8 @@ export class DKIMCreator {
|
|||||||
console.log(`No DKIM keys found for ${domainArg}. Generating...`);
|
console.log(`No DKIM keys found for ${domainArg}. Generating...`);
|
||||||
await this.createAndStoreDKIMKeys(domainArg);
|
await this.createAndStoreDKIMKeys(domainArg);
|
||||||
const dnsValue = await this.getDNSRecordForDomain(domainArg);
|
const dnsValue = await this.getDNSRecordForDomain(domainArg);
|
||||||
plugins.smartfile.fs.ensureDirSync(paths.dnsRecordsDir);
|
await plugins.smartfs.directory(paths.dnsRecordsDir).recursive().create();
|
||||||
plugins.smartfile.memory.toFsSync(JSON.stringify(dnsValue, null, 2), plugins.path.join(paths.dnsRecordsDir, `${domainArg}.dkimrecord.json`));
|
await plugins.smartfs.file(plugins.path.join(paths.dnsRecordsDir, `${domainArg}.dkimrecord.json`)).write(JSON.stringify(dnsValue, null, 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
// MtaService reference removed
|
// MtaService reference removed
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.ts';
|
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result of a DKIM verification
|
* Result of a DKIM verification
|
||||||
@@ -66,10 +66,10 @@ export class DKIMVerifier {
|
|||||||
|
|
||||||
const result: IDkimVerificationResult = {
|
const result: IDkimVerificationResult = {
|
||||||
isValid,
|
isValid,
|
||||||
domain: dkimResult.domain,
|
domain: dkimResult.signingDomain,
|
||||||
selector: dkimResult.selector,
|
selector: dkimResult.selector,
|
||||||
status: dkimResult.status.result,
|
status: dkimResult.status.result,
|
||||||
signatureFields: dkimResult.signature,
|
signatureFields: (dkimResult as any).signature,
|
||||||
details: options.returnDetails ? verificationMailauth : undefined
|
details: options.returnDetails ? verificationMailauth : undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,19 +79,19 @@ export class DKIMVerifier {
|
|||||||
timestamp: Date.now()
|
timestamp: Date.now()
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.log(isValid ? 'info' : 'warn', `DKIM Verification using mailauth: ${isValid ? 'pass' : 'fail'} for domain ${dkimResult.domain}`);
|
logger.log(isValid ? 'info' : 'warn', `DKIM Verification using mailauth: ${isValid ? 'pass' : 'fail'} for domain ${dkimResult.signingDomain}`);
|
||||||
|
|
||||||
// Enhanced security logging
|
// Enhanced security logging
|
||||||
SecurityLogger.getInstance().logEvent({
|
SecurityLogger.getInstance().logEvent({
|
||||||
level: isValid ? SecurityLogLevel.INFO : SecurityLogLevel.WARN,
|
level: isValid ? SecurityLogLevel.INFO : SecurityLogLevel.WARN,
|
||||||
type: SecurityEventType.DKIM,
|
type: SecurityEventType.DKIM,
|
||||||
message: `DKIM verification ${isValid ? 'passed' : 'failed'} for domain ${dkimResult.domain}`,
|
message: `DKIM verification ${isValid ? 'passed' : 'failed'} for domain ${dkimResult.signingDomain}`,
|
||||||
details: {
|
details: {
|
||||||
selector: dkimResult.selector,
|
selector: dkimResult.selector,
|
||||||
signatureFields: dkimResult.signature,
|
signatureFields: (dkimResult as any).signature,
|
||||||
result: dkimResult.status.result
|
result: dkimResult.status.result
|
||||||
},
|
},
|
||||||
domain: dkimResult.domain,
|
domain: dkimResult.signingDomain,
|
||||||
success: isValid
|
success: isValid
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.ts';
|
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js';
|
||||||
// MtaService reference removed
|
// MtaService reference removed
|
||||||
import type { Email } from '../core/classes.email.ts';
|
import type { Email } from '../core/classes.email.js';
|
||||||
import type { IDnsVerificationResult } from '../routing/classes.dnsmanager.ts';
|
import type { IDnsVerificationResult } from '../routing/classes.dnsmanager.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DMARC policy types
|
* DMARC policy types
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as plugins from '../../plugins.ts';
|
import * as plugins from '../../plugins.js';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.js';
|
||||||
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.ts';
|
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js';
|
||||||
// MtaService reference removed
|
// MtaService reference removed
|
||||||
import type { Email } from '../core/classes.email.ts';
|
import type { Email } from '../core/classes.email.js';
|
||||||
import type { IDnsVerificationResult } from '../routing/classes.dnsmanager.ts';
|
import type { IDnsVerificationResult } from '../routing/classes.dnsmanager.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SPF result qualifiers
|
* SPF result qualifiers
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Email security components
|
// Email security components
|
||||||
export * from './classes.dkimcreator.ts';
|
export * from './classes.dkimcreator.js';
|
||||||
export * from './classes.dkimverifier.ts';
|
export * from './classes.dkimverifier.js';
|
||||||
export * from './classes.dmarcverifier.ts';
|
export * from './classes.dmarcverifier.js';
|
||||||
export * from './classes.spfverifier.ts';
|
export * from './classes.spfverifier.js';
|
||||||
20
ts/paths.ts
20
ts/paths.ts
@@ -32,17 +32,17 @@ export const configPath = process.env.CONFIG_PATH
|
|||||||
: plugins.path.join(baseDir, 'config.json');
|
: plugins.path.join(baseDir, 'config.json');
|
||||||
|
|
||||||
// Create directories if they don't exist
|
// Create directories if they don't exist
|
||||||
export function ensureDirectories() {
|
export async function ensureDirectories() {
|
||||||
// Ensure data directories
|
// Ensure data directories
|
||||||
plugins.smartfile.fs.ensureDirSync(dataDir);
|
await plugins.smartfs.directory(dataDir).recursive().create();
|
||||||
plugins.smartfile.fs.ensureDirSync(keysDir);
|
await plugins.smartfs.directory(keysDir).recursive().create();
|
||||||
plugins.smartfile.fs.ensureDirSync(dnsRecordsDir);
|
await plugins.smartfs.directory(dnsRecordsDir).recursive().create();
|
||||||
plugins.smartfile.fs.ensureDirSync(sentEmailsDir);
|
await plugins.smartfs.directory(sentEmailsDir).recursive().create();
|
||||||
plugins.smartfile.fs.ensureDirSync(receivedEmailsDir);
|
await plugins.smartfs.directory(receivedEmailsDir).recursive().create();
|
||||||
plugins.smartfile.fs.ensureDirSync(failedEmailsDir);
|
await plugins.smartfs.directory(failedEmailsDir).recursive().create();
|
||||||
plugins.smartfile.fs.ensureDirSync(logsDir);
|
await plugins.smartfs.directory(logsDir).recursive().create();
|
||||||
|
|
||||||
// Ensure email template directories
|
// Ensure email template directories
|
||||||
plugins.smartfile.fs.ensureDirSync(emailTemplatesDir);
|
await plugins.smartfs.directory(emailTemplatesDir).recursive().create();
|
||||||
plugins.smartfile.fs.ensureDirSync(MtaAttachmentsDir);
|
await plugins.smartfs.directory(MtaAttachmentsDir).recursive().create();
|
||||||
}
|
}
|
||||||
@@ -46,6 +46,7 @@ import * as smartacme from '@push.rocks/smartacme';
|
|||||||
import * as smartdata from '@push.rocks/smartdata';
|
import * as smartdata from '@push.rocks/smartdata';
|
||||||
import * as smartdns from '@push.rocks/smartdns';
|
import * as smartdns from '@push.rocks/smartdns';
|
||||||
import * as smartfile from '@push.rocks/smartfile';
|
import * as smartfile from '@push.rocks/smartfile';
|
||||||
|
import { SmartFs, SmartFsProviderNode } from '@push.rocks/smartfs';
|
||||||
import * as smartguard from '@push.rocks/smartguard';
|
import * as smartguard from '@push.rocks/smartguard';
|
||||||
import * as smartjwt from '@push.rocks/smartjwt';
|
import * as smartjwt from '@push.rocks/smartjwt';
|
||||||
import * as smartlog from '@push.rocks/smartlog';
|
import * as smartlog from '@push.rocks/smartlog';
|
||||||
@@ -60,7 +61,9 @@ import * as smartrule from '@push.rocks/smartrule';
|
|||||||
import * as smartrx from '@push.rocks/smartrx';
|
import * as smartrx from '@push.rocks/smartrx';
|
||||||
import * as smartunique from '@push.rocks/smartunique';
|
import * as smartunique from '@push.rocks/smartunique';
|
||||||
|
|
||||||
export { projectinfo, qenv, smartacme, smartdata, smartdns, smartfile, smartguard, smartjwt, smartlog, smartmail, smartmetrics, smartnetwork, smartpath, smartproxy, smartpromise, smartrequest, smartrule, smartrx, 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, smartrx, smartunique };
|
||||||
|
|
||||||
// Define SmartLog types for use in error handling
|
// Define SmartLog types for use in error handling
|
||||||
export type TLogLevel = 'error' | 'warn' | 'info' | 'success' | 'debug';
|
export type TLogLevel = 'error' | 'warn' | 'info' | 'success' | 'debug';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as plugins from '../plugins.ts';
|
import * as plugins from '../plugins.js';
|
||||||
import * as paths from '../paths.ts';
|
import * as paths from '../paths.js';
|
||||||
import { logger } from '../logger.ts';
|
import { logger } from '../logger.js';
|
||||||
import { Email } from '../mail/core/classes.email.ts';
|
import { Email } from '../mail/core/classes.email.js';
|
||||||
import type { IAttachment } from '../mail/core/classes.email.ts';
|
import type { IAttachment } from '../mail/core/classes.email.js';
|
||||||
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from './classes.securitylogger.ts';
|
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from './classes.securitylogger.js';
|
||||||
import { LRUCache } from 'lru-cache';
|
import { LRUCache } from 'lru-cache';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as plugins from '../plugins.ts';
|
import * as plugins from '../plugins.js';
|
||||||
import * as paths from '../paths.ts';
|
import * as paths from '../paths.js';
|
||||||
import { logger } from '../logger.ts';
|
import { logger } from '../logger.js';
|
||||||
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from './classes.securitylogger.ts';
|
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from './classes.securitylogger.js';
|
||||||
import { LRUCache } from 'lru-cache';
|
import { LRUCache } from 'lru-cache';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -472,10 +472,10 @@ export class IPReputationChecker {
|
|||||||
} else {
|
} else {
|
||||||
// Fall back to filesystem
|
// Fall back to filesystem
|
||||||
const cacheDir = plugins.path.join(paths.dataDir, 'security');
|
const cacheDir = plugins.path.join(paths.dataDir, 'security');
|
||||||
plugins.smartfile.fs.ensureDirSync(cacheDir);
|
await plugins.smartfs.directory(cacheDir).recursive().create();
|
||||||
|
|
||||||
const cacheFile = plugins.path.join(cacheDir, 'ip_reputation_cache.json');
|
const cacheFile = plugins.path.join(cacheDir, 'ip_reputation_cache.json');
|
||||||
plugins.smartfile.memory.toFsSync(cacheData, cacheFile);
|
await plugins.smartfs.file(cacheFile).write(cacheData);
|
||||||
|
|
||||||
logger.log('info', `Saved ${entries.length} IP reputation cache entries to disk`);
|
logger.log('info', `Saved ${entries.length} IP reputation cache entries to disk`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as plugins from '../plugins.ts';
|
import * as plugins from '../plugins.js';
|
||||||
import { logger } from '../logger.ts';
|
import { logger } from '../logger.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log level for security events
|
* Log level for security events
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ export {
|
|||||||
SecurityLogLevel,
|
SecurityLogLevel,
|
||||||
SecurityEventType,
|
SecurityEventType,
|
||||||
type ISecurityEvent
|
type ISecurityEvent
|
||||||
} from './classes.securitylogger.ts';
|
} from './classes.securitylogger.js';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
IPReputationChecker,
|
IPReputationChecker,
|
||||||
@@ -11,11 +11,11 @@ export {
|
|||||||
IPType,
|
IPType,
|
||||||
type IReputationResult,
|
type IReputationResult,
|
||||||
type IIPReputationOptions
|
type IIPReputationOptions
|
||||||
} from './classes.ipreputationchecker.ts';
|
} from './classes.ipreputationchecker.js';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
ContentScanner,
|
ContentScanner,
|
||||||
ThreatCategory,
|
ThreatCategory,
|
||||||
type IScanResult,
|
type IScanResult,
|
||||||
type IContentScannerOptions
|
type IContentScannerOptions
|
||||||
} from './classes.contentscanner.ts';
|
} from './classes.contentscanner.js';
|
||||||
13
tsconfig.json
Normal file
13
tsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"types": ["node", "mailparser"]
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"dist_*/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user