@bobfrankston/rmfmail 1.0.594 → 1.0.598

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.
@@ -607,35 +607,74 @@ function parseAddrs(s: string): { name: string; address: string }[] {
607
607
  * contacts.jsonc → groups map. Recipients that match a group name (case
608
608
  * insensitive) get replaced by their member list, recursively. Unresolved
609
609
  * tokens are left in place so the user sees them and can fix the typo.
610
- * Loaded once per send via `getContactsConfig`; cached for the session. */
611
- let _groupsCache: Record<string, string[]> | null = null;
612
- async function loadGroupsMap(): Promise<Record<string, string[]>> {
613
- if (_groupsCache) return _groupsCache;
610
+ * Loaded ASYNCHRONOUSLY at compose-init time Send must NEVER await
611
+ * this. Earlier `await loadGroupsMap()` inside the click handler hung
612
+ * Send for 61 seconds (Bob 2026-05-09 00:16:57): the GDrive read of
613
+ * contacts.jsonc was on a slow connection. Bob then clicked Send a
614
+ * second time at 00:23, producing two real outgoing messages with
615
+ * different Message-IDs because each Send call assigned its own. Send
616
+ * must be instantaneous; group expansion must not gate it.
617
+ *
618
+ * localStorage is the synchronous tier — populated by the background
619
+ * refresh, read instantly by `expandGroups`. If localStorage has
620
+ * nothing yet (first ever launch on this device), expandGroups is a
621
+ * no-op and the user's literal recipient string flows through. The
622
+ * background refresh seeds localStorage on first success. */
623
+ const GROUPS_LS_KEY = "mailx-groups-cache-v1";
624
+ let _groupsCache: Record<string, string[]> = readGroupsFromLocalStorage();
625
+
626
+ function readGroupsFromLocalStorage(): Record<string, string[]> {
614
627
  try {
615
- const { readJsoncFile } = await import("../lib/api-client.js");
616
- const r = await readJsoncFile("contacts.jsonc");
617
- if (!r?.content) { _groupsCache = {}; return _groupsCache; }
618
- // Use a loose JSONC parse: strip // comments + trailing commas.
619
- const stripped = r.content.replace(/^\s*\/\/.*$/gm, "").replace(/,(\s*[}\]])/g, "$1");
620
- const cfg = JSON.parse(stripped);
621
- _groupsCache = (cfg && typeof cfg.groups === "object" && cfg.groups) ? cfg.groups : {};
622
- return _groupsCache;
623
- } catch {
624
- _groupsCache = {};
625
- return _groupsCache;
626
- }
628
+ const raw = localStorage.getItem(GROUPS_LS_KEY);
629
+ if (raw) return JSON.parse(raw) || {};
630
+ } catch { /* */ }
631
+ return {};
632
+ }
633
+
634
+ function writeGroupsToLocalStorage(groups: Record<string, string[]>): void {
635
+ try { localStorage.setItem(GROUPS_LS_KEY, JSON.stringify(groups)); }
636
+ catch { /* localStorage full or private mode */ }
637
+ }
638
+
639
+ /** Background refresh of the groups map. Fires once at compose init,
640
+ * results land in `_groupsCache` and localStorage for next time. */
641
+ function refreshGroupsMapInBackground(): void {
642
+ (async () => {
643
+ try {
644
+ const { readJsoncFile } = await import("../lib/api-client.js");
645
+ const r = await readJsoncFile("contacts.jsonc");
646
+ if (!r?.content) return;
647
+ const stripped = r.content.replace(/^\s*\/\/.*$/gm, "").replace(/,(\s*[}\]])/g, "$1");
648
+ const cfg = JSON.parse(stripped);
649
+ const groups = (cfg && typeof cfg.groups === "object" && cfg.groups) ? cfg.groups : {};
650
+ _groupsCache = groups;
651
+ writeGroupsToLocalStorage(groups);
652
+ } catch { /* leave existing cache in place */ }
653
+ })();
627
654
  }
