email-connect/tests/harness
tegwick 89fd13ac2d
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
EMAIL-WP-0005-T02: add GreenMail test harness
Adds tests/harness/docker-compose.yml running GreenMail 2.1.12 (digest-pinned)
with SMTP 3025, IMAP 3143 and the API bound to 127.0.0.1 only, plus a
config/harness-imap.yml scanner profile and harness README. Auth is disabled
and no users are declared, so a mailbox is created on first login and per-test
users need no provisioning.

GreenMail standalone offers no STARTTLS, only plaintext or implicit TLS, while
SMTPProvider hardcoded starttls() -- so no send could reach it. SMTPProvider
now takes a security mode via EMAIL_CONNECT_SMTP_SECURITY, defaulting to
starttls. plaintext is refused for any non-loopback host, and hostnames are
never resolved to decide that, so a misconfigured deployment fails at startup
rather than sending credentials in the clear. Trusting GreenMail's self-signed
cert was rejected as the wider risk; see DECISIONS.md.

Verified end to end against the live harness: SMTPProvider.send -> GreenMail ->
ImapMailboxSource, and the documented scan-mailbox CLI. Suite: 52 passed with
the harness down.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 01:41:38 +02:00
..
docker-compose.yml EMAIL-WP-0005-T02: add GreenMail test harness 2026-08-14 01:41:38 +02:00
README.md EMAIL-WP-0005-T02: add GreenMail test harness 2026-08-14 01:41:38 +02:00

Local mail test harness

A single GreenMail container serving SMTP and IMAP on loopback, so integration tests can drive the transactional send path and read the result back through the scanner without a live provider.

Part of EMAIL-WP-0005. Unit tests do not need this harness — they run against fixture directories and temporary Maildir trees and stay offline.

Start and stop

docker compose -f tests/harness/docker-compose.yml up -d
docker compose -f tests/harness/docker-compose.yml down -v

Readiness (the container healthcheck probes both mail ports; the API also answers):

docker inspect --format '{{.State.Health.Status}}' email-connect-harness
curl -s http://127.0.0.1:8080/api/service/readiness

Ports

Port Protocol Notes
3025 SMTP plaintext, no STARTTLS
3143 IMAP plaintext
8080 HTTP GreenMail API — readiness, user and mail management

All three bind 127.0.0.1 only. The harness accepts any credentials and must never be exposed beyond the host.

Accounts

The harness runs with greenmail.auth.disabled, so any login is accepted and the mailbox is created on first use. No provisioning step is needed: pick an address under harness.email-connect.test and log in.

export EMAIL_CONNECT_IMAP_USER=t01@harness.email-connect.test
export EMAIL_CONNECT_IMAP_PASSWORD=harness   # ignored, but must be set

These credentials are deliberately non-secret and belong in the repo. Real provider material is routed through OpenBao — see .claude/rules/credential-routing.md. Never point this harness at real credentials or a real mailbox.

Scanning the harness

docker compose -f tests/harness/docker-compose.yml up -d
export EMAIL_CONNECT_IMAP_USER=t01@harness.email-connect.test
export EMAIL_CONNECT_IMAP_PASSWORD=harness
email-connect scan-mailbox --config config/harness-imap.yml --out reports/

Sending through the harness

GreenMail offers no STARTTLS, only plaintext or implicit TLS with a self-signed certificate. The transactional service therefore needs its transport mode set explicitly:

export EMAIL_CONNECT_SMTP_HOST=127.0.0.1
export EMAIL_CONNECT_SMTP_PORT=3025
export EMAIL_CONNECT_SMTP_SECURITY=plaintext
export EMAIL_CONNECT_SMTP_USERNAME=sender@harness.email-connect.test
export EMAIL_CONNECT_SMTP_PASSWORD=harness
export EMAIL_CONNECT_SENDER=noreply@harness.email-connect.test

EMAIL_CONNECT_SMTP_SECURITY defaults to starttls. plaintext is rejected for any non-loopback host, so this setting cannot weaken a real deployment: it fails at startup rather than sending credentials in the clear.

What harness mail proves

Nothing beyond provider_accepted. A message sitting in a GreenMail mailbox is not evidence of inbox placement, recipient awareness, identity, or authorization. Bounces, complaints, and deferrals are not reproducible here — GreenMail accepts everything. Those classes stay on crafted .eml fixtures and an optional provider-simulator tier (EMAIL-WP-0005-T05).