routing smoke: seed synthetic mail into Stalwart; make targeted intake work there #2

Merged
founder merged 1 commit from claude/routing-smoke-seed-stalwart into main 2026-08-16 06:12:15 +00:00
Owner

The identity-routing smoke's mail legs (mail-trusted-billing-cfo, mail-trusted-billing-assistant, mail-trusted-security, mail-review-billing) have never passed since c4a5029 made /webhook/forwardemail wake the Stalwart mirror instead of enqueueing the payload: the synthetic message never existed in Forward Email or Stalwart, so the targeted intake found nothing and the legs timed out with status=missing.

Two fixes:

  1. Targeted intake on Stalwart. The wake runs agent-dispatcher mail --once --message-id <id>, which only asked for SEARCH HEADER Message-ID. Stalwart 0.15 answers HEADER searches on unindexed fields with an empty result rather than an error (verified against the forge: HEADER Subject/From hit, HEADER Message-ID/Date empty), so the wake path never intook anything for real mail either — messages waited for the periodic unseen sweep. findMessagesByMessageID keeps the server-side search but, when it comes back empty, fetches just the Message-Id header of the unseen messages plus the newest 50 and matches client-side, still touching only the requested message. Regression test runs pollMailbox against a header-blind go-imap memory backend.
  2. Smoke seeding. identity-routing-smoke.sh now APPENDs each synthetic message (same Message-ID/From/To/Subject, no-action body) into the target account's Stalwart INBOX over IMAP before posting the webhook, using KEYSTORE_ROUTING_SMOKE_MAIL_ACCOUNTS=<alias>=<account>:<password_file>,... (the same alias → account mapping the key-store-forwardemail-wake@ unit uses) and KEYSTORE_ROUTING_SMOKE_IMAP_ADDR. Seeding is idempotent across the stable Message-IDs the smoke reuses, retries the transient LDAP auth failures the intake also retries, and is skipped when no mapping is configured. The security leg is addressed to security@key.store, the real Forward Email alias the wake command can mirror, instead of the security-agent login.

README documents the wake path and the seeding contract. The key.store side (env derived from forwardEmailMirrorMailboxes + dispatch_src bump + forge deploy) follows in key.store.

🤖 Generated with Claude Code

The identity-routing smoke's mail legs (`mail-trusted-billing-cfo`, `mail-trusted-billing-assistant`, `mail-trusted-security`, `mail-review-billing`) have never passed since c4a5029 made `/webhook/forwardemail` wake the Stalwart mirror instead of enqueueing the payload: the synthetic message never existed in Forward Email or Stalwart, so the targeted intake found nothing and the legs timed out with `status=missing`. Two fixes: 1. **Targeted intake on Stalwart.** The wake runs `agent-dispatcher mail --once --message-id <id>`, which only asked for `SEARCH HEADER Message-ID`. Stalwart 0.15 answers HEADER searches on unindexed fields with an empty result rather than an error (verified against the forge: `HEADER Subject`/`From` hit, `HEADER Message-ID`/`Date` empty), so the wake path never intook anything for real mail either — messages waited for the periodic unseen sweep. `findMessagesByMessageID` keeps the server-side search but, when it comes back empty, fetches just the Message-Id header of the unseen messages plus the newest 50 and matches client-side, still touching only the requested message. Regression test runs `pollMailbox` against a header-blind go-imap memory backend. 2. **Smoke seeding.** `identity-routing-smoke.sh` now APPENDs each synthetic message (same Message-ID/From/To/Subject, no-action body) into the target account's Stalwart INBOX over IMAP before posting the webhook, using `KEYSTORE_ROUTING_SMOKE_MAIL_ACCOUNTS=<alias>=<account>:<password_file>,...` (the same alias → account mapping the `key-store-forwardemail-wake@` unit uses) and `KEYSTORE_ROUTING_SMOKE_IMAP_ADDR`. Seeding is idempotent across the stable Message-IDs the smoke reuses, retries the transient LDAP auth failures the intake also retries, and is skipped when no mapping is configured. The security leg is addressed to `security@key.store`, the real Forward Email alias the wake command can mirror, instead of the `security-agent` login. README documents the wake path and the seeding contract. The key.store side (env derived from `forwardEmailMirrorMailboxes` + `dispatch_src` bump + forge deploy) follows in key.store. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The identity-routing smoke's mail legs (mail-trusted-billing-cfo,
mail-trusted-billing-assistant, mail-trusted-security, mail-review-billing)
have never passed since c4a5029 made the Forward Email webhook wake the
Stalwart mirror instead of enqueueing the payload: the synthetic message never
existed in Forward Email or Stalwart, so the targeted intake found nothing and
the legs timed out with status=missing.

Two things were wrong, and this fixes both:

- The webhook wake runs `agent-dispatcher mail --once --message-id <id>`,
  which only asked Stalwart for SEARCH HEADER Message-ID. Stalwart 0.15
  answers HEADER searches on unindexed fields with an empty result rather than
  an error, so the wake path never intook anything for real mail either;
  messages waited for the periodic unseen sweep. findMessagesByMessageID now
  keeps the server-side search but, when it comes back empty, fetches just the
  Message-Id header of the unseen messages plus the newest 50 and matches
  client-side, still touching only the requested message. Regression test
  runs pollMailbox against a header-blind go-imap memory backend.

- identity-routing-smoke.sh now APPENDs each synthetic message (same
  Message-ID/From/To/Subject, no-action body) into the target account's
  Stalwart INBOX over IMAP before posting the webhook, using the alias ->
  account:password_file mapping in KEYSTORE_ROUTING_SMOKE_MAIL_ACCOUNTS (the
  same mapping the key-store-forwardemail-wake@ unit uses) and
  KEYSTORE_ROUTING_SMOKE_IMAP_ADDR. Seeding is idempotent across the stable
  Message-IDs the smoke reuses, retries the transient LDAP auth failures the
  intake also retries, and is skipped when no mapping is configured. The
  security leg is addressed to security@key.store, the real Forward Email
  alias the wake command can mirror, instead of the security-agent login.

README documents the wake path and the seeding contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
key-store/dispatch!2
No description provided.