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.
117 lines
4.5 KiB
Markdown
117 lines
4.5 KiB
Markdown
# Test Infrastructure: SMTP Server (Mailpit)
|
|
|
|
## Overview
|
|
|
|
The test SMTP server uses [Mailpit](https://mailpit.axllent.org/), 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):
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```bash
|
|
docker ps --filter name=scadalink-smtp
|
|
```
|
|
|
|
2. Open the web UI at `http://localhost:8025` to view captured emails.
|
|
|
|
3. Send a test email using `curl` or any SMTP client:
|
|
|
|
```bash
|
|
# 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**:
|
|
|
|
```bash
|
|
# 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 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.
|