From 4633758f0c7313b56626a0316fa0f0567823275f Mon Sep 17 00:00:00 2001 From: Adriano Caloiaro Date: Mon, 20 Jul 2026 18:03:49 -0600 Subject: [PATCH] docs: document mbsync coexistence gotcha --- README.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/README.md b/README.md index 272b40c..6d82793 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,73 @@ Module options: | `logLevel` | enum | `"info"` | `debug`, `info`, `warn`, or `error` | | `accounts` | list | `[]` | List of account submodules (see config file fields above) | +## Using mbrts alongside mbsync + +mbrts handles inbound delivery; mbsync is still useful for pushing local changes (read flags, deletions, moves) back to Fastmail. They can coexist, but need careful configuration to avoid duplicate messages. + +The problem is that mbsync tracks synced messages by IMAP UID in its own state database. It knows nothing about messages mbrts delivered directly to the Maildir. Because of this blindness to mbrts, mbsync re-downloads messages that mbrts has already written, creating duplicates. + +The fix is to give mbsync two separate channels per account; one for the scheduled sync (flags and deletions only, no new messages), and one for mbrts to call on-demand as a fallback when its JMAP state is missing or stale. + +``` +# scheduled channel — only pushes local changes upstream +Channel Personal +Far :Personal-remote: +Near :Personal-local: +Sync Flags Delete + +# pull channel — only used by mbrts on fallback +Channel Personal-pull +Far :Personal-remote: +Near :Personal-local: +Sync New +``` + +Point mbrts at the pull channel via `mbsync_account`: + +```yaml +accounts: + - name: Personal + maildir_path: /home/you/.mail/Personal + password_command: "pass show fastmail/api-token" + mbsync_account: Personal-pull +``` + +Any scheduled mbsync timers then runs `mbsync Personal` (flags/deletions only), while mbrts calls `mbsync Personal-pull` on fallback (new messages only). + +### With home-manager + +Restrict the auto-generated channel to flags and deletions via `extraConfig.channel`, then append the pull-only channel via `programs.mbsync.extraConfig`: + +```nix +# per-account: restrict scheduled sync to flags/deletions +accounts.email.accounts.Personal.mbsync = { + enable = true; + extraConfig.channel.Sync = "Flags Delete"; + # ... other mbsync options +}; + +# global: define a pull-only channel for mbrts fallback +programs.mbsync.extraConfig = '' + Channel Personal-pull + Far :Personal-remote: + Near :Personal-local: + Sync New + Create Near + SyncState * +''; + +# point mbrts at the pull channel +services.mbrts.accounts = [ + { + name = "Personal"; + maildirPath = "/home/you/.mail/Personal"; + passwordCommand = "pass show fastmail/api-token"; + mbsyncAccount = "Personal-pull"; + } +]; +``` + ## Build ```