Problem
When a user account is created via the API (not the web signup), the inbox starts empty. The backfill cursor gets set to 0 because there are no messages yet. Later, when emails arrive in the IMAP server, the backfill tick sees cursor = 0 and skips straight to IDLE — it never fetches those messages.
The real-time IDLE loop works fine and catches new messages going forward. But anything that landed between account creation and the IDLE connection starting is lost.
Where in the code
discover-mailboxes.ts ~line 114: backfillCursorUid: Math.max(0, (box.uidNext ?? 1) - 1) — empty mailbox → cursor = 0
backfill-full.ts ~line 123: if (cursor <= 0) → immediately sets phase to IDLE, skips backfill
Our setup
We use Kurrier as a webmail frontend with Stalwart as the IMAP/SMTP backend. Stalwart is our source of truth for mail, with Baikal as a sync layer for calendar and contacts. Accounts are provisioned via SQL + API, not the signup form. While building this setup we noticed the inbox stayed empty after setup even though Stalwart had messages.
Suggested fix
When backfillCursorUid is 0, re-check uidNext from the IMAP server before giving up. If uidNext > 1, there are messages to fetch — set the cursor and proceed.
Problem
When a user account is created via the API (not the web signup), the inbox starts empty. The backfill cursor gets set to
0because there are no messages yet. Later, when emails arrive in the IMAP server, the backfill tick seescursor = 0and skips straight to IDLE — it never fetches those messages.The real-time IDLE loop works fine and catches new messages going forward. But anything that landed between account creation and the IDLE connection starting is lost.
Where in the code
discover-mailboxes.ts~line 114:backfillCursorUid: Math.max(0, (box.uidNext ?? 1) - 1)— empty mailbox → cursor = 0backfill-full.ts~line 123:if (cursor <= 0)→ immediately sets phase to IDLE, skips backfillOur setup
We use Kurrier as a webmail frontend with Stalwart as the IMAP/SMTP backend. Stalwart is our source of truth for mail, with Baikal as a sync layer for calendar and contacts. Accounts are provisioned via SQL + API, not the signup form. While building this setup we noticed the inbox stayed empty after setup even though Stalwart had messages.
Suggested fix
When
backfillCursorUidis 0, re-checkuidNextfrom the IMAP server before giving up. IfuidNext > 1, there are messages to fetch — set the cursor and proceed.