@bobfrankston/rmfmail 1.2.321 → 1.2.323

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 (60) hide show
  1. package/.commitmsg +16 -9
  2. package/.llm/trusted-lists.md +3 -0
  3. package/client/android-bootstrap.bundle.js +35 -9
  4. package/client/android-bootstrap.bundle.js.map +2 -2
  5. package/client/app.bundle.js +33 -3
  6. package/client/app.bundle.js.map +2 -2
  7. package/client/components/calendar-sidebar.js +14 -2
  8. package/client/components/calendar-sidebar.js.map +1 -1
  9. package/client/components/calendar-sidebar.ts +17 -2
  10. package/client/components/message-viewer.js +33 -0
  11. package/client/components/message-viewer.js.map +1 -1
  12. package/client/components/message-viewer.ts +32 -1
  13. package/client/compose/compose.bundle.js +1 -1
  14. package/client/compose/compose.bundle.js.map +2 -2
  15. package/client/lib/api-client.js +1 -1
  16. package/client/lib/api-client.js.map +1 -1
  17. package/client/lib/api-client.ts +3 -3
  18. package/docs/allowlist.md +15 -1
  19. package/npmchanges.md +43 -0
  20. package/package.json +7 -7
  21. package/packages/mailx-imap/package-lock.json +2 -2
  22. package/packages/mailx-imap/package.json +1 -1
  23. package/packages/mailx-service/index.d.ts +1 -0
  24. package/packages/mailx-service/index.d.ts.map +1 -1
  25. package/packages/mailx-service/index.js +9 -2
  26. package/packages/mailx-service/index.js.map +1 -1
  27. package/packages/mailx-service/index.ts +10 -3
  28. package/packages/mailx-service/package.json +1 -1
  29. package/packages/mailx-settings/docs/allowlist.md +15 -1
  30. package/packages/mailx-settings/index.d.ts +1 -0
  31. package/packages/mailx-settings/index.d.ts.map +1 -1
  32. package/packages/mailx-settings/index.js +4 -0
  33. package/packages/mailx-settings/index.js.map +1 -1
  34. package/packages/mailx-settings/index.ts +4 -0
  35. package/packages/mailx-settings/package.json +1 -1
  36. package/packages/mailx-store/package.json +1 -1
  37. package/packages/mailx-store/store.d.ts.map +1 -1
  38. package/packages/mailx-store/store.js +2 -0
  39. package/packages/mailx-store/store.js.map +1 -1
  40. package/packages/mailx-store/store.ts +2 -0
  41. package/packages/mailx-store-web/package.json +1 -1
  42. package/packages/mailx-store-web/web-service.d.ts +1 -0
  43. package/packages/mailx-store-web/web-service.d.ts.map +1 -1
  44. package/packages/mailx-store-web/web-service.js +1 -0
  45. package/packages/mailx-store-web/web-service.js.map +1 -1
  46. package/packages/mailx-store-web/web-service.ts +2 -1
  47. package/packages/mailx-store-web/web-settings.d.ts +1 -0
  48. package/packages/mailx-store-web/web-settings.d.ts.map +1 -1
  49. package/packages/mailx-store-web/web-settings.js +1 -0
  50. package/packages/mailx-store-web/web-settings.js.map +1 -1
  51. package/packages/mailx-store-web/web-settings.ts +1 -0
  52. package/packages/mailx-types/mailx-api.d.ts +1 -0
  53. package/packages/mailx-types/mailx-api.d.ts.map +1 -1
  54. package/packages/mailx-types/mailx-api.ts +1 -1
  55. package/packages/mailx-types/package.json +1 -1
  56. package/packages/mailx-types/trust.d.ts +18 -0
  57. package/packages/mailx-types/trust.d.ts.map +1 -1
  58. package/packages/mailx-types/trust.js +42 -4
  59. package/packages/mailx-types/trust.js.map +1 -1
  60. package/packages/mailx-types/trust.ts +60 -4
package/.commitmsg CHANGED
@@ -1,10 +1,17 @@
1
- Compose: a thin 3 cm rule above the signature instead of "-- "
1
+ New event: the calendar picker is always there, and lists every calendar you can write to
2
2
 
3
- Bob 2026-09-10: "you seem to be putting a -- above the signature. If I
4
- want it it should be part of my HTML. If you do it it should be a line
5
- rather than -- and maybe three cm or an inch." The signature block in
6
- compose.ts hard-coded the "-- " delimiter above acct.sig / acct.signature.
7
- It is now a left-aligned <hr> 3 cm wide, 1 px, grey, inline-styled since
8
- no stylesheet travels with mail. Anything else belongs in the signature
9
- HTML itself. Trade-off noted to Bob: other clients use "-- " to trim a
10
- quoted signature; without it some will quote it back.
3
+ Bob 2026-09-11: "the add appointment box should give me a choice of
4
+ calendars." v1.2.318 hid the picker whenever Google reported fewer than
5
+ two writable calendars and his four are one owned calendar plus two
6
+ holiday feeds and a shared one, so the row never appeared and read as a
7
+ missing feature.
8
+
9
+ The row is now always shown. With one writable calendar the dropdown is
10
+ disabled and its tooltip says that this is the only calendar Google lets
11
+ you add events to, that the others are read-only, and where to change
12
+ that (Google Calendar, then Refresh). getCalendars returns EVERY
13
+ calendar with `selected` as a flag instead of a filter: the sidebar
14
+ still lists the selected ones, but a calendar the reader owns and has
15
+ unticked in Google is still one a new event can go to. The daemon logs
16
+ each calendar's role and selection at enumeration so "why only one" can
17
+ be answered from the log. mailx-types 0.1.98, mailx-service 0.1.39.
@@ -66,3 +66,6 @@ tests/trust.test.ts, .commitmsg, TODO.md C165, root version 1.2.311. Then rebuil
66
66
  - v1.2.319: TinyMCE smart-paste left the caret INSIDE the pasted <a>; stepCaretOutOfPastedLink in client/compose/editor.ts moves it after the anchor one tick after paste. Quill path has the same shape (insertText link + setSelection) — untouched, Bob uses TinyMCE.
67
67
  - v1.2.320: Quill counterpart — placeCaretAfterLink(index) = setSelection + format("link", false) at 5 paste sites + 2 Edit-link dialog sites. Untested; Bob will switch editor to test.
68
68
  - v1.2.321: signature block uses a 3cm <hr> instead of '-- ' (compose.ts sigBlock).
69
+ - Bob confirmed 2026-09-10: 'quill worked' (v1.2.320 placeCaretAfterLink).
70
+ - v1.2.322: trustedSendersVia ('sender via relay' pairs) — Ground News via amazonses.com. Banner offers 'Trust ‹sender› via ‹relay›' on the trusted-but-unproved caution; counts only when the relay DKIM-signed. 45/45 trust tests.
71
+ - v1.2.323: New event picker always shown (disabled + explanatory tooltip when only one writable calendar); getCalendars returns all calendars with selected flag; daemon logs roles.
@@ -2297,6 +2297,23 @@ function provedIntermediary(input) {
2297
2297
  return entry;
2298
2298
  return "";
2299
2299
  }
2300
+ function parseSenderVia(entry) {
2301
+ const m = (entry || "").trim().toLowerCase().match(/^(\S+)\s+via\s+(\S+)$/);
2302
+ return m ? { domain: m[1], signer: m[2] } : null;
2303
+ }
2304
+ function provedSenderVia(input) {
2305
+ const entries = (input.trustedSendersVia || []).map(parseSenderVia).filter(Boolean);
2306
+ if (!entries.length)
2307
+ return "";
2308
+ const fromDomain = (bare(input.fromAddress).split("@")[1] || "").toLowerCase();
2309
+ if (!fromDomain)
2310
+ return "";
2311
+ const signers = dkimSigners(input);
2312
+ for (const e of entries)
2313
+ if (sameOrg(fromDomain, e.domain) && signers.some((s) => sameOrg(s, e.signer)))
2314
+ return `${e.domain} via ${e.signer}`;
2315
+ return "";
2316
+ }
2300
2317
  function listProof(input) {
2301
2318
  const none = { id: "", proved: false, host: "" };
2302
2319
  const raw = header(input.headerLines, "list-id");
@@ -2420,7 +2437,8 @@ function analyzeServerSpam(input) {
2420
2437
  reasons,
2421
2438
  intermediary: provedIntermediary(input),
2422
2439
  signers: dkimSigners(input),
2423
- list
2440
+ list,
2441
+ senderVia: provedSenderVia(input)
2424
2442
  };
2425
2443
  }
2426
2444
  function provedNote(a) {
@@ -2439,7 +2457,7 @@ function serverSpamVerdict(input) {
2439
2457
  const a = analyzeServerSpam(input);
2440
2458
  if (!a || !a.flagged)
2441
2459
  return null;
2442
- const trustedAndProved = input.senderTrusted && a.proved || !!a.intermediary || a.list.trusted;
2460
+ const trustedAndProved = input.senderTrusted && a.proved || !!a.intermediary || a.list.trusted || !!a.senderVia;
2443
2461
  if (trustedAndProved && a.kind !== "forgery" && !a.authFailures.length)
2444
2462
  return null;
2445
2463
  const senderDomain = (bare(header(input.headerLines, "sender")).split("@")[1] || "").toLowerCase();
@@ -2473,14 +2491,19 @@ function serverSpamVerdict(input) {
2473
2491
  detail: `${numbers}${why}${bayes}`
2474
2492
  };
2475
2493
  const proof = a.proved ? `${provedNote(a)} ` : "";
2476
- if (input.senderTrusted && !a.proved)
2494
+ if (input.senderTrusted && !a.proved) {
2495
+ const fromDomain = (bare(input.fromAddress).split("@")[1] || "").toLowerCase();
2496
+ const relaySigner = a.signers.find((s) => !sameOrg(s, fromDomain)) || "";
2497
+ const senderViaNote = relaySigner ? `. ${relaySigner} signed this message on the sender's behalf; "Trust ${fromDomain} via ${relaySigner}" stops this note for mail from ${fromDomain} that ${relaySigner} signs.` : "";
2477
2498
  return {
2478
2499
  id: "server-spam-verdict",
2479
2500
  severity: "caution",
2480
2501
  text: "This claims to be a sender you trust, but nothing proves it is.",
2481
- detail: `No DMARC pass, no valid signature from the sending domain, and it passed through hosts your server does not trust. ${numbers}${why}${listNote}`,
2482
- ...viaList
2502
+ detail: `No DMARC pass, no valid signature from the sending domain, and it passed through hosts your server does not trust. ${numbers}${why}${listNote}${senderViaNote}`,
2503
+ ...viaList,
2504
+ ...relaySigner ? { senderVia: `${fromDomain} via ${relaySigner}` } : {}
2483
2505
  };
2506
+ }
2484
2507
  return {
2485
2508
  id: "server-spam-verdict",
2486
2509
  severity: "caution",
@@ -2664,7 +2687,7 @@ function spamScoreOf(input) {
2664
2687
  proved: a.proved,
2665
2688
  provedBy: a.provedBy,
2666
2689
  bulkOnly: a.bulkOnly,
2667
- trusted: (!!input.senderTrusted && a.proved || !!a.intermediary || a.list.trusted) && a.kind !== "forgery" && !a.authFailures.length,
2690
+ trusted: (!!input.senderTrusted && a.proved || !!a.intermediary || a.list.trusted || !!a.senderVia) && a.kind !== "forgery" && !a.authFailures.length,
2668
2691
  reasons: a.reasons,
2669
2692
  listId: a.list.id,
2670
2693
  listProved: a.list.proved,
@@ -2679,7 +2702,8 @@ var init_trust = __esm({
2679
2702
  sender: "trustedSenders",
2680
2703
  domain: "trustedDomains",
2681
2704
  intermediary: "trustedIntermediaries",
2682
- list: "trustedLists"
2705
+ list: "trustedLists",
2706
+ via: "trustedSendersVia"
2683
2707
  };
2684
2708
  FORGERY_RULES = [
2685
2709
  /^SPF_(HELO_)?(FAIL|SOFTFAIL)$/,
@@ -4291,7 +4315,8 @@ var init_web_settings = __esm({
4291
4315
  trustedSenders: [],
4292
4316
  trustedDomains: [],
4293
4317
  // Mailing lists by List-Id — mirrors mailx-settings DEFAULT_ALLOWLIST (2026-09-09).
4294
- trustedLists: []
4318
+ trustedLists: [],
4319
+ trustedSendersVia: []
4295
4320
  };
4296
4321
  PREV_KEEP = 5;
4297
4322
  SHARED_REFRESH_MS = 5 * 6e4;
@@ -7256,7 +7281,8 @@ var WebMailxService = class _WebMailxService {
7256
7281
  trustedSenders: list.trustedSenders || [],
7257
7282
  trustedDomains: list.trustedDomains || [],
7258
7283
  trustedIntermediaries: list.trustedIntermediaries || [],
7259
- trustedLists: list.trustedLists || []
7284
+ trustedLists: list.trustedLists || [],
7285
+ trustedSendersVia: list.trustedSendersVia || []
7260
7286
  };
7261
7287
  }
7262
7288
  async allowRemoteContent(type, value) {