121 lines
4.8 KiB
Markdown
121 lines
4.8 KiB
Markdown
# Campaign SMTP/IMAP Test Bed
|
|
|
|
This test bed provides dedicated non-production SMTP/IMAP infrastructure for
|
|
campaign delivery checks. It uses GreenMail and must never be configured with
|
|
production recipients or credentials.
|
|
|
|
## Start
|
|
|
|
```bash
|
|
cd /mnt/DATA/git/govoplan-campaign/dev/mail-testbed
|
|
cp .env.example .env
|
|
docker compose --env-file .env up -d
|
|
```
|
|
|
|
Default endpoints:
|
|
|
|
- SMTP: `127.0.0.1:3025`, plain transport
|
|
- IMAP: `127.0.0.1:3143`, plain transport
|
|
- GreenMail API/UI endpoint: `127.0.0.1:38080`
|
|
|
|
## Smoke Test
|
|
|
|
Run the transport smoke from the core virtual environment after installing the
|
|
campaign and mail modules:
|
|
|
|
```bash
|
|
cd /mnt/DATA/git/govoplan-campaign/dev/mail-testbed
|
|
set -a
|
|
. ./.env
|
|
set +a
|
|
/mnt/DATA/git/govoplan-core/.venv/bin/python run_transport_smoke.py
|
|
```
|
|
|
|
The smoke sends and appends three messages:
|
|
|
|
- no attachment
|
|
- one normal attachment
|
|
- one password-protected AES ZIP attachment
|
|
|
|
It verifies SMTP authentication, IMAP authentication, folder listing, delivery
|
|
to `INBOX`, and append-to-Sent behavior.
|
|
|
|
If the smoke is started immediately after `docker compose up -d`, GreenMail may
|
|
bind the SMTP/IMAP ports before the services are fully ready. The smoke retries
|
|
login and folder setup for `GOVOPLAN_MAIL_TEST_READY_TIMEOUT_SECONDS`.
|
|
|
|
## Campaign Acceptance
|
|
|
|
The transport smoke proves the Mail adapters. The Campaign acceptance runner
|
|
proves the public composition: it creates an isolated temporary Core database,
|
|
creates a Mail-owned encrypted profile through the API, materializes the
|
|
credential-free [`greenmail-delivery`](../../examples/greenmail-delivery/campaign.json)
|
|
fixture with only that profile reference, validates/builds it, sends the exact
|
|
generated EML through Campaign once, appends it once, and cross-checks Campaign
|
|
report/audit state with one unique-subject message in the GreenMail INBOX and
|
|
Sent folders. Provider mailbox verification is not a byte-for-byte comparison
|
|
after provider-side header or storage transformations.
|
|
|
|
```bash
|
|
cd /mnt/DATA/git/govoplan-campaign/dev/mail-testbed
|
|
set -a
|
|
. ./.env
|
|
set +a
|
|
/mnt/DATA/git/govoplan/.venv/bin/python run_campaign_acceptance.py \
|
|
--evidence /tmp/govoplan-campaign-greenmail-evidence.json
|
|
```
|
|
|
|
The default run also uses controlled loopback protocol endpoints to prove that
|
|
an SMTP connection loss before transmission is temporary, an explicit SMTP
|
|
authentication rejection is permanent, and an IMAP authentication rejection
|
|
after SMTP acceptance leaves the send accepted while the append fails. A
|
|
second ordinary send must be rejected before another provider effect.
|
|
|
|
The bounded JSON contains no endpoint, account, address, credential, profile,
|
|
campaign, version, or job identifiers. It records module versions, the fixture
|
|
hash, normalized classifications/counts, the Mail-profile boundary, required
|
|
audit actions, provider mailbox increments, and coverage flags. Runtime version
|
|
declarations identify the exercised composition; they do not claim that the
|
|
sources are clean, tagged, signed, or release-provenanced. The evidence names
|
|
them `declared_module_versions` and keeps `source_artifact_provenance` false;
|
|
exact commit/artifact provenance belongs to the package and release gate.
|
|
|
|
This runner is restricted to literal loopback IP addresses and the synchronous
|
|
Campaign delivery mode. Hostnames such as `localhost` and every non-loopback
|
|
address fail before profile creation, avoiding a DNS change between validation
|
|
and connection. It is local target-like evidence, not approval of an
|
|
institution's SMTP/IMAP service. A post-DATA connection loss
|
|
with ambiguous SMTP outcome, an explicit temporary SMTP response, partial
|
|
recipient refusal, and a real worker restart remain separate drills and are
|
|
explicitly `false` in the coverage projection. Use `--success-only` only when
|
|
testing the success journey without the local failure endpoints.
|
|
|
|
Starting the maintained test bed requires a working Docker CLI, Compose plugin,
|
|
daemon/socket access, and permission to pull `greenmail/standalone:2.1.9`. The
|
|
Campaign runner needs only the already-running loopback endpoints; it neither
|
|
starts Docker nor claims that it did.
|
|
|
|
## Use With A Campaign
|
|
|
|
Use the same settings in a campaign mail profile:
|
|
|
|
- SMTP host `127.0.0.1`, port `3025`, security `plain`
|
|
- IMAP host `127.0.0.1`, port `3143`, security `plain`
|
|
- username and password from `.env`
|
|
- append folder from `GOVOPLAN_MAIL_TEST_SENT_FOLDER`
|
|
|
|
When changing the mailbox, keep `GOVOPLAN_MAIL_TEST_USER` equal to
|
|
`${GOVOPLAN_MAIL_TEST_LOCAL_PART}@${GOVOPLAN_MAIL_TEST_DOMAIN}` because the
|
|
compose file creates the GreenMail account from local part, password, and
|
|
domain while login uses the full email address.
|
|
|
|
Then run the controlled sending checklist from
|
|
`docs/CAMPAIGN_DELIVERY_RUNBOOK.md` for no attachment, one attachment, and
|
|
password-protected ZIP campaign variants.
|
|
|
|
## Stop
|
|
|
|
```bash
|
|
docker compose --env-file .env down -v
|
|
```
|