# 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/assert` from 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 testing - **`test-key.pem`** - Private key for TLS testing ## Test Suite Organization All tests follow the naming convention: `test...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 ```bash deno test --allow-all --no-check test/ ``` ### Run Specific Category ```bash # 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 ```bash deno test --allow-all --no-check test/suite/smtpserver_commands/test.cmd-01.ehlo-command.test.ts ``` ### Run with Verbose Output ```bash deno test --allow-all --no-check --trace-leaks test/ ``` ## Test Development Guidelines ### Writing New Tests 1. **Use Deno.test() format**: ```typescript Deno.test({ name: 'CMD-XX: Description of test', async fn() { // Test implementation }, sanitizeResources: false, // Required for network tests sanitizeOps: false, // Required for network tests }); ``` 2. **Import assertions from @std/assert**: ```typescript import { assert, assertEquals, assertMatch } from '@std/assert'; ``` 3. **Use test helpers**: ```typescript import { startTestServer, stopTestServer } from '../../helpers/server.loader.ts'; import { connectToSmtp, sendSmtpCommand } from '../../helpers/utils.ts'; ``` 4. **Always cleanup**: - Close connections with `closeSmtpConnection()` or `conn.close()` - Stop test servers with `stopTestServer()` - Use try/finally blocks for guaranteed cleanup 5. **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 `net` module - **After**: Deno `Deno.connect()` / `Deno.listen()` ### Imports - **Before**: `.js` extensions, Node-style imports - **After**: `.ts` extensions, 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**: 1. Port SEC-01: Authentication test 2. Port SEC-08: Rate Limiting test 3. Port SEC-10: Header Injection Prevention test 4. 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: 1. Maintain test IDs and organization 2. Convert to Deno.test() format 3. Use @std/assert for assertions 4. Update imports to .ts extensions 5. Use Deno-native TCP connections 6. Preserve test logic and validations 7. Add `sanitizeResources: false, sanitizeOps: false` for network tests 8. Update this README with ported tests ## Resources - [Deno Testing](https://deno.land/manual/basics/testing) - [Deno Standard Library - Assert](https://deno.land/std/assert) - [RFC 5321 - SMTP](https://tools.ietf.org/html/rfc5321) - [RFC 5322 - Internet Message Format](https://tools.ietf.org/html/rfc5322)