The test helper's mock email server was missing the getRateLimiter() method that was added during the rate limiting feature implementation. This caused all SMTP tests to fail with "getRateLimiter is not a function" error. Changes: - Add getRateLimiter() method to mock email server that returns a mock rate limiter - Update mock rate limiter method signatures to match actual implementation - Fix TypeScript type issue with auth options by adding explicit casting
dcrouter
dcrouter: a traffic router intended to be gating your datacenter.
A comprehensive traffic routing solution that provides unified gateway capabilities for HTTP/HTTPS, TCP/SNI, email (SMTP), and DNS protocols. Designed for enterprises requiring robust traffic management, automatic certificate provisioning, and enterprise-grade email infrastructure.
Table of Contents
- Features
- Installation
- Quick Start
- Architecture
- Configuration
- Email System
- SmartProxy Routing
- Security Features
- API Reference
- Examples
- Troubleshooting
Features
🌐 Universal Traffic Router
- HTTP/HTTPS routing with pattern matching and virtual hosts
- TCP/SNI proxy for any protocol with TLS termination/passthrough
- DNS server with authoritative and dynamic record management
- Multi-protocol support on the same infrastructure
🔒 Enterprise Security
- Automatic TLS certificates via ACME with DNS-01 challenges
- IP reputation checking and real-time threat detection
- Content scanning for spam, viruses, and malicious content
- Comprehensive security logging with correlation tracking
📧 Complete Email Infrastructure
- Multi-domain SMTP server on standard ports (25, 587, 465)
- Pattern-based email routing with three processing modes
- DKIM, SPF, DMARC authentication and verification
- Enterprise deliverability with IP warmup and reputation management
⚡ High Performance
- Connection pooling and efficient resource management
- Load balancing with automatic failover
- Rate limiting at multiple levels
- Real-time metrics and monitoring
💾 Flexible Storage System
- Multiple storage backends: filesystem, custom functions, or memory
- Unified storage interface for all components
- Automatic data migration between backends
- Persistent configuration for domains, routes, and security data
Installation
npm install @serve.zone/dcrouter --save
Prerequisites
- Node.js 18+ with ES modules support
- Valid domain with DNS control (for ACME certificates)
- Cloudflare API token (for DNS challenges)
Quick Start
Basic HTTP/HTTPS Router
import { DcRouter } from '@serve.zone/dcrouter';
const router = new DcRouter({
smartProxyConfig: {
routes: [
{
name: 'web-service',
match: { domains: ['example.com'], ports: [443] },
action: {
type: 'forward',
target: { host: '192.168.1.10', port: 8080 },
tls: { mode: 'terminate', certificate: 'auto' }
}
}
],
acme: {
email: 'admin@example.com',
enabled: true,
useProduction: true
}
}
});
await router.start();
console.log('DcRouter started successfully');
Basic Email Router
import { DcRouter } from '@serve.zone/dcrouter';
const router = new DcRouter({
emailConfig: {
ports: [25, 587, 465],
hostname: 'mail.example.com',
routes: [
{
name: 'local-mail',
match: { recipients: '*@example.com' },
action: {
type: 'process',
process: {
scan: true,
dkim: true,
queue: 'normal'
}
}
}
],
tls: {
keyPath: './certs/key.pem',
certPath: './certs/cert.pem'
}
}
});
await router.start();
Architecture
System Overview
graph TB
subgraph "External Traffic"
HTTP[HTTP/HTTPS Clients]
SMTP[SMTP Clients]
TCP[TCP Clients]
DNS[DNS Queries]
end
subgraph "DcRouter Core"
DcRouter[DcRouter Orchestrator]
SmartProxy[SmartProxy Engine]
EmailServer[Unified Email Server]
DnsServer[DNS Server]
CertManager[Certificate Manager]
end
subgraph "Backend Services"
WebServices[Web Services]
MailServers[Mail Servers]
Databases[Databases]
APIs[Internal APIs]
end
HTTP --> SmartProxy
TCP --> SmartProxy
SMTP --> EmailServer
DNS --> DnsServer
DcRouter --> SmartProxy
DcRouter --> EmailServer
DcRouter --> DnsServer
DcRouter --> CertManager
SmartProxy --> WebServices
SmartProxy --> APIs
EmailServer --> MailServers
EmailServer --> Databases
CertManager -.-> SmartProxy
CertManager -.-> EmailServer
Core Components
DcRouter Orchestrator
Central coordination engine that manages all services and provides unified configuration.
SmartProxy Engine
High-performance HTTP/HTTPS and TCP/SNI proxy with:
- Pattern-based routing
- TLS termination/passthrough
- Load balancing
- Connection pooling
Unified Email Server
Enterprise-grade SMTP server with:
- Multi-domain support
- Pattern-based routing
- Three processing modes
- Complete authentication stack
Certificate Manager
Automatic TLS certificate provisioning via ACME with DNS-01 challenges.
Configuration
Complete Configuration Interface
interface IDcRouterOptions {
// SmartProxy configuration for HTTP/HTTPS/TCP routing
smartProxyConfig?: {
routes: IRouteConfig[];
acme?: IAcmeConfig;
allowSessionTicket?: boolean;
};
// Email system configuration
emailConfig?: {
ports: number[];
hostname: string;
domains?: IEmailDomainConfig[]; // Domain infrastructure setup
routes: IEmailRoute[]; // Route-based email handling
auth?: IAuthConfig;
tls?: ITlsConfig;
maxMessageSize?: number;
rateLimits?: IRateLimitConfig;
useSocketHandler?: boolean; // Enable socket-handler mode (no port binding)
defaults?: { // Global defaults for all domains
dnsMode?: 'forward' | 'internal-dns' | 'external-dns';
dkim?: IDkimConfig;
rateLimits?: IRateLimitConfig;
};
};
// DNS server configuration
dnsServerConfig?: {
port?: number;
authoritative?: boolean;
records?: IDnsRecord[];
};
// DNS domain for automatic DNS-over-HTTPS setup
dnsDomain?: string; // e.g., 'dns.example.com'
// TLS and certificate configuration
tls?: {
contactEmail: string;
domain: string;
};
// DNS challenge configuration
dnsChallenge?: {
cloudflareApiKey: string;
};
// Storage configuration
storage?: {
fsPath?: string; // Filesystem storage path
readFunction?: (key: string) => Promise<string>; // Custom read function
writeFunction?: (key: string, value: string) => Promise<void>; // Custom write function
};
}
Route Configuration
interface IRouteConfig {
name: string;
priority?: number;
match: {
domains?: string[];
ports?: number | number[] | { from: number; to: number }[];
};
action: {
type: 'forward' | 'redirect' | 'serve';
target?: {
host: string;
port: number | 'preserve' | ((context: any) => number);
};
tls?: {
mode: 'terminate' | 'passthrough';
certificate?: 'auto' | string;
};
security?: {
ipAllowList?: string[];
ipBlockList?: string[];
};
};
}
Socket-Handler Mode
DcRouter supports an advanced socket-handler mode that eliminates internal port binding for both DNS and email services. Instead of services listening on internal ports, SmartProxy passes sockets directly to the services.
DNS Socket-Handler
When dnsDomain
is configured, DcRouter automatically:
- Sets up DNS server for UDP on port 53
- Creates SmartProxy routes for DNS-over-HTTPS (DoH) on the specified domain
- Uses socket-handler for HTTPS/DoH traffic (no HTTPS port binding)
const router = new DcRouter({
dnsDomain: 'dns.example.com', // Enables DNS with DoH
smartProxyConfig: {
// DNS routes are automatically created
}
});
This creates:
- UDP DNS service on port 53 (standard DNS queries)
- HTTPS routes for
dns.example.com/dns-query
anddns.example.com/resolve
- Automatic TLS certificates via Let's Encrypt
Email Socket-Handler
When useSocketHandler
is enabled in email config:
- Email server doesn't bind to any ports
- SmartProxy passes sockets directly to email handlers
- Reduces latency and resource usage
const router = new DcRouter({
emailConfig: {
ports: [25, 587, 465],
hostname: 'mail.example.com',
useSocketHandler: true, // Enable socket-handler mode
routes: [/* email routes */]
}
});
Benefits of Socket-Handler Mode
- Performance: Eliminates internal port forwarding overhead
- Security: No exposed internal ports
- Resource Efficiency: Fewer open ports and listeners
- Simplified Networking: Direct socket passing
- Automatic Configuration: Routes created automatically
Traditional vs Socket-Handler Mode
Traditional Mode (default):
External Port → SmartProxy → Internal Port → Service
25 → 10025 → Email
Socket-Handler Mode:
External Port → SmartProxy → Socket Handler → Service
25 → (direct socket) → Email
Email System
Email Domain Configuration
DcRouter separates email infrastructure (which domains to handle) from routing logic (how to handle emails):
DNS Modes
Forward Mode - Simple mail forwarding without local DNS:
{
domain: 'forwarded.com',
dnsMode: 'forward',
dns: {
forward: {
skipDnsValidation: true,
targetDomain: 'mail.target.com'
}
}
}
Internal DNS Mode - Use built-in DNS server (requires dnsDomain
in DcRouter config):
{
domain: 'mail.example.com',
dnsMode: 'internal-dns',
dns: {
internal: {
mxPriority: 10,
ttl: 3600
}
},
dkim: {
selector: 'mail2024',
keySize: 2048,
rotateKeys: true,
rotationInterval: 90
}
}
External DNS Mode - Use existing DNS infrastructure:
{
domain: 'mail.external.com',
dnsMode: 'external-dns',
dns: {
external: {
requiredRecords: ['MX', 'SPF', 'DKIM', 'DMARC']
}
},
rateLimits: {
inbound: {
messagesPerMinute: 100,
connectionsPerIp: 10
}
}
}
DKIM Management
DKIM is always enabled for all domains. Keys are automatically:
- Generated on first use
- Stored persistently via StorageManager
- Rotated based on configuration
- Cleaned up after grace period
Email Route Actions
Forward Action
Routes emails to external SMTP servers.
{
name: 'forward-to-internal',
match: { recipients: '*@company.com' },
action: {
type: 'forward',
forward: {
host: 'internal-mail.company.com',
port: 25,
auth: {
username: 'relay-user',
password: 'relay-pass'
},
addHeaders: {
'X-Forwarded-By': 'dcrouter'
}
}
}
}
Process Action
Full Mail Transfer Agent functionality with scanning and delivery queues.
{
name: 'process-notifications',
match: { recipients: '*@notifications.company.com' },
action: {
type: 'process',
process: {
scan: true,
dkim: true,
queue: 'priority'
}
}
}
Deliver Action
Local delivery for mailbox storage.
{
name: 'deliver-local',
match: { recipients: '*@marketing.company.com' },
action: {
type: 'deliver'
}
}
Reject Action
Reject emails with custom SMTP responses.
{
name: 'reject-spam',
match: {
senders: '*@spam-domain.com',
sizeRange: { min: 1000000 } // > 1MB
},
action: {
type: 'reject',
reject: {
code: 550,
message: 'Message rejected due to policy'
}
}
}
Common Email Routing Patterns
IP-Based Relay
Allow internal networks to relay through the server:
{
name: 'office-relay',
priority: 100,
match: { clientIp: ['192.168.0.0/16', '10.0.0.0/8'] },
action: {
type: 'forward',
forward: { host: 'internal-mail.company.com', port: 25 }
}
}
Domain-Based Routing
Route different domains to different servers:
{
name: 'partner-domain',
match: { recipients: '*@partner.com' },
action: {
type: 'forward',
forward: { host: 'partner-mail.com', port: 587 }
}
}
Authentication-Based Processing
Different handling for authenticated vs unauthenticated senders:
{
name: 'authenticated-users',
match: { authenticated: true },
action: {
type: 'process',
process: { scan: false, dkim: true, queue: 'priority' }
}
},
{
name: 'unauthenticated-reject',
match: { authenticated: false },
action: {
type: 'reject',
reject: { code: 550, message: 'Authentication required' }
}
}
Content-Based Filtering
Filter based on size, subject, or headers:
{
name: 'large-email-reject',
match: { sizeRange: { min: 25000000 } }, // > 25MB
action: {
type: 'reject',
reject: { code: 552, message: 'Message too large' }
}
},
{
name: 'priority-emails',
match: {
headers: { 'X-Priority': 'high' },
subject: /urgent|emergency/i
},
action: {
type: 'process',
process: { queue: 'priority' }
}
}
Email Security Features
Route Matching Patterns
Glob Pattern Matching
// Email address patterns
match: { recipients: '*@example.com' } // All addresses at domain
match: { recipients: 'admin@*' } // Admin at any domain
match: { senders: ['*@trusted.com', '*@partner.com'] } // Multiple patterns
// CIDR IP matching
match: { clientIp: '192.168.0.0/16' } // Private subnet
match: { clientIp: ['10.0.0.0/8', '172.16.0.0/12'] } // Multiple ranges
// Header matching
match: {
headers: {
'X-Priority': 'high',
'Subject': /urgent|emergency/i
}
}
// Size and content matching
match: {
sizeRange: { min: 1000, max: 5000000 }, // 1KB to 5MB
hasAttachments: true,
subject: /invoice|receipt/i
}
Content Scanning
const scanners = [
{
type: 'spam',
threshold: 5.0,
action: 'tag',
headers: ['X-Spam-Score', 'X-Spam-Status']
},
{
type: 'virus',
action: 'reject',
quarantine: true
},
{
type: 'attachment',
blockedExtensions: ['.exe', '.bat', '.scr'],
maxSize: 25 * 1024 * 1024 // 25MB
}
];
SmartProxy Routing
HTTP/HTTPS Routing
const routes = [
// API routing with path-based forwarding
{
name: 'api-gateway',
match: {
domains: ['api.example.com'],
ports: [443]
},
action: {
type: 'forward',
target: {
host: '192.168.1.20',
port: (context) => {
// Route based on path
if (context.path.startsWith('/v1/')) return 8080;
if (context.path.startsWith('/v2/')) return 8081;
return 8080;
}
},
tls: {
mode: 'terminate',
certificate: 'auto'
}
}
},
// Static file serving
{
name: 'static-assets',
match: {
domains: ['cdn.example.com'],
ports: [443]
},
action: {
type: 'serve',
root: '/var/www/static',
tls: {
mode: 'terminate',
certificate: 'auto'
}
}
}
];
TCP/SNI Routing
const tcpRoutes = [
// Database connection routing
{
name: 'database-cluster',
match: {
ports: [{ from: 5432, to: 5439 }]
},
action: {
type: 'forward',
target: {
host: '192.168.1.30',
port: 'preserve'
},
security: {
ipAllowList: ['192.168.1.0/24']
}
}
},
// SNI-based routing for TLS services
{
name: 'secure-service',
match: {
domains: ['secure.example.com'],
ports: [8443]
},
action: {
type: 'forward',
target: {
host: '192.168.1.40',
port: 8443
},
tls: {
mode: 'passthrough'
}
}
}
];
Storage System
StorageManager
DcRouter includes a flexible storage system that supports multiple backends:
Filesystem Storage
const router = new DcRouter({
storage: {
fsPath: '/var/lib/dcrouter/data'
}
});
Custom Storage Backend
const router = new DcRouter({
storage: {
readFunction: async (key) => {
// Read from Redis, S3, etc.
return await myDatabase.get(key);
},
writeFunction: async (key, value) => {
// Write to Redis, S3, etc.
await myDatabase.set(key, value);
}
}
});
Memory Storage (Development)
const router = new DcRouter({
// No storage config = memory storage with warning
});
Storage Usage
The storage system is used for:
- DKIM Keys:
/email/dkim/{domain}/private.key
,/email/dkim/{domain}/public.key
- Email Routes:
/email/routes/{routeId}.json
- Bounce Lists:
/email/bounces/suppression.json
- IP Reputation:
/security/ip-reputation/{ip}.json
- Domain Configs:
/email/domains/{domain}.json
Data Migration
Migrate data between storage backends:
import { StorageManager } from '@serve.zone/dcrouter';
// Export from filesystem
const fsStorage = new StorageManager({ fsPath: './data' });
const keys = await fsStorage.list('/');
const data = {};
for (const key of keys) {
data[key] = await fsStorage.get(key);
}
// Import to cloud storage
const cloudStorage = new StorageManager({
readFunction: cloudRead,
writeFunction: cloudWrite
});
for (const [key, value] of Object.entries(data)) {
await cloudStorage.set(key, value);
}
Security Features
IP Reputation Checking
import { IpReputationChecker } from '@serve.zone/dcrouter';
const ipChecker = new IpReputationChecker({
providers: ['spamhaus', 'barracuda', 'surbl'],
cacheTimeout: 3600000, // 1 hour
threshold: 0.7
});
// Check IP reputation
const result = await ipChecker.checkIp('192.0.2.1');
if (result.isBlocked) {
console.log(`IP blocked: ${result.reason}`);
}
Content Security Scanner
import { ContentScanner } from '@serve.zone/dcrouter';
const scanner = new ContentScanner({
spamThreshold: 5.0,
virusScanning: true,
attachmentFiltering: {
maxSize: 25 * 1024 * 1024,
blockedTypes: ['.exe', '.bat', '.scr']
}
});
const scanResult = await scanner.scanEmail(email);
API Reference
DcRouter Class
Constructor
constructor(options: IDcRouterOptions)
Methods
start(): Promise<void>
Starts all configured services (SmartProxy, email server, DNS server).
stop(): Promise<void>
Gracefully stops all services.
updateRoutes(routes: IRouteConfig[]): Promise<void>
Updates SmartProxy routes dynamically.
updateDomainRules(rules: IDomainRule[]): Promise<void>
Updates email domain routing rules.
getStats(): IStatsResponse
Returns real-time statistics for all services.
Email Service API
sendEmail(options: IEmailOptions): Promise<string>
const emailId = await router.emailService.sendEmail({
from: 'sender@example.com',
to: 'recipient@example.com',
subject: 'Test Email',
html: '<p>Hello World</p>',
attachments: []
});
getEmailStatus(emailId: string): IEmailStatus
const status = router.emailService.getEmailStatus(emailId);
console.log(status.status); // 'pending', 'sent', 'delivered', 'bounced'
getDeliveryReport(emailId: string): IDeliveryReport
Detailed delivery information including bounce reasons and tracking data.
Examples
Complete Enterprise Setup
import { DcRouter } from '@serve.zone/dcrouter';
const router = new DcRouter({
// HTTP/HTTPS routing
smartProxyConfig: {
routes: [
// Main website
{
name: 'website',
priority: 100,
match: { domains: ['example.com', 'www.example.com'], ports: [443] },
action: {
type: 'forward',
target: { host: '192.168.1.10', port: 80 },
tls: { mode: 'terminate', certificate: 'auto' }
}
},
// API services
{
name: 'api',
priority: 110,
match: { domains: ['api.example.com'], ports: [443] },
action: {
type: 'forward',
target: { host: '192.168.1.20', port: 8080 },
tls: { mode: 'terminate', certificate: 'auto' }
}
},
// Internal services
{
name: 'internal',
match: { ports: [{ from: 8000, to: 8999 }] },
action: {
type: 'forward',
target: { host: '192.168.1.30', port: 'preserve' },
security: { ipAllowList: ['192.168.0.0/16'] }
}
}
],
// ACME certificate automation
acme: {
email: 'ssl@example.com',
enabled: true,
useProduction: true,
autoRenew: true
}
},
// Enterprise email system
emailConfig: {
ports: [25, 587, 465],
hostname: 'mail.example.com',
// Domain configuration
domains: [
{
domain: 'example.com',
dnsMode: 'external-dns',
dkim: {
selector: 'mail',
rotateKeys: true
}
},
{
domain: 'notifications.example.com',
dnsMode: 'internal-dns',
rateLimits: {
outbound: { messagesPerHour: 10000 }
}
}
],
// Authentication configuration
auth: {
required: true,
methods: ['PLAIN', 'LOGIN']
},
// TLS configuration
tls: {
keyPath: './certs/mail-key.pem',
certPath: './certs/mail-cert.pem'
},
// Email routing rules
routes: [
// Relay from office network
{
name: 'office-relay',
priority: 100,
match: { clientIp: '192.168.0.0/16' },
action: {
type: 'forward',
forward: {
host: 'internal-mail.example.com',
port: 25
}
}
},
// Transactional emails via processing
{
name: 'notifications',
priority: 50,
match: { recipients: '*@notifications.example.com' },
action: {
type: 'process',
process: {
scan: true,
dkim: true,
queue: 'priority'
}
}
},
// Internal emails forwarded to Exchange
{
name: 'internal-mail',
priority: 25,
match: { recipients: '*@example.com' },
action: {
type: 'forward',
forward: {
host: 'exchange.internal.example.com',
port: 25
}
}
},
// Default reject
{
name: 'default-reject',
match: { recipients: '*' },
action: {
type: 'reject',
reject: {
code: 550,
message: 'Relay denied'
}
}
}
]
},
// DNS server for ACME challenges
dnsServerConfig: {
port: 53,
authoritative: true
},
// Cloudflare DNS challenges
dnsChallenge: {
cloudflareApiKey: process.env.CLOUDFLARE_API_KEY
},
// Persistent storage
storage: {
fsPath: '/var/lib/dcrouter/data'
}
});
// Start the router
await router.start();
console.log('Enterprise DcRouter started');
// Monitor statistics
setInterval(() => {
const stats = router.getStats();
console.log('Active connections:', stats.activeConnections);
console.log('Emails processed:', stats.emailsProcessed);
}, 60000);
Email Template System
import { EmailService, TemplateManager } from '@serve.zone/dcrouter';
// Setup email templates
const templateManager = new TemplateManager();
templateManager.addTemplate('welcome', {
subject: 'Welcome to {{company}}!',
html: `
<h1>Welcome {{name}}!</h1>
<p>Thank you for joining {{company}}.</p>
<p>Your account: {{email}}</p>
`,
text: 'Welcome {{name}}! Thank you for joining {{company}}.'
});
// Send templated email
const emailService = new EmailService(router);
await emailService.sendTemplatedEmail('welcome', {
to: 'user@example.com',
templateData: {
name: 'John Doe',
company: 'Example Corp',
email: 'user@example.com'
}
});
Troubleshooting
Common Issues
Certificate Issues
# Check certificate status
curl -I https://your-domain.com
# Verify ACME challenge accessibility
curl http://your-domain.com/.well-known/acme-challenge/test
Email Delivery Issues
# Test SMTP connectivity
telnet your-server.com 25
# Check DKIM record
dig TXT mail._domainkey.your-domain.com
# Verify SPF record
dig TXT your-domain.com
Email Routing Issues
Route Not Matching
- Check route priority order (higher priority = evaluated first)
- Verify glob patterns:
*@example.com
matches domain,admin@*
matches user - Test CIDR notation:
192.168.0.0/16
includes all 192.168.x.x addresses - Confirm authentication state matches your expectations
Common Route Patterns
// Debug route to log all traffic
{
name: 'debug-all',
priority: 1000,
match: { recipients: '*' },
action: { type: 'process', process: { scan: false } }
}
// Catch-all reject (should be lowest priority)
{
name: 'default-reject',
priority: 0,
match: { recipients: '*' },
action: { type: 'reject', reject: { code: 550, message: 'No route' } }
}
DNS Issues
# Test DNS server
dig @your-server.com your-domain.com
# Check DNS propagation
dig your-domain.com @8.8.8.8
Logging and Monitoring
import { SmartLog } from '@push.rocks/smartlog';
// Configure logging
const logger = new SmartLog({
level: 'info',
transport: 'console'
});
// Monitor email events
router.emailServer.on('emailReceived', (email) => {
logger.log('info', `Email received: ${email.from} -> ${email.to}`);
});
router.emailServer.on('emailSent', (result) => {
logger.log('info', `Email sent: ${result.messageId} (${result.status})`);
});
// Monitor proxy events
router.smartProxy.on('connectionEstablished', (connection) => {
logger.log('info', `Connection: ${connection.clientIp} -> ${connection.target}`);
});
Performance Tuning
const performanceConfig = {
// Connection limits
maxConnections: 1000,
connectionTimeout: 30000,
// Email queue settings
emailQueue: {
concurrency: 10,
maxRetries: 3,
retryDelay: 300000
},
// Cache settings
cache: {
ipReputation: { ttl: 3600000 }, // 1 hour
dns: { ttl: 300000 }, // 5 minutes
certificates: { ttl: 86400000 } // 24 hours
}
};
License
MIT License - see LICENSE file for details.
Testing
Comprehensive Test Suite
DcRouter includes a comprehensive test suite covering all aspects of the system:
SMTP Protocol Tests
- Commands: EHLO, HELO, MAIL FROM, RCPT TO, DATA, RSET, NOOP, QUIT, VRFY, EXPN, HELP
- Extensions: SIZE, PIPELINING, STARTTLS
- Connection Management: TLS/plain connections, timeouts, limits, rejection handling
- Error Handling: Syntax errors, invalid sequences, temporary/permanent failures
- Email Processing: Basic sending, multiple recipients, large emails, invalid addresses
- Security: Authentication, rate limiting
- Performance: Throughput testing
- Edge Cases: Very large emails, special characters
Storage and Configuration Tests
- Storage Manager: All backend types (filesystem, custom, memory)
- Integration: Component storage usage and persistence
- DNS Validation: All DNS modes (forward, internal, external)
- DNS Mode Switching: Dynamic configuration changes
- Data Migration: Moving data between storage backends
Running Tests
# Run all tests
pnpm test
# Run specific test categories
tsx test/suite/commands/test.ehlo-command.ts
tsx test/suite/connection/test.tls-connection.ts
tsx test/suite/email-processing/test.basic-email.ts
# Run with verbose output
tstest test/suite/security/test.authentication.ts --verbose
Test Infrastructure
The test suite uses a self-contained pattern where each test:
- Starts its own SMTP server instance
- Runs comprehensive test scenarios
- Cleans up all resources
- Provides detailed logging for debugging
This ensures tests are isolated, reliable, and can run in parallel.
Support
- Documentation: https://docs.serve.zone/dcrouter
- Issues: https://github.com/serve-zone/dcrouter/issues
- Community: https://community.serve.zone