Mailer SMTP Test Suite (Deno)
Comprehensive SMTP server and client test suite ported from dcrouter to Deno-native testing.
Test Framework
- Framework: Deno native testing (
Deno.test) - Assertions:
@std/assertfrom Deno standard library - Run Command:
deno test --allow-all --no-check test/ - Run Single Test:
deno test --allow-all --no-check test/suite/smtpserver_commands/test.cmd-01.ehlo-command.test.ts
Test Infrastructure
Helpers (test/helpers/)
-
server.loader.ts- Test SMTP server lifecycle management- Start/stop test servers with configurable options
- TLS certificate handling
- Mock email processing
- Port management utilities
-
utils.ts- SMTP protocol test utilities- TCP connection management (Deno-native)
- SMTP command sending/receiving
- Protocol handshake helpers
- MIME message creation
- Retry and timing utilities
-
smtp.client.ts- SMTP client test utilities- Test client creation with various configurations
- Email sending helpers
- Connection pooling testing
- Throughput measurement
Fixtures (test/fixtures/)
test-cert.pem- Self-signed certificate for TLS testingtest-key.pem- Private key for TLS testing
Test Suite Organization
All tests follow the naming convention: test.<category-id>.<description>.test.ts
Test Categories
1. Connection Management (CM) - smtpserver_connection/
Tests for SMTP connection handling, TLS support, and connection lifecycle.
| ID | Test | Priority | Status |
|---|---|---|---|
| CM-01 | TLS Connection | High | ✅ PORTED |
| CM-02 | Multiple Simultaneous Connections | High | Planned |
| CM-03 | Connection Timeout | High | Planned |
| CM-06 | STARTTLS Upgrade | High | Planned |
| CM-10 | Plain Connection | Low | Planned |
2. SMTP Commands (CMD) - smtpserver_commands/
Tests for SMTP protocol command implementation.
| ID | Test | Priority | Status |
|---|---|---|---|
| CMD-01 | EHLO Command | High | ✅ PORTED |
| CMD-02 | MAIL FROM Command | High | ✅ PORTED |
| CMD-03 | RCPT TO Command | High | ✅ PORTED |
| CMD-04 | DATA Command | High | ✅ PORTED |
| CMD-06 | RSET Command | Medium | ✅ PORTED |
| CMD-13 | QUIT Command | High | ✅ PORTED |
3. Email Processing (EP) - smtpserver_email-processing/
Tests for email content handling, parsing, and delivery.
| ID | Test | Priority | Status |
|---|---|---|---|
| EP-01 | Basic Email Sending | High | ✅ PORTED |
| EP-02 | Invalid Email Address Handling | High | Planned |
| EP-04 | Large Email Handling | High | Planned |
| EP-05 | MIME Handling | High | Planned |
4. Security (SEC) - smtpserver_security/
Tests for security features and protections.
| ID | Test | Priority | Status |
|---|---|---|---|
| SEC-01 | Authentication | High | Planned |
| SEC-03 | DKIM Processing | High | Planned |
| SEC-04 | SPF Checking | High | Planned |
| SEC-06 | IP Reputation Checking | High | ✅ PORTED |
| SEC-08 | Rate Limiting | High | Planned |
| SEC-10 | Header Injection Prevention | High | Planned |
5. Error Handling (ERR) - smtpserver_error-handling/
Tests for proper error handling and recovery.
| ID | Test | Priority | Status |
|---|---|---|---|
| ERR-01 | Syntax Error Handling | High | ✅ PORTED |
| ERR-02 | Invalid Sequence Handling | High | ✅ PORTED |
| ERR-05 | Resource Exhaustion | High | Planned |
| ERR-07 | Exception Handling | High | Planned |
Currently Ported Tests
✅ CMD-01: EHLO Command (test.cmd-01.ehlo-command.test.ts)
Tests: 5 total (5 passing)
- Server startup/shutdown
- EHLO response with proper capabilities
- Invalid hostname handling
- Command pipelining (multiple EHLO)
Key validations:
- ✓ Server advertises SIZE capability
- ✓ Server advertises 8BITMIME capability
- ✓ Last capability line uses "250 " (space, not hyphen)
- ✓ Server handles invalid hostnames gracefully
- ✓ Second EHLO resets session state
✅ CMD-02: MAIL FROM Command (test.cmd-02.mail-from.test.ts)
Tests: 6 total (6 passing)
- Valid sender address acceptance
- Invalid sender address rejection
- SIZE parameter support
- Command sequence enforcement
Key validations:
- ✓ Accepts valid email formats
- ✓ Accepts IP literals (user@[192.168.1.1])
- ✓ Rejects malformed addresses
- ✓ Supports SIZE parameter
- ✓ Enforces EHLO before MAIL FROM
✅ CMD-03: RCPT TO Command (test.cmd-03.rcpt-to.test.ts)
Tests: 7 total (7 passing)
- Valid recipient address acceptance
- Multiple recipients support
- Invalid recipient address rejection
- Command sequence enforcement
- RSET clears recipients
Key validations:
- ✓ Accepts valid recipient formats
- ✓ Accepts IP literals and subdomains
- ✓ Supports multiple recipients per transaction
- ✓ Rejects invalid email addresses
- ✓ Enforces RCPT TO after MAIL FROM
- ✓ RSET properly clears recipient list
✅ CMD-04: DATA Command (test.cmd-04.data-command.test.ts)
Tests: 7 total (7 passing)
- Email data transmission after RCPT TO
- Rejection without RCPT TO
- Dot-stuffing handling
- Large message support
- Command sequence enforcement
Key validations:
- ✓ Accepts email data with proper terminator
- ✓ Returns 354 to start data input
- ✓ Returns 250 after successful email acceptance
- ✓ Rejects DATA without MAIL FROM
- ✓ Handles dot-stuffed content correctly
- ✓ Supports large messages (10KB+)
✅ CMD-06: RSET Command (test.cmd-06.rset-command.test.ts)
Tests: 8 total (8 passing)
- RSET after MAIL FROM
- RSET after RCPT TO
- Multiple consecutive RSET commands
- RSET without active transaction
- RSET clears all recipients
- RSET with parameters (ignored)
Key validations:
- ✓ Responds with 250 OK
- ✓ Resets transaction state after MAIL FROM
- ✓ Clears recipients requiring new MAIL FROM
- ✓ Idempotent (multiple RSETs work)
- ✓ Works without active transaction
- ✓ Clears all recipients from transaction
- ✓ Ignores parameters as per RFC
✅ CMD-13: QUIT Command (test.cmd-13.quit-command.test.ts)
Tests: 7 total (7 passing)
- Graceful connection termination
- QUIT after MAIL FROM
- QUIT after complete transaction
- Idempotent QUIT handling
- Immediate QUIT without EHLO
Key validations:
- ✓ Returns 221 Service closing
- ✓ Works at any point in SMTP session
- ✓ Properly closes connection
- ✓ Handles multiple QUIT commands gracefully
- ✓ Allows immediate QUIT after greeting
✅ CM-01: TLS Connection (test.cm-01.tls-connection.test.ts)
Tests: 8 total (8 passing)
- Server advertises STARTTLS capability
- STARTTLS command initiates upgrade
- Direct TLS connection support
- STARTTLS not available after already started
- STARTTLS requires EHLO first
- Connection accepts commands after TLS
- Server lifecycle management
Key validations:
- ✓ STARTTLS advertised in EHLO capabilities
- ✓ STARTTLS command responds with 220 Ready
- ✓ Direct TLS connections work (with self-signed certs)
- ✓ Second STARTTLS properly rejected
- ✓ STARTTLS before EHLO handled correctly
- ✓ TLS upgrade process validated
✅ EP-01: Basic Email Sending (test.ep-01.basic-email-sending.test.ts)
Tests: 7 total (7 passing)
- Complete SMTP transaction flow (CONNECT → EHLO → MAIL FROM → RCPT TO → DATA → CONTENT → QUIT)
- Email with MIME attachment (multipart/mixed)
- HTML email (multipart/alternative)
- Email with custom headers (X-Custom-Header, X-Priority, Reply-To, etc.)
- Minimal email (body only, no headers)
- Server lifecycle management
Key validations:
- ✓ Complete email lifecycle from greeting to QUIT
- ✓ MIME multipart messages with attachments
- ✓ HTML email with plain text fallback
- ✓ Custom header support (X-*, Reply-To, Organization)
- ✓ Minimal email content accepted
- ✓ Email queuing and processing confirmed
✅ SEC-06: IP Reputation Checking (test.sec-06.ip-reputation.test.ts)
Tests: 7 total (7 passing)
- IP reputation check accepts localhost connections
- Known good senders accepted
- Multiple connections from same IP handled
- Complete SMTP flow with reputation check
- Infrastructure placeholder test
- Server lifecycle management
Key validations:
- ✓ IP reputation infrastructure in place
- ✓ Localhost connections accepted after reputation check
- ✓ Legitimate senders and recipients accepted
- ✓ Multiple concurrent connections handled properly
- ✓ Complete email transaction works with IP checks
- ✓ IPReputationChecker class exists (placeholder implementation)
Note: Current implementation uses placeholder IP reputation checker that accepts all legitimate traffic. Infrastructure is ready for future implementation of real IP reputation databases, blacklist checking, and suspicious pattern detection.
✅ ERR-01: Syntax Error Handling (test.err-01.syntax-errors.test.ts)
Tests: 10 total (10 passing)
- Rejects invalid commands
- Rejects MAIL FROM without brackets
- Rejects RCPT TO without brackets
- Rejects EHLO without hostname
- Handles commands with extra parameters
- Rejects malformed email addresses
- Rejects commands in wrong sequence
- Handles excessively long commands
- Server lifecycle management
Key validations:
- ✓ Invalid commands rejected with 500/502 error codes
- ✓ MAIL FROM requires angle brackets (501 error if missing)
- ✓ RCPT TO requires angle brackets (501 error if missing)
- ✓ EHLO requires hostname parameter (501 error if missing)
- ✓ Extra parameters on QUIT handled (501 syntax error)
- ✓ Malformed email addresses rejected (501 error)
- ✓ Commands in wrong sequence rejected (503 error)
- ✓ Excessively long commands handled gracefully
✅ ERR-02: Invalid Sequence Handling (test.err-02.invalid-sequence.test.ts)
Tests: 10 total (10 passing)
- Rejects MAIL FROM before EHLO
- Rejects RCPT TO before MAIL FROM
- Rejects DATA before RCPT TO (RFC 5321 compliance)
- Allows multiple EHLO commands
- Handles second MAIL FROM without RSET
- Rejects DATA without MAIL FROM
- Handles commands after QUIT
- Recovers from syntax errors in sequence
- Server lifecycle management
Key validations:
- ✓ MAIL FROM requires EHLO first (503 error if missing)
- ✓ RCPT TO requires MAIL FROM first (503 error if missing)
- ✓ DATA requires RCPT TO with at least one recipient (503 error if missing)
- ✓ Multiple EHLO commands allowed (resets session state)
- ✓ Commands after QUIT handled correctly (connection closed)
- ✓ Session recovers from syntax errors without terminating
- ✓ RFC 5321 compliance: strict command sequence enforcement
Running Tests
Run All Tests
deno test --allow-all --no-check test/
Run Specific Category
# SMTP commands tests
deno test --allow-all --no-check test/suite/smtpserver_commands/
# Connection tests
deno test --allow-all --no-check test/suite/smtpserver_connection/
Run Single Test File
deno test --allow-all --no-check test/suite/smtpserver_commands/test.cmd-01.ehlo-command.test.ts
Run with Verbose Output
deno test --allow-all --no-check --trace-leaks test/
Test Development Guidelines
Writing New Tests
- Use Deno.test() format:
Deno.test({
name: 'CMD-XX: Description of test',
async fn() {
// Test implementation
},
sanitizeResources: false, // Required for network tests
sanitizeOps: false, // Required for network tests
});
- Import assertions from @std/assert:
import { assert, assertEquals, assertMatch } from '@std/assert';
- Use test helpers:
import { startTestServer, stopTestServer } from '../../helpers/server.loader.ts';
import { connectToSmtp, sendSmtpCommand } from '../../helpers/utils.ts';
- Always cleanup:
- Close connections with
closeSmtpConnection()orconn.close() - Stop test servers with
stopTestServer() - Use try/finally blocks for guaranteed cleanup
- Test isolation:
- Each test file uses its own port (e.g., CMD-01 uses 25251, CMD-02 uses 25252)
- Setup and cleanup tests ensure clean state
Key Differences from dcrouter Tests
Framework
- Before:
@git.zone/tstest/tapbundle(Node.js) - After: Deno.test (native)
Assertions
- Before:
expect(x).toBeTruthy(),expect(x).toEqual(y) - After:
assert(x),assertEquals(x, y),assertMatch(x, regex)
Network I/O
- Before: Node.js
netmodule - After: Deno
Deno.connect()/Deno.listen()
Imports
- Before:
.jsextensions, Node-style imports - After:
.tsextensions, Deno-style imports
Test Priorities
Phase 1: Core SMTP Functionality (High Priority) ✅ COMPLETE
- ✅ CMD-01: EHLO Command
- ✅ CMD-02: MAIL FROM Command
- ✅ CMD-03: RCPT TO Command
- ✅ CMD-04: DATA Command
- ✅ CMD-13: QUIT Command
- ✅ CM-01: TLS Connection
- ✅ EP-01: Basic Email Sending
Phase 2: Security & Validation (High Priority)
- 🔄 SEC-01: Authentication
- ✅ SEC-06: IP Reputation
- 🔄 SEC-08: Rate Limiting
- 🔄 SEC-10: Header Injection Prevention
- ✅ ERR-01: Syntax Error Handling
- ✅ ERR-02: Invalid Sequence Handling
Phase 3: Advanced Features (Medium Priority)
- 🔄 SEC-03: DKIM Processing
- 🔄 SEC-04: SPF Checking
- 🔄 EP-04: Large Email Handling
- 🔄 EP-05: MIME Handling
- 🔄 CM-02: Multiple Connections
- 🔄 CM-06: STARTTLS Upgrade
Phase 4: Complete Coverage (All Remaining)
- All performance tests
- All reliability tests
- All edge case tests
- All RFC compliance tests
- SMTP client tests
Current Status
Infrastructure: ✅ Complete
- Deno-native test helpers (utils.ts, server.loader.ts, smtp.client.ts)
- Server lifecycle management
- SMTP protocol utilities with readSmtpResponse helper
- Test certificates (self-signed RSA)
Tests Ported: 11/100+ test files (82 total tests passing)
- ✅ CMD-01: EHLO Command (5 tests passing)
- ✅ CMD-02: MAIL FROM Command (6 tests passing)
- ✅ CMD-03: RCPT TO Command (7 tests passing)
- ✅ CMD-04: DATA Command (7 tests passing)
- ✅ CMD-06: RSET Command (8 tests passing)
- ✅ CMD-13: QUIT Command (7 tests passing)
- ✅ CM-01: TLS Connection (8 tests passing)
- ✅ EP-01: Basic Email Sending (7 tests passing)
- ✅ SEC-06: IP Reputation Checking (7 tests passing)
- ✅ ERR-01: Syntax Error Handling (10 tests passing)
- ✅ ERR-02: Invalid Sequence Handling (10 tests passing)
Coverage: Complete essential SMTP transaction flow
- EHLO → MAIL FROM → RCPT TO → DATA → QUIT ✅
- TLS/STARTTLS support ✅
- Complete email lifecycle (MIME, HTML, custom headers) ✅
Phase 1 Status: ✅ COMPLETE (7/7 tests, 100%)
Phase 2 Status: 🔄 IN PROGRESS (3/6 tests, 50%)
- ✅ SEC-06: IP Reputation
- ✅ ERR-01: Syntax Errors
- ✅ ERR-02: Invalid Sequence
- 🔄 SEC-01: Authentication
- 🔄 SEC-08: Rate Limiting
- 🔄 SEC-10: Header Injection
Next Steps:
- Port SEC-01: Authentication test
- Port SEC-08: Rate Limiting test
- Port SEC-10: Header Injection Prevention test
- Continue with Phase 3 (Advanced Features)
Production Readiness Criteria
Gate 1: Core Functionality (>90% tests passing)
- Basic SMTP command handling
- Connection management
- Email delivery
- Error handling
Gate 2: Security (>95% tests passing)
- Authentication mechanisms
- TLS/STARTTLS support
- Rate limiting
- Injection prevention
Gate 3: Enterprise Ready (>85% tests passing)
- Full RFC compliance
- Performance under load
- Advanced security features
- Complete edge case handling
Contributing
When porting tests from dcrouter:
- Maintain test IDs and organization
- Convert to Deno.test() format
- Use @std/assert for assertions
- Update imports to .ts extensions
- Use Deno-native TCP connections
- Preserve test logic and validations
- Add
sanitizeResources: false, sanitizeOps: falsefor network tests - Update this README with ported tests