Adds a fourth Docker service (Mailpit) to capture outgoing emails without delivery, with CLI tool for sending test emails, listing/reading captured messages, and clearing the inbox. Supports BCC pattern matching ScadaLink's notification delivery model.
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
- Check the container is running:
docker ps --filter name=scadalink-smtp
-
Open the web UI at
http://localhost:8025to view captured emails. -
Send a test email using
curlor 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.
Relevance to ScadaLink Components
- 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 withdocker compose start smtp. - The web UI at
http://localhost:8025provides 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.