628
- /** Expand the raw recipient string against the loaded groups map. */
629
- async function expandGroups(raw: string): Promise<string> {
655
+ // Kick off the background refresh once when this module loads.
656
+ refreshGroupsMapInBackground();
657
+
658
+ /** Expand the raw recipient string against the cached groups map.
659
+ * SYNCHRONOUS by design — Send must not wait on cloud I/O for group
660
+ * expansion. If no groups are cached, the input passes through. */
661
+ function expandGroups(raw: string): string {
630
662
  if (!raw.trim()) return raw;
631
- const groups = await loadGroupsMap();
632
- if (Object.keys(groups).length === 0) return raw;
633
- const { expandRecipients } = await import("@bobfrankston/mailx-types");
634
- const r = expandRecipients(raw, groups);
635
- if (r.unresolved.length > 0) {
636
- console.warn(`[groups] unresolved recipients: ${r.unresolved.join(", ")}`);
663
+ if (Object.keys(_groupsCache).length === 0) return raw;
664
+ // Lazy-load the expansion utility synchronously isn't possible
665
+ // since it's a separate package — fall back to inline expansion.
666
+ // Same algorithm as `expandRecipients`: split on comma, look up
667
+ // each token (case-insensitive), keep the original on miss.
668
+ const groupsLc: Record<string, string[]> = {};
669
+ for (const k of Object.keys(_groupsCache)) groupsLc[k.toLowerCase()] = _groupsCache[k];
670
+ const tokens = raw.split(",").map(s => s.trim()).filter(Boolean);
671
+ const out: string[] = [];
672
+ for (const tok of tokens) {
673
+ const members = groupsLc[tok.toLowerCase()];
674
+ if (members && Array.isArray(members)) out.push(...members);
675
+ else out.push(tok);
637
676
  }
638
- return r.addresses.join(", ");
677
+ return out.join(", ");
639
678
  }
640
679
 
641
680
  function applyInit(init: ComposeInit): void {
@@ -940,9 +979,14 @@ document.getElementById("btn-send")?.addEventListener("click", async () => {
940
979
  // Group expansion — replace any group names (family, neighbors, etc.)
941
980
  // with their address lists from contacts.jsonc → groups before parsing
942
981
  // into the validated {name, address}[] shape the service expects.
943
- const toExpanded = await expandGroups(toInput.value);
944
- const ccExpanded = await expandGroups(ccInput.value);
945
- const bccExpanded = await expandGroups(bccInput.value);
982
+ // Synchronous group expansion — reads in-memory + localStorage cache
983
+ // ONLY. NEVER awaits cloud I/O. This used to be `await expandGroups`
984
+ // which fired a GDrive read of contacts.jsonc and hung Send for 61 s
985
+ // on a slow network (Bob 2026-05-09 00:16:57); the user clicked
986
+ // Send again, producing a real duplicate message.
987
+ const toExpanded = expandGroups(toInput.value);
988
+ const ccExpanded = expandGroups(ccInput.value);
989
+ const bccExpanded = expandGroups(bccInput.value);
946
990
  const body = {
947
991
  from: getFromAccountId(),
948
992
  fromAddress: getFromAddress(),
@@ -963,85 +1007,105 @@ document.getElementById("btn-send")?.addEventListener("click", async () => {
963
1007
  alert("Please add at least one To recipient.");
964
1008
  return;
965
1009
  }
1010
+ // Local-first send: validate fast in the client, then fire-and-forget
1011
+ // the IPC and close compose IMMEDIATELY. The body is already snapshotted
1012
+ // into `body` above; nothing the user types after this point can affect
1013
+ // what gets sent.
1014
+ //
1015
+ // Earlier "wait for IPC ack before closing" version produced a real,
1016
+ // user-reported bug: clicking Send → typing for a few hundred ms while
1017
+ // the IPC was in flight → IPC returns → compose closes mid-keystroke
1018
+ // and the user's last edits go nowhere. The fix is structural: send
1019
+ // is committed by the client validation + the snapshot, NOT by the
1020
+ // server's reply. The server-side write is synchronous-on-disk inside
1021
+ // service.send() (queueOutgoingLocal), and any failure surfaces as a
1022
+ // top-level banner via the parent's `mailx-send-error` postMessage.
1023
+ //
1024
+ // Client-side regex validation up front so a typo'd address bounces
1025
+ // back inline (compose stays open) instead of disappearing into a
1026
+ // toast after compose has closed. Same pattern Outlook/Thunderbird use.
1027
+ const emailRe = /^[^\s<>@]+@[^\s<>@]+\.[^\s<>@]+$/;
1028
+ const badAddress = (list: { address?: string }[] | undefined): string | null => {
1029
+ if (!list) return null;
1030
+ for (const a of list) {
1031
+ const addr = (a?.address || "").trim();
1032
+ if (!addr) continue; // empty fragments are dropped
1033
+ if (!emailRe.test(addr)) return addr;
1034
+ }
1035
+ return null;
1036
+ };
1037
+ const bad = badAddress(body.to) || badAddress(body.cc) || badAddress(body.bcc);
1038
+ if (bad) {
1039
+ logClientEvent("compose-send-rejected-bad-addr", { addr: bad });
1040
+ const statusEl = document.getElementById("compose-status");
1041
+ if (statusEl) statusEl.textContent = `Invalid address: "${bad}"`;
1042
+ else alert(`Invalid address: "${bad}"`);
1043
+ return;
1044
+ }
966
1045
  console.log(`[compose] Send clicked: from=${body.from} to=${JSON.stringify(body.to)} subject="${body.subject}" attachments=${body.attachments.length}`);
967
- // Wait for the IPC round-trip before closing compose. The IPC is supposed
968
- // to be <100ms (Node validates + disk-writes synchronously inside send()
969
- // then returns). If it throws OR takes too long, the user keeps their
970
- // typed message and sees the error inline instead of losing it to a
971
- // fire-and-forget that never landed. Earlier fire-and-forget version lost
972
- // messages silently when anything upstream of disk write broke.
973
- const sendBtn = document.getElementById("btn-send") as HTMLButtonElement | null;
974
- if (sendBtn) { sendBtn.disabled = true; sendBtn.textContent = "Sending…"; }
975
- const statusEl = document.getElementById("compose-status");
976
- if (statusEl) statusEl.textContent = "";
1046
+
1047
+ // Stop autosave NOW the body we're sending is the body we're sending,
1048
+ // and we don't want a stray autosave to write a stale "still typing"
1049
+ // copy back to the Drafts folder while SMTP is in flight.
1050
+ if (draftTimer) { clearInterval(draftTimer); draftTimer = null; }
1051
+ // Record From-address history before close. Only manual values worth
1052
+ // keeping skip anything that exactly matches a known account.
1053
+ try {
1054
+ const raw = fromInput.value.trim();
1055
+ const known = knownAccounts.some(a => formatAccountFrom(a) === raw);
1056
+ if (raw && !known && /@.+\./.test(raw)) recordFromHistory(raw);
1057
+ } catch { /* */ }
1058
+ if (draftUid || draftId) {
1059
+ deleteDraft(getFromAccountId(), draftUid || 0, draftId || "").catch(() => {});
1060
+ }
1061
+
977
1062
  const sendStart = Date.now();
978
1063
  logClientEvent("compose-send-pre-ipc");
979
- // Parent-window relay for send. Empirical observation: Android (direct
980
- // in-process SMTP) sends reliably; desktop (iframe parent.mailxapi
981
- // msger Node service) has sendMessage IPCs failing to reach Node
982
- // for reasons still unknown (iframe bridge behaves differently from the
983
- // top frame in msger's WebView2 for this specific call). Meanwhile the
984
- // parent window's bridge is proven — getAccounts / getOutboxStatus run
985
- // through it every few seconds with no failures.
986
- //
987
- // Fix: the iframe doesn't touch the bridge at all for send. It posts
988
- // a request to the parent, and the parent calls the real sendMessage
989
- // from its own frame. Parent posts the result back. This bypasses
990
- // whatever is wrong with iframe-scoped IPC.
991
- const ipcPromise = new Promise<void>((resolve, reject) => {
1064
+ // Fire the parent-relay IPC and don't await it. Parent will postMessage
1065
+ // a `mailx-send-error` to the parent window on failure; the app handles
1066
+ // that with a top-level banner. On success the outbox-status pill picks
1067
+ // up the queued message via the daemon's outboxStatus event.
1068
+ try {
992
1069
  const reqId = `send-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
993
- const timer = setTimeout(() => {
994
- window.removeEventListener("message", onMsg);
995
- reject(new Error("parent-relay send timeout (120s)"));
996
- }, 120000);
1070
+ // Result listener: log only. Compose is already closed by the time
1071
+ // any of these fire.
997
1072
  const onMsg = (ev: MessageEvent) => {
998
1073
  if (!ev.data || ev.data.type !== "mailx-compose-send-result" || ev.data.id !== reqId) return;
999
- clearTimeout(timer);
1000
1074
  window.removeEventListener("message", onMsg);
1001
- if (ev.data.ok) resolve();
1002
- else reject(new Error(ev.data.error || "unknown"));
1075
+ if (ev.data.ok) {
1076
+ logClientEvent("compose-send-ipc-resolved", { ms: Date.now() - sendStart });
1077
+ } else {
1078
+ const msg = ev.data.error || "unknown";
1079
+ logClientEvent("compose-send-ipc-rejected", { error: msg, ms: Date.now() - sendStart });
1080
+ // Bubble the error up so the parent can show a banner. The
1081
+ // dropped-into-outbox path (queueOutgoingLocal) catches most
1082
+ // failures locally, so this branch fires only when the
1083
+ // *queue write itself* failed — rare, but the user must see
1084
+ // it because the message would otherwise be lost silently.
1085
+ try { parent.postMessage({ type: "mailx-send-error", message: msg, accountId: body.from }, "*"); } catch { /* */ }
1086
+ }
1003
1087
  };
1004
1088
  window.addEventListener("message", onMsg);
1005
- try {
1006
- parent.postMessage({ type: "mailx-compose-send", id: reqId, body }, "*");
1007
- logClientEvent("compose-send-ipc-invoked", { via: "parent-relay", reqId });
1008
- } catch (e: any) {
1009
- clearTimeout(timer);
1010
- window.removeEventListener("message", onMsg);
1011
- reject(e);
1012
- }
1013
- });
1014
- Promise.resolve(ipcPromise)
1015
- .then(() => {
1016
- logClientEvent("compose-send-ipc-resolved", { ms: Date.now() - sendStart });
1017
- console.log(`[compose] Send IPC returned OK in ${Date.now() - sendStart}ms`);
1018
- // Record From-address history on successful send. Only manual
1019
- // values worth keeping — skip anything that exactly matches a
1020
- // known account (already in the dropdown), and skip obviously
1021
- // invalid inputs. Populated dropdown surfaces this next time.
1022
- try {
1023
- const raw = fromInput.value.trim();
1024
- const known = knownAccounts.some(a => formatAccountFrom(a) === raw);
1025
- if (raw && !known && /@.+\./.test(raw)) recordFromHistory(raw);
1026
- } catch { /* */ }
1027
- // Stop autosave only after ACK — if send threw we want the draft
1028
- // autosave to keep the message safe.
1029
- if (draftTimer) { clearInterval(draftTimer); draftTimer = null; }
1030
- if (draftUid || draftId) {
1031
- deleteDraft(getFromAccountId(), draftUid || 0, draftId || "").catch(() => {});
1032
- }
1033
- closeCompose();
1034
- })
1035
- .catch((e: any) => {
1036
- const msg: string = e?.message || String(e);
1037
- logClientEvent("compose-send-ipc-rejected", { error: msg, ms: Date.now() - sendStart });
1038
- console.error(`[compose] Send IPC failed after ${Date.now() - sendStart}ms: ${msg}`);
1039
- if (sendBtn) { sendBtn.disabled = false; sendBtn.textContent = "Send"; }
1040
- if (statusEl) statusEl.textContent = `Send failed: ${msg}`;
1041
- try {
1042
- parent.postMessage({ type: "mailx-send-error", message: msg, accountId: body.from }, "*");
1043
- } catch { /* */ }
1044
- });
1089
+ // Safety: if parent never replies (msger pipe broken), prune the
1090
+ // listener after 120s so we don't leak it. No retry here — the
1091
+ // daemon's outbox worker is the retry path.
1092
+ setTimeout(() => window.removeEventListener("message", onMsg), 120000);
1093
+ parent.postMessage({ type: "mailx-compose-send", id: reqId, body }, "*");
1094
+ logClientEvent("compose-send-ipc-invoked", { via: "parent-relay", reqId });
1095
+ } catch (e: any) {
1096
+ // postMessage itself threw — bridge totally dead. This is the only
1097
+ // path where we keep compose open, since we couldn't even hand the
1098
+ // body off.
1099
+ const msg: string = e?.message || String(e);
1100
+ logClientEvent("compose-send-ipc-throw", { error: msg });
1101
+ const sendBtn = document.getElementById("btn-send") as HTMLButtonElement | null;
1102
+ if (sendBtn) { sendBtn.disabled = false; sendBtn.textContent = "Send"; }
1103
+ const statusEl = document.getElementById("compose-status");
1104
+ if (statusEl) statusEl.textContent = `Bridge error: ${msg}`;
1105
+ return;
1106
+ }
1107
+
1108
+ closeCompose();
1045
1109
  });
1046
1110
 
1047
1111
  // ── Close handling ──
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/rmfmail",
3
- "version": "1.0.594",
3
+ "version": "1.0.598",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
@@ -50,7 +50,7 @@
50
50
  "@bobfrankston/node-tcp-transport": "^0.1.8",
51
51
  "@bobfrankston/smtp-direct": "^0.1.8",
52
52
  "@bobfrankston/mailx-sync": "^0.1.16",
53
- "@bobfrankston/mailx-imap": "^0.1.30",
53
+ "@bobfrankston/mailx-imap": "^0.1.32",
54
54
  "html-to-docx": "^1.8.0",
55
55
  "mammoth": "^1.12.0"
56
56
  },
@@ -118,7 +118,7 @@
118
118
  "@bobfrankston/node-tcp-transport": "^0.1.8",
119
119
  "@bobfrankston/smtp-direct": "^0.1.8",
120
120
  "@bobfrankston/mailx-sync": "^0.1.16",
121
- "@bobfrankston/mailx-imap": "^0.1.30",
121
+ "@bobfrankston/mailx-imap": "^0.1.32",
122
122
  "html-to-docx": "^1.8.0",
123
123
  "mammoth": "^1.12.0"
124
124
  }
@@ -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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"}
@@ -3368,7 +3368,12 @@ export class ImapManager extends EventEmitter {
3368
3368
  // this exact case: `.sending-rmf39-63196` sat in the queue
3369
3369
  // for 7+ hours because PID 63196 was now an unrelated Node.
3370
3370
  // (c) it's our PID — never sweep our own claim.
3371
- const STALE_CLAIM_MS = 3600_000;
3371
+ // 5 minutes: SMTP transactions complete in seconds; 5m of
3372
+ // claim with no progress means the worker is wedged or PID
3373
+ // got recycled. Earlier 1h was a band-aid that left Bob's
3374
+ // outbox stuck for hours when an SMTP wedge crashed the
3375
+ // worker mid-flight.
3376
+ const STALE_CLAIM_MS = 5 * 60_000;
3372
3377
  const myPid = process.pid;
3373
3378
  for (const dir of [outboxDir, queuedDir]) {
3374
3379
  if (!fs.existsSync(dir))
@@ -3470,11 +3475,23 @@ export class ImapManager extends EventEmitter {
3470
3475
  // file is visible to the scan loop again.
3471
3476
  const nextAt = new Date(nowMs + OUTBOX_RETRY_DELAY_MS).toISOString();
3472
3477
  const withDelay = insertHeaderBeforeBody(raw, `X-Mailx-Retry-After: ${nextAt}`);
3473
- fs.writeFileSync(claimedPath, withDelay, "utf-8");
3478
+ try {
3479
+ fs.writeFileSync(claimedPath, withDelay, "utf-8");
3480
+ }
3481
+ catch (we) {
3482
+ console.error(` [outbox] FAIL writeBack ${claimedPath}: ${we?.message || we}`);
3483
+ }
3474
3484
  try {
3475
3485
  fs.renameSync(claimedPath, filePath);
3476
3486
  }
3477
- catch { /* file stays claimed; recovery sweeper will handle */ }
3487
+ catch (re) {
3488
+ // Loud — the file is now stuck in `.sending-` state
3489
+ // until the recovery sweeper's stale-claim timer
3490
+ // (5 min) reclaims it. User-visible as "stuck" in
3491
+ // the outbox view; cancelable via the new always-
3492
+ // allowed Cancel button.
3493
+ console.error(` [outbox] FAIL renameBack ${claimedPath} → ${filePath}: ${re?.message || re} — claim will sit until stale-recovery (5 min)`);
3494
+ }
3478
3495
  console.error(` [outbox] Send failed for ${file} (attempt ${attempt}, retry after ${nextAt}): ${e.message}`);
3479
3496
  }
3480
3497
  }