Adds tests/test_integration_send_scan.py: 7 harness-gated cases covering delivery and Message-ID correlation, scanner ingestion without a delivery claim, idempotency, resend, suppression, rejected requests never reaching the provider, and verification mail carrying no authorization. Fixes the reply heuristic, which matched against headers as well as body. The Received: trace that every MTA-handled message carries matched its "received" keyword, so ordinary mail was classified human_reply with a success.reply_received assessment at medium confidence -- the exact overclaim this repo exists to prevent. Hand-written fixtures have no Received headers, so only real scanned mail exposed it. The heuristic now takes the body alone; DSN detection still sees headers, which it needs. Regression test is offline. Fixes the provider reference: SMTPProvider set no Message-ID, so send() fell back to abs(hash((recipient, subject))) -- randomized per process and colliding for equal recipient/subject. Outgoing mail now carries a proper RFC 5322 Message-ID, returned as the reference, which is what makes send-to-scan correlation testable. Suite: 72 passed with the harness up, 62 passed + 10 skipped with it down. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|---|---|---|
| .claude/rules | ||
| .forgejo/workflows | ||
| config | ||
| deploy/k8s/railiance | ||
| docs | ||
| registry | ||
| reports | ||
| spec | ||
| src/email_connect | ||
| tests | ||
| workplans | ||
| .custodian-brief.md | ||
| .gitignore | ||
| .repo-classification.yaml | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| Containerfile | ||
| DECISIONS.md | ||
| INTENT.md | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| SCOPE.md | ||
| WORK-RECORDS.md | ||
email-connect
Headless, provider-neutral email communication and evidence service.
The first implementation slice is the Mailbox Evidence Scanner MVP: scan a return mailbox or fixture directory, classify inbound email-channel evidence, store scan state locally, and generate timestamped CSV reports without overclaiming delivery, awareness, or coordination success.
Quickstart
PYTHONPATH=src python3 -m unittest discover -s tests
PYTHONPATH=src python3 -m email_connect.cli adapter-descriptor
PYTHONPATH=src python3 -m email_connect.cli scan-mailbox --config config/mailbox.example.yml --out reports/
PYTHONPATH=src python3 -m email_connect.cli scan-mailbox --config config/mailbox.example.yml --expected-recipients tests/fixtures/expected_recipients.txt --out reports/
The example config uses tests/fixtures/mailbox as a mailbox source. Runtime
state is written to .email-connect/state.sqlite; generated CSV reports are
written to reports/.
Expected recipients are optional. When provided as a text file or CSV, reports
include a known_recipient column, place known recipients first, and add
undef.no_signal diagnostics for expected recipients with no mailbox evidence.
See Mailbox Report Tutorial.
For a live mailbox, set mailbox.protocol: imap, configure host, port, folder,
and credential environment variable names, then export the credentials before
running scan-mailbox. IMAP scans select the configured folder read-only and
fetch message bodies with BODY.PEEK[]; mailbox write-back actions such as
marking messages seen are intentionally unsupported in this MVP.
Current Scope
- Coordination-engine spec review and references.
- Initial adapter descriptor, capability profile, evidence ceiling, and limitations.
- Fixture and read-only IMAP mailbox sources.
- Conservative mailbox message parser and evidence mapper.
- SQLite state store with scan cursor, message/evidence deduplication, and endpoint quality hints.
- CSV report generation, including
--report-only-new. - Optional expected-recipient text/CSV input,
known_recipientreport filtering, no-evidence diagnostics, and datetime range filtering. - Golden fixture tests for hard bounce, soft bounce, delayed delivery, final failure, complaint, unsubscribe, challenge-response, unknown return, parse-failure, out-of-office, and human reply signals.
Provider webhooks, outbound sending, suppression workflows, OAuth mailbox login, and a UI remain outside this first mailbox-scanner slice.