Files
scadalink-design/docs/test_infra/test_infra_smtp.md
Joseph Doherty d91aa83665 refactor(docs): move requirements and test infra docs into docs/ subdirectories
Organize documentation by moving requirements (HighLevelReqs, Component-*,
lmxproxy_protocol) to docs/requirements/ and test infrastructure docs to
docs/test_infra/. Updates all cross-references in README, CLAUDE.md,
infra/README, component docs, and 23 plan files.
2026-03-21 01:11:35 -04:00

4.5 KiB

Test Infrastructure: SMTP Server (Mailpit)

Overview

The test SMTP server uses Mailpit, a lightweight email testing tool that captures all outgoing emails without delivering them. It provides both an SMTP server for sending and a web UI for inspecting captured messages.

Image & Ports

  • Image: axllent/mailpit:latest
  • SMTP port: 1025
  • Web UI / API: http://localhost:8025

Configuration

Setting Value Description
MP_SMTP_AUTH_ACCEPT_ANY 1 Accept any SMTP credentials (or none) — no real authentication
MP_SMTP_AUTH_ALLOW_INSECURE 1 Allow auth over plain SMTP (no TLS required) — dev only
MP_MAX_MESSAGES 500 Maximum stored messages before oldest are auto-deleted

Mailpit accepts all emails regardless of sender/recipient domain. No emails leave the server — they are captured and viewable in the web UI.

SMTP Connection Settings

For appsettings.Development.json (Notification Service):

{
  "Smtp": {
    "Server": "localhost",
    "Port": 1025,
    "AuthMode": "None",
    "FromAddress": "scada-notifications@company.com",
    "ConnectionTimeout": 30
  }
}

Since MP_SMTP_AUTH_ACCEPT_ANY is enabled, the Notification Service can use any auth mode:

  • No auth: Connect directly, no credentials needed.
  • Basic Auth: Any username/password will be accepted (useful for testing the auth code path without a real server).
  • OAuth2: Not supported by Mailpit. For OAuth2 testing, use a real Microsoft 365 tenant.

Mailpit API

Mailpit exposes a REST API at http://localhost:8025/api for programmatic access:

Endpoint Method Description
/api/v1/info GET Server info (version, message count)
/api/v1/messages GET List messages (supports ?limit=N)
/api/v1/message/{id} GET Read a specific message
/api/v1/messages DELETE Delete all messages
/api/v1/search?query=... GET Search messages

Verification

  1. Check the container is running:
docker ps --filter name=scadalink-smtp
  1. Open the web UI at http://localhost:8025 to view captured emails.

  2. Send a test email using curl or any SMTP client:

# Using Python's smtplib (one-liner)
python3 -c "
import smtplib; from email.mime.text import MIMEText
msg = MIMEText('Test body'); msg['Subject'] = 'Test'; msg['From'] = 'test@example.com'; msg['To'] = 'user@example.com'
smtplib.SMTP('localhost', 1025).sendmail('test@example.com', ['user@example.com'], msg.as_string())
print('Sent')
"

CLI Tool

The infra/tools/smtp_tool.py script provides a convenient CLI for interacting with the SMTP server and Mailpit API. This tool uses only Python standard library modules — no additional dependencies required.

Commands:

# Check SMTP connectivity and Mailpit status
python infra/tools/smtp_tool.py check

# Send a test email
python infra/tools/smtp_tool.py send --to user@example.com --subject "Alarm: Tank High Level" --body "Tank level exceeded 95%"

# Send with BCC (matches ScadaLink notification delivery pattern)
python infra/tools/smtp_tool.py send --to scada-notifications@company.com --bcc "operator1@company.com,operator2@company.com" --subject "Shift Report"

# List captured messages
python infra/tools/smtp_tool.py list

# Read a specific message by ID
python infra/tools/smtp_tool.py read --id <message-id>

# Clear all messages
python infra/tools/smtp_tool.py clear

Use --host and --port to override SMTP defaults (localhost:1025), --api for the Mailpit API URL. Run with --help for full usage.

  • Notification Service — test SMTP delivery, BCC recipient handling, plain-text formatting, and store-and-forward retry behavior (Mailpit can be stopped/started to simulate transient failures).
  • Store-and-Forward Engine — verify buffered retry by stopping the SMTP container and observing queued notifications.

Notes

  • Mailpit does not support OAuth2 Client Credentials authentication. To test the OAuth2 code path, use a real Microsoft 365 tenant (see Q12 in docs/plans/questions.md).
  • To simulate SMTP failures for store-and-forward testing, stop the container: docker compose stop smtp. Restart with docker compose start smtp.
  • The web UI at http://localhost:8025 provides real-time message inspection, search, and message source viewing.
  • No data persistence — messages are stored in a temporary database inside the container and lost on container removal.