# 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 ```bash 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): ```bash 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. ```bash 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 ```bash 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: ```bash 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`).