Files
mailer/test/readme.md
Juergen Kunz 7ecdd9f1e4 Add comprehensive SMTP command tests for RCPT TO, DATA, QUIT, TLS, and basic email sending
- Implement CMD-03 tests for RCPT TO command, validating recipient addresses, handling multiple recipients, and enforcing command sequence.
- Implement CMD-04 tests for DATA command, ensuring proper email content transmission, handling of dot-stuffing, large messages, and correct command sequence.
- Implement CMD-13 tests for QUIT command, verifying graceful connection termination and idempotency.
- Implement CM-01 tests for TLS connections, including STARTTLS capability and direct TLS connections.
- Implement EP-01 tests for basic email sending, covering complete SMTP transaction flow, MIME attachments, HTML emails, custom headers, and minimal emails.
2025-10-28 10:11:34 +00:00

12 KiB

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.<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 Planned
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 Planned
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 Planned
ERR-02 Invalid Sequence Handling High Planned
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-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

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

  1. 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
});
  1. Import assertions from @std/assert:
import { assert, assertEquals, assertMatch } from '@std/assert';
  1. Use test helpers:
import { startTestServer, stopTestServer } from '../../helpers/server.loader.ts';
import { connectToSmtp, sendSmtpCommand } from '../../helpers/utils.ts';
  1. Always cleanup:
  • Close connections with closeSmtpConnection() or conn.close()
  • Stop test servers with stopTestServer()
  • Use try/finally blocks for guaranteed cleanup
  1. 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: 7/100+ test files (47 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-13: QUIT Command (7 tests passing)
  • CM-01: TLS Connection (8 tests passing)
  • EP-01: Basic Email Sending (7 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%)

Next Steps:

  1. Port CMD-06 (RSET) for transaction reset testing
  2. Port security tests (SEC-01 Authentication, SEC-06 IP Reputation, SEC-08 Rate Limiting)
  3. Port error handling tests (ERR-01 Syntax, ERR-02 Sequence)
  4. Continue with remaining high-priority tests

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