Commit Graph
7 Commits
Author SHA1 Message Date
rustmailer c6da79cdb0 feat(config): add built-in IMAP server config with shared SMTP/IMAP TLS paths 2026-07-15 09:40:44 +08:00
rustmailer 89557700ae Merge branch 'main' of https://github.com/rustmailer/bichon 2026-06-11 09:23:00 +08:00
rustmailer 2f5de48c6a fix(smtp): reject journaling attempts to non-local accounts 2026-06-11 09:22:57 +08:00
JoshandClaude Opus 4.8 ce3f8944a3 fix(smtp): don't clobber the IMAP-owned INBOX uid_validity on journal ingest
When SMTP journaling ingests a message, parse_email() upserts the account's
INBOX MailBox row so the journaled envelope has a row to attach to. But it
built the row with uid_validity/highest_uid/uid_next = None and called
batch_upsert, which replaces the WHOLE row. The INBOX row id
(create_hash(account_id, "INBOX")) is the same id the IMAP sync maintains,
so every journaled delivery reset the IMAP-maintained uid_validity to None.

On the next reconcile, local_mailbox.uid_validity != Some(remote) is then
true, so the mailbox is treated as invalid and wiped + rebuilt. For a large,
UID-sparse INBOX whose rebuild gets interrupted, the local copy is silently
lost and never restored (the incremental fetch resumes past all existing
UIDs). See #297 for the full diagnosis and DB evidence.

Fix: only create the INBOX row when it does not already exist; otherwise
leave the IMAP-owned row untouched. The journaling path only needs the row
to exist so the envelope can attach to it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 11:36:38 -07:00
rustmailer 83dd9cdd6b perf: optimize IMAP account fetch flow 2026-05-26 15:23:34 +08:00
rustmailer 5406c4322c refactor: replace native_db with memdb and add tests 2026-05-14 02:29:23 +08:00
rustmailer 0b866c81ff refactor(workspace): decompose project into multiple crates 2026-04-23 21:45:34 +08:00