@bobfrankston/rmfmail 1.2.295 → 1.2.297

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.commitmsg +29 -15
  2. package/client/android-bootstrap.bundle.js +69 -11
  3. package/client/android-bootstrap.bundle.js.map +3 -3
  4. package/client/app.bundle.js +30 -0
  5. package/client/app.bundle.js.map +3 -3
  6. package/client/app.js +27 -1
  7. package/client/app.js.map +1 -1
  8. package/client/app.ts +25 -1
  9. package/client/index.html +5 -0
  10. package/client/styles/components.css +22 -5
  11. package/npmchanges.md +53 -0
  12. package/package.json +8 -8
  13. package/packages/mailx-imap/index.d.ts +1 -0
  14. package/packages/mailx-imap/index.d.ts.map +1 -1
  15. package/packages/mailx-imap/index.js +75 -11
  16. package/packages/mailx-imap/index.js.map +1 -1
  17. package/packages/mailx-imap/index.ts +76 -12
  18. package/packages/mailx-imap/package-lock.json +2 -2
  19. package/packages/mailx-imap/package.json +1 -1
  20. package/packages/mailx-settings/package.json +1 -1
  21. package/packages/mailx-store/package.json +1 -1
  22. package/packages/mailx-store-web/android-bootstrap.d.ts.map +1 -1
  23. package/packages/mailx-store-web/android-bootstrap.js +6 -2
  24. package/packages/mailx-store-web/android-bootstrap.js.map +1 -1
  25. package/packages/mailx-store-web/android-bootstrap.ts +8 -2
  26. package/packages/mailx-store-web/package.json +1 -1
  27. package/packages/mailx-types/index.d.ts +1 -0
  28. package/packages/mailx-types/index.d.ts.map +1 -1
  29. package/packages/mailx-types/index.js +1 -0
  30. package/packages/mailx-types/index.js.map +1 -1
  31. package/packages/mailx-types/index.ts +1 -0
  32. package/packages/mailx-types/log-changes.d.ts +29 -0
  33. package/packages/mailx-types/log-changes.d.ts.map +1 -0
  34. package/packages/mailx-types/log-changes.js +42 -0
  35. package/packages/mailx-types/log-changes.js.map +1 -0
  36. package/packages/mailx-types/log-changes.ts +44 -0
  37. package/packages/mailx-types/package.json +1 -1
  38. /package/packages/mailx-imap/{node_modules.npmglobalize-stash-52364 → node_modules.npmglobalize-stash-77248}/.package-lock.json +0 -0
package/client/app.ts CHANGED
@@ -2157,7 +2157,7 @@ document.getElementById("btn-flag")?.addEventListener("click", async () => {
2157
2157
  try {
2158
2158
  await updateFlags(sel.accountId, sel.uid, sel.flags, (sel as any).folderId);
2159
2159
  messageState.updateMessageFlags(sel.accountId, sel.uid, sel.flags, (sel as any).folderId);
2160
- // Row owns its own DOM \u2014 go through the row object so class + star
2160
+ // Row owns its own DOM go through the row object so class + star
2161
2161
  // update atomically and the list/preview stay in sync.
2162
2162
  setRowFlagged(sel.accountId, sel.uid, !wasFlagged, (sel as any).folderId);
2163
2163
  } catch (e: unknown) {
@@ -5537,6 +5537,27 @@ function syncFilterFlaggedButton(): void {
5537
5537
  btn.setAttribute("aria-pressed", optFlagged?.checked ? "true" : "false");
5538
5538
  }
5539
5539
 
5540
+ /** Name the active list filter above the list, and make the name the way out
5541
+ * of it. The filter used to announce itself by tinting every row — which is
5542
+ * how the list says "selected", so a filtered list read as a selected one
5543
+ * (Bob 2026-08-29: "if I press * on search it shouldn't automatically select
5544
+ * those letters, just show them"). Names which filter, not "a filter is on". */
5545
+ function syncFilterChip(): void {
5546
+ const chip = document.getElementById("ml-filter-chip");
5547
+ if (!chip) return;
5548
+ const flagged = !!(document.getElementById("opt-flagged") as HTMLInputElement | null)?.checked;
5549
+ const priority = !!(document.getElementById("opt-priority-only") as HTMLInputElement | null)?.checked;
5550
+ const names = [flagged ? "flagged (★) messages" : "", priority ? "priority senders" : ""].filter(Boolean);
5551
+ if (!names.length) { chip.hidden = true; return; }
5552
+ chip.hidden = false;
5553
+ chip.textContent = "Showing " + names.join(" and ") + " only — click to show everything";
5554
+ chip.title = "Clear the list filter";
5555
+ }
5556
+
5557
+ document.getElementById("ml-filter-chip")?.addEventListener("click", () => {
5558
+ document.dispatchEvent(new CustomEvent("mailx-clear-list-filters"));
5559
+ });
5560
+
5540
5561
  function applyFlaggedFilter(on: boolean): void {
5541
5562
  try { logClientEvent("applyFlaggedFilter", { on, caller: new Error().stack?.split("\n").slice(2, 5).join(" | ") }); } catch { /* */ }
5542
5563
  if (optFlagged) optFlagged.checked = on;
@@ -5545,6 +5566,7 @@ function applyFlaggedFilter(on: boolean): void {
5545
5566
  else body?.classList.remove("flagged-only");
5546
5567
  localStorage.setItem("mailx-flagged", String(on));
5547
5568
  syncFilterFlaggedButton();
5569
+ syncFilterChip();
5548
5570
  reloadCurrentFolder();
5549
5571
  }
5550
5572
 
@@ -5559,6 +5581,7 @@ document.getElementById("btn-filter-flagged")?.addEventListener("click", () => {
5559
5581
  // Initial paint of the button's pressed state (covers the localStorage-restored
5560
5582
  // value loaded earlier in this file).
5561
5583
  syncFilterFlaggedButton();
5584
+ syncFilterChip();
5562
5585
 
5563
5586
  // Priority-senders-only filter — same pattern as flagged-only. Adds
5564
5587
  // .priority-only to the list body; CSS hides any row without .priority.
@@ -5572,6 +5595,7 @@ if (optPriorityOnly) {
5572
5595
  if (optPriorityOnly.checked) body?.classList.add("priority-only");
5573
5596
  else body?.classList.remove("priority-only");
5574
5597
  localStorage.setItem("mailx-priority-only", String(optPriorityOnly.checked));
5598
+ syncFilterChip();
5575
5599
  });
5576
5600
  }
5577
5601
 
package/client/index.html CHANGED
@@ -849,6 +849,11 @@
849
849
  <button type="button" id="search-help" class="search-help-btn" title="Search syntax help">?</button>
850
850
  </search>
851
851
  <div class="ml-folder-title" id="ml-folder-title"></div>
852
+ <!-- Active list filter, named. Replaces the full-list colour wash:
853
+ a tint over the rows reads as "these are selected" (Bob
854
+ 2026-08-29: "it shouldnt automatically select those letters,
855
+ just show them"). Click clears the filter. -->
856
+ <button type="button" class="ml-filter-chip" id="ml-filter-chip" hidden></button>
852
857
  <div class="ml-header" id="ml-header">
853
858
  <span class="ml-col ml-col-avatar"></span>
854
859
  <span class="ml-col ml-col-flag"></span>
@@ -736,11 +736,28 @@ button.tb-menu-item { background: none; border: none; color: inherit; width: 100
736
736
  .message-list.no-empty-stars .ml-row:not(.flagged) .ml-flag { opacity: 0; }
737
737
  .message-list.no-empty-stars .ml-row:not(.flagged):hover .ml-flag { opacity: 1; }
738
738
  .flagged-only .ml-row:not(.flagged) { display: none; }
739
- /* Flagged-only filter active wash the whole list in the flag colour so the
740
- active filter is unmistakable at a glance, instead of relying on the search
741
- button's thin active underline (Bob 2026-06-26). Rows are transparent, so
742
- the tint shows through; flagged rows' own 8% tint layers on top. */
743
- #ml-body.flagged-only { background-color: color-mix(in oklch, var(--color-flag-star) 16%, transparent); }
739
+ /* The active filter is announced by the #ml-filter-chip above the list, NOT
740
+ by tinting the rows. The wash added 2026-06-26 made the filter unmistakable
741
+ and made the messages under it look selected, which is a different claim
742
+ (Bob 2026-08-29: "if I press * on search it shouldn't automatically select
743
+ those letters, just show them"). A row's background is the list's way of
744
+ saying "this one is chosen"; a filter must not borrow it. */
745
+ .ml-filter-chip {
746
+ display: block;
747
+ width: 100%;
748
+ text-align: left;
749
+ font: inherit;
750
+ font-size: 0.85em;
751
+ padding: 2px var(--gap-md);
752
+ border: 0;
753
+ border-bottom: 1px solid var(--color-border, #ddd);
754
+ background: color-mix(in oklch, var(--color-flag-star) 22%, transparent);
755
+ color: inherit;
756
+ cursor: pointer;
757
+ }
758
+
759
+ .ml-filter-chip:hover { background: color-mix(in oklch, var(--color-flag-star) 34%, transparent); }
760
+ .ml-filter-chip[hidden] { display: none; }
744
761
  /* Flagged row star: gold/amber (--color-flag-star, oklch hue 60) — the
745
762
  same colour as the viewer toolbar Flag button (#btn-flag.flagged).
746
763
  Scaled up via transform (not font-size) so the bigger glyph can't grow
package/npmchanges.md CHANGED
@@ -1162,3 +1162,56 @@ Two more tests in tests/allowlist-merge.test.ts: a stated removal sticks while
1162
1162
  its neighbours stay, and removals match case-insensitively like every other
1163
1163
  address comparison in this codebase.
1164
1164
 
1165
+ ## v1.2.295 — 2026-08-28
1166
+
1167
+ A cloud read must not cache over a local write that beat it home
1168
+
1169
+ Untrusting a sender wrote correctly to Drive — a clean restart pulled the right
1170
+ list — while the LOCAL copy still had the entry, mtime stamped at the moment of
1171
+ the write. A cloud read that started before the write finished after it, and
1172
+ its caching step put the pre-change content back on disk. Everything read
1173
+ through the sync loadAllowlist() then saw the value the user had just removed,
1174
+ until the next poll happened to overwrite it with the truth.
1175
+
1176
+ cloudRead now stamps each shared file's last local write and skips its cache
1177
+ step when the file changed while the read was in flight — the content it holds
1178
+ is older than what is on disk, and the local write has already gone to the
1179
+ cloud. The stamp is taken BEFORE the write, so a race resolves in favour of the
1180
+ local copy.
1181
+
1182
+ Same shape as the contacts.jsonc flush clobber, and the same lesson: the local
1183
+ file is not a cache to be overwritten, it is a copy someone may have just
1184
+ edited.
1185
+
1186
+ ## v1.2.296 — 2026-08-29
1187
+
1188
+ A star set on the phone now reaches the desktop in seconds, not minutes
1189
+
1190
+ Bob 2026-08-29: "how long should it take for a * on the phone to get to my
1191
+ desktop?" Measured, on his own log: a median of 5 minutes and up to 20.
1192
+
1193
+ Why: gal.iecc.com does not advertise NOTIFY, so the desktop watches INBOX with
1194
+ plain IDLE. The server DOES push a flag change there as an unsolicited
1195
+ `* 1234 FETCH (FLAGS (\Seen \Flagged))` — iflow-direct dropped it (fixed in
1196
+ 0.1.67), and mailx had nothing to receive it with. The 5-minute quick check
1197
+ could not help either: it is a STATUS poll, and MESSAGES / UNSEEN / UIDNEXT do
1198
+ not move when a message is starred. So the only path was the periodic full
1199
+ sync's QRESYNC pass — which is why the numbers above are the sync cadence
1200
+ rather than any property of flags.
1201
+
1202
+ The IDLE watcher now takes `onFlagChange` and, debounced 1.5 s, runs the
1203
+ folder's normal QRESYNC pass — the same one that already reconciles flags and
1204
+ took 53 ms in that log. Marking ten messages read on the phone arrives as ten
1205
+ pushes and costs one pass. Our own STOREs bounce back as flag pushes too, so
1206
+ the handler skips while this account has sync actions draining; the local store
1207
+ already has those.
1208
+
1209
+ INBOX only, because IDLE watches one mailbox per connection. Flags changed in
1210
+ other folders still wait for that folder's turn in the sync cycle.
1211
+
1212
+ Also in this build: the log noise behind it. `[search]` / `[fetch]` per-command
1213
+ lines moved behind iflow's existing `verbose` flag, and the repeated
1214
+ per-folder reconcile lines now go through `logIfChanged` — first occurrence,
1215
+ every change, and an hourly restatement — instead of once per folder per cycle
1216
+ forever. On Android each of those lines was an HTTP request to the log server.
1217
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/rmfmail",
3
- "version": "1.2.295",
3
+ "version": "1.2.297",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
@@ -28,14 +28,14 @@
28
28
  "watch": "tsc -w",
29
29
  "release": "npmglobalize",
30
30
  "test": "node --experimental-strip-types --test tests/*.test.ts tests/dom/*.test.ts",
31
- "test:fast": "node --experimental-strip-types --test tests/dedup.test.ts tests/dedup-newest.test.ts tests/dupcount.test.ts tests/search.test.ts tests/sync-coalesce.test.ts tests/undelete.test.ts tests/body-load.test.ts tests/allowlist-merge.test.ts tests/dom/_smoke.test.ts tests/dom/viewer-scroll.test.ts tests/dom/viewer-rerender-guard.test.ts tests/dom/harper-lint.test.ts",
31
+ "test:fast": "node --experimental-strip-types --test tests/dedup.test.ts tests/dedup-newest.test.ts tests/dupcount.test.ts tests/search.test.ts tests/sync-coalesce.test.ts tests/undelete.test.ts tests/body-load.test.ts tests/allowlist-merge.test.ts tests/log-changes.test.ts tests/dom/_smoke.test.ts tests/dom/viewer-scroll.test.ts tests/dom/viewer-rerender-guard.test.ts tests/dom/harper-lint.test.ts",
32
32
  "postinstall": "node bin/postinstall.js"
33
33
  },
34
34
  "dependencies": {
35
- "@bobfrankston/iflow-direct": "^0.1.65",
35
+ "@bobfrankston/iflow-direct": "^0.1.68",
36
36
  "@bobfrankston/mailx-host": "^0.1.15",
37
- "@bobfrankston/mailx-imap": "^0.1.167",
38
- "@bobfrankston/mailx-store-web": "^0.1.97",
37
+ "@bobfrankston/mailx-imap": "^0.1.169",
38
+ "@bobfrankston/mailx-store-web": "^0.1.99",
39
39
  "@bobfrankston/mailx-sync": "^0.1.29",
40
40
  "@bobfrankston/miscinfo": "^1.0.20",
41
41
  "@bobfrankston/msger": "^0.1.429",
@@ -114,10 +114,10 @@
114
114
  },
115
115
  ".transformedSnapshot": {
116
116
  "dependencies": {
117
- "@bobfrankston/iflow-direct": "^0.1.65",
117
+ "@bobfrankston/iflow-direct": "^0.1.68",
118
118
  "@bobfrankston/mailx-host": "^0.1.15",
119
- "@bobfrankston/mailx-imap": "^0.1.167",
120
- "@bobfrankston/mailx-store-web": "^0.1.97",
119
+ "@bobfrankston/mailx-imap": "^0.1.169",
120
+ "@bobfrankston/mailx-store-web": "^0.1.99",
121
121
  "@bobfrankston/mailx-sync": "^0.1.29",
122
122
  "@bobfrankston/miscinfo": "^1.0.20",
123
123
  "@bobfrankston/msger": "^0.1.429",
@@ -237,6 +237,7 @@ export declare class ImapManager extends EventEmitter {
237
237
  slow?: boolean;
238
238
  lane?: string;
239
239
  timeoutMs?: number;
240
+ priority?: boolean;
240
241
  }): Promise<T>;
241
242
  /** Drain the next queued task on EVERY lane for the account. Lanes run
242
243
  * concurrently — each on its own connection — and the per-lane running
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ import { createAutoImapConfig, CompatImapClient } from "@bobfrankston/iflow-dire
7
7
  import { authenticateOAuth, clearReauthBackoff } from "@bobfrankston/oauthsupport";
8
8
  import { parseSerial, fixCharsetDeclString, storeBus } from "@bobfrankston/mailx-store";
9
9
  import { loadSettings, getConfigDir, getHistoryDays, getPrefetch, tokenDirName } from "@bobfrankston/mailx-settings";
10
- import { isJunkPreviewText } from "@bobfrankston/mailx-types";
10
+ import { isJunkPreviewText, logIfChanged } from "@bobfrankston/mailx-types";
11
11
  import { EventEmitter } from "node:events";
12
12
  import * as fs from "node:fs";
13
13
  import * as path from "node:path";
@@ -874,7 +874,19 @@ export class ImapManager extends EventEmitter {
874
874
  reject(e);
875
875
  }
876
876
  };
877
- queue.tasks.push(task);
877
+ // A task the user is waiting on goes to the FRONT of its lane.
878
+ // Lanes are strictly sequential, so without this a click-time body
879
+ // fetch sits behind whatever background work was queued first and
880
+ // can only start after all of it — Bob 2026-08-29: "if I look at a
881
+ // letter while sync things get confused … viewing the body should
882
+ // get priority instead of waiting for sync". It cannot preempt the
883
+ // command already in flight (an IMAP command cannot be cancelled
884
+ // without dropping the connection), but it no longer waits for the
885
+ // whole backlog.
886
+ if (opts.priority)
887
+ queue.tasks.unshift(task);
888
+ else
889
+ queue.tasks.push(task);
878
890
  this.drainOpsQueue(accountId);
879
891
  });
880
892
  }
@@ -2405,10 +2417,13 @@ export class ImapManager extends EventEmitter {
2405
2417
  && statusMessageCount !== null
2406
2418
  && serverUidsArr.length === statusMessageCount;
2407
2419
  if (serverUidsArr.length === 0 && localUidsAll.length > 0 && !authoritative) {
2408
- console.log(` [sync] ${accountId}/${folder.path}: reconcile skipped server UID list empty but local has ${localUidsAll.length} (treating as transient)`);
2420
+ // Same line every cycle for a folder stuck in this state
2421
+ // logIfChanged prints the first one, each change, and an
2422
+ // hourly restatement. (Claude Code 2026-08-29)
2423
+ logIfChanged(`${accountId}/${folder.path}:reconcile`, ` [sync] ${accountId}/${folder.path}: reconcile skipped — server UID list empty but local has ${localUidsAll.length} (treating as transient)`);
2409
2424
  }
2410
2425
  else if (!authoritative && localUids.length > 0 && toDelete.length / localUids.length > 0.5) {
2411
- console.log(` [sync] ${accountId}/${folder.path}: reconcile REFUSED — would delete ${toDelete.length}/${localUids.length} (${Math.round(toDelete.length / localUids.length * 100)}%) — probably a sync bug, skipping`);
2426
+ logIfChanged(`${accountId}/${folder.path}:reconcile`, ` [sync] ${accountId}/${folder.path}: reconcile REFUSED — would delete ${toDelete.length}/${localUids.length} (${Math.round(toDelete.length / localUids.length * 100)}%) — probably a sync bug, skipping`);
2412
2427
  }
2413
2428
  else if (toDelete.length > 0) {
2414
2429
  // DEFERRED DELETE — DO NOT delete immediately. Server-side
@@ -2888,10 +2903,10 @@ export class ImapManager extends EventEmitter {
2888
2903
  const serverUids = new Set(serverUidsArr);
2889
2904
  const localUids = this.db.getUidsForFolder(accountId, folder.id);
2890
2905
  if (serverUidsArr._truncated) {
2891
- console.log(` [api] ${accountId}/${folder.path}: reconcile skipped — server list truncated (${serverUidsArr.length} ids)`);
2906
+ logIfChanged(`${accountId}/${folder.path}:api-reconcile`, ` [api] ${accountId}/${folder.path}: reconcile skipped — server list truncated (${serverUidsArr.length} ids)`);
2892
2907
  }
2893
2908
  else if (serverUidsArr.length === 0 && localUids.length > 0) {
2894
- console.log(` [api] ${accountId}/${folder.path}: reconcile skipped — server list empty but local has ${localUids.length}`);
2909
+ logIfChanged(`${accountId}/${folder.path}:api-reconcile`, ` [api] ${accountId}/${folder.path}: reconcile skipped — server list empty but local has ${localUids.length}`);
2895
2910
  }
2896
2911
  else {
2897
2912
  const toDelete = localUids.filter(uid => !serverUids.has(uid));
@@ -2925,7 +2940,7 @@ export class ImapManager extends EventEmitter {
2925
2940
  }
2926
2941
  }
2927
2942
  if (!confirmed) {
2928
- console.log(` [api] ${accountId}/${folder.path}: reconcile refused — would delete ${toDelete.length}/${localUids.length} (${Math.round(toDelete.length / localUids.length * 100)}%) — probably a sync bug, skipping`);
2943
+ logIfChanged(`${accountId}/${folder.path}:api-reconcile`, ` [api] ${accountId}/${folder.path}: reconcile refused — would delete ${toDelete.length}/${localUids.length} (${Math.round(toDelete.length / localUids.length * 100)}%) — probably a sync bug, skipping`);
2929
2944
  }
2930
2945
  else {
2931
2946
  for (const uid of toDelete) {
@@ -3511,10 +3526,41 @@ export class ImapManager extends EventEmitter {
3511
3526
  this.syncFolder(accountId, inbox.id).catch(e => console.error(` [idle] expunge reconcile failed: ${e.message}`));
3512
3527
  }, 2000);
3513
3528
  };
3529
+ // A flag changed on a message we already have — someone starred
3530
+ // or read it on another client. The server pushes it during
3531
+ // IDLE as an unsolicited FETCH; before v1.2.296 that was
3532
+ // dropped, so a star set on the phone reached the desktop only
3533
+ // on the next periodic sync of INBOX. Measured on Bob's own
3534
+ // log that was a median of 5 minutes and up to 20 (Bob
3535
+ // 2026-08-29: "how long should it take for a * on the phone to
3536
+ // get to my desktop?").
3537
+ //
3538
+ // The push says WHICH flags but by sequence number, which this
3539
+ // connection cannot map to a UID reliably — so it triggers the
3540
+ // folder's normal QRESYNC pass, which asks the server for
3541
+ // exactly what changed since our modseq and took 53 ms in the
3542
+ // same log. Debounced: marking ten messages read on the phone
3543
+ // arrives as ten pushes.
3544
+ let flagTimer = null;
3545
+ const onFlagChange = () => {
3546
+ if (flagTimer)
3547
+ clearTimeout(flagTimer);
3548
+ flagTimer = setTimeout(() => {
3549
+ flagTimer = null;
3550
+ // Our own STOREs bounce straight back as flag pushes;
3551
+ // the local store already has those.
3552
+ if (this.db.getPendingSyncActions(accountId).length > 0)
3553
+ return;
3554
+ const inbox = this.db.getFolders(accountId).find(f => f.specialUse === "inbox");
3555
+ if (!inbox)
3556
+ return;
3557
+ this.syncFolder(accountId, inbox.id).catch(e => console.error(` [idle] flag-change sync failed: ${e.message}`));
3558
+ }, 1500);
3559
+ };
3514
3560
  const stop = await watchClient.watchMailbox("INBOX", (newCount) => {
3515
3561
  console.log(` [idle] ${accountId}: ${newCount} new message(s)`);
3516
3562
  this.syncInboxNewOnly(accountId).catch(e => console.error(` [idle] sync error: ${e.message}`));
3517
- }, { notifySpec, onMailboxStatus, onExpunge });
3563
+ }, { notifySpec, onMailboxStatus, onExpunge, onFlagChange });
3518
3564
  this.watchers.set(accountId, async () => {
3519
3565
  await stop();
3520
3566
  await watchClient.logout();
@@ -3728,6 +3774,13 @@ export class ImapManager extends EventEmitter {
3728
3774
  // IMAP: fast lane on the ops queue. One try; if the socket is stale,
3729
3775
  // withConnection's discard-on-error logic drops the client so the
3730
3776
  // next attempt (caller-driven retry) gets a fresh one.
3777
+ //
3778
+ // An interactive fetch (`force`) jumps the lane queue and gets a
3779
+ // tighter cap: the reader is staring at a blank pane, and 90 s of
3780
+ // silence followed by a banner is the worst of both. 30 s is long
3781
+ // enough for a big body on a slow server and short enough that a
3782
+ // wedged lane becomes a RETRYABLE timeout while the reader is still
3783
+ // looking at the message.
3731
3784
  try {
3732
3785
  const raw = await this.withConnection(accountId, async (client) => {
3733
3786
  const msg = await client.fetchMessageByUid(folder.path, uid, { source: true });
@@ -3736,7 +3789,7 @@ export class ImapManager extends EventEmitter {
3736
3789
  if (!msg.source)
3737
3790
  return null;
3738
3791
  return Buffer.from(msg.source, "utf-8");
3739
- });
3792
+ }, force ? { priority: true, timeoutMs: 30_000 } : {});
3740
3793
  if (!raw)
3741
3794
  return null;
3742
3795
  const bodyPath = await this.bodyStore.putMessage(accountId, folderId, uid, raw);
@@ -3751,8 +3804,19 @@ export class ImapManager extends EventEmitter {
3751
3804
  if (e?.isNotFound)
3752
3805
  throw e;
3753
3806
  console.error(` Body fetch error (${accountId}/${uid}): ${e?.message || e}`);
3754
- // Record so the next view / prefetch backs off instead of
3755
- // re-attempting a hanging fetch and re-congesting the queue.
3807
+ // A lane timeout / dropped socket says nothing about whether this
3808
+ // message HAS a body. Swallowing it into `null` told the caller
3809
+ // "the server has no body for this" — the reconciler classifies
3810
+ // that as non-transient, skips its retry budget, and banners.
3811
+ // That is the "eventually reports an error rather than retrying"
3812
+ // Bob hit (2026-08-29). Rethrow instead, so the reconciler's
3813
+ // transient test sees the word "timeout" and retries with backoff.
3814
+ const transient = /timeout|discarding client|connection|not connected|ECONN|ETIMEDOUT|ENOTFOUND|socket/i
3815
+ .test(String(e?.message || ""));
3816
+ if (transient)
3817
+ throw e;
3818
+ // A genuine "no body here" — arm the backoff so prefetch and the
3819
+ // next view don't re-attempt a fetch the server won't satisfy.
3756
3820
  try {
3757
3821
  this.markPrefetchEmpty(accountId, folderId, uid);
3758
3822
  }