@bobfrankston/rmfmail 1.2.333 → 1.2.337

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 (49) hide show
  1. package/client/android-bootstrap.bundle.js +53 -0
  2. package/client/android-bootstrap.bundle.js.map +2 -2
  3. package/client/app.bundle.js +51 -14
  4. package/client/app.bundle.js.map +2 -2
  5. package/client/app.js +12 -6
  6. package/client/app.js.map +1 -1
  7. package/client/app.ts +12 -6
  8. package/client/components/folder-tree.js +6 -1
  9. package/client/components/folder-tree.js.map +1 -1
  10. package/client/components/folder-tree.ts +5 -1
  11. package/client/components/message-list.js +54 -11
  12. package/client/components/message-list.js.map +1 -1
  13. package/client/components/message-list.ts +47 -9
  14. package/client/components/message-viewer.js +6 -1
  15. package/client/components/message-viewer.js.map +1 -1
  16. package/client/components/message-viewer.ts +6 -1
  17. package/client/compose/compose.bundle.js +42 -5
  18. package/client/compose/compose.bundle.js.map +4 -4
  19. package/client/compose/compose.js +7 -2
  20. package/client/compose/compose.js.map +1 -1
  21. package/client/compose/compose.ts +7 -2
  22. package/client/index.html +2 -2
  23. package/client/package.json +1 -1
  24. package/package.json +9 -9
  25. package/packages/mailx-imap/index.d.ts +4 -1
  26. package/packages/mailx-imap/index.d.ts.map +1 -1
  27. package/packages/mailx-imap/index.js +5 -2
  28. package/packages/mailx-imap/index.js.map +1 -1
  29. package/packages/mailx-imap/index.ts +7 -3
  30. package/packages/mailx-imap/package-lock.json +2 -2
  31. package/packages/mailx-imap/package.json +1 -1
  32. package/packages/mailx-service/index.d.ts.map +1 -1
  33. package/packages/mailx-service/index.js +33 -3
  34. package/packages/mailx-service/index.js.map +1 -1
  35. package/packages/mailx-service/index.ts +30 -3
  36. package/packages/mailx-service/package.json +1 -1
  37. package/packages/mailx-service/sync-queue.d.ts +7 -0
  38. package/packages/mailx-service/sync-queue.d.ts.map +1 -1
  39. package/packages/mailx-service/sync-queue.js +9 -0
  40. package/packages/mailx-service/sync-queue.js.map +1 -1
  41. package/packages/mailx-service/sync-queue.ts +10 -0
  42. package/packages/mailx-settings/package.json +1 -1
  43. package/packages/mailx-store/package.json +1 -1
  44. package/packages/mailx-store-web/package.json +1 -1
  45. package/packages/mailx-types/index.d.ts.map +1 -1
  46. package/packages/mailx-types/index.js +14 -0
  47. package/packages/mailx-types/index.js.map +1 -1
  48. package/packages/mailx-types/index.ts +13 -0
  49. package/packages/mailx-types/package.json +1 -1
@@ -3383,6 +3383,14 @@ function htmlToPlainText(html) {
3383
3383
  const t = text.replace(/<[^>]+>/g, "").trim();
3384
3384
  return t && t !== href ? `${t} (${href})` : href;
3385
3385
  });
3386
+ s = s.replace(/<img\b[^>]*>/gi, (tag) => {
3387
+ const src = (tag.match(/\bsrc\s*=\s*(['"])([^'"]*)\1/i) || [])[2]?.trim() || "";
3388
+ const alt = (tag.match(/\balt\s*=\s*(['"])([^'"]*)\1/i) || [])[2]?.trim() || "";
3389
+ const remote = /^https?:\/\//i.test(src);
3390
+ if (remote)
3391
+ return alt ? `[image: ${alt}] (${src})` : `(${src})`;
3392
+ return alt ? `[image: ${alt}]` : "[image]";
3393
+ });
3386
3394
  s = s.replace(/<[^>]+>/g, "");
3387
3395
  s = s.replace(/&nbsp;/gi, " ").replace(/&amp;/gi, "&").replace(/&lt;/gi, "<").replace(/&gt;/gi, ">").replace(/&quot;/gi, '"').replace(/&#39;/gi, "'").replace(/&apos;/gi, "'").replace(/&mdash;/gi, "\u2014").replace(/&ndash;/gi, "\u2013").replace(/&hellip;/gi, "\u2026").replace(/&#(\d+);/g, (_m, n) => String.fromCodePoint(parseInt(n, 10))).replace(/&#x([0-9a-f]+);/gi, (_m, h) => String.fromCodePoint(parseInt(h, 16)));
3388
3396
  s = s.replace(/[ \t]+/g, " ").split("\n").map((l) => l.replace(/^[ \t]+|[ \t]+$/g, "")).join("\n").replace(/\n{3,}/g, "\n\n").trim();
@@ -8744,6 +8752,18 @@ function searchCommand(tag, criteria) {
8744
8752
  function storeCommand(tag, uid, action, flags) {
8745
8753
  return buildCommand(tag, `UID STORE ${uid} ${action} (${flags.join(" ")})`);
8746
8754
  }
8755
+ function uidSequenceSet(uids) {
8756
+ const sorted = Array.from(new Set(uids)).sort((a, b) => a - b);
8757
+ const parts = [];
8758
+ for (let i = 0; i < sorted.length; ) {
8759
+ let j = i;
8760
+ while (j + 1 < sorted.length && sorted[j + 1] === sorted[j] + 1)
8761
+ j++;
8762
+ parts.push(j > i ? `${sorted[i]}:${sorted[j]}` : String(sorted[i]));
8763
+ i = j + 1;
8764
+ }
8765
+ return parts.join(",");
8766
+ }
8747
8767
  function copyCommand(tag, uid, destination) {
8748
8768
  return buildCommand(tag, `UID COPY ${uid} ${quoteMailbox(destination)}`);
8749
8769
  }
@@ -9788,6 +9808,26 @@ var NativeImapClient = class {
9788
9808
  await this.addFlags(uid, ["\\Deleted"]);
9789
9809
  await this.expunge();
9790
9810
  }
9811
+ /** Delete many messages in the selected mailbox: one `UID STORE <set>
9812
+ * +FLAGS.SILENT (\Deleted)` per chunk, then a single EXPUNGE.
9813
+ * 2026-09-16 — Claude Code (Fable 5.1), at Bob's direction. Emptying
9814
+ * Trash looped deleteMessage() per UID — a STORE and an EXPUNGE round
9815
+ * trip for every message — so a large Trash took minutes and the
9816
+ * caller's IPC timed out ("mailxapi timeout: emptyFolder"). Chunked so a
9817
+ * ten-thousand-UID set never produces a command line the server rejects. */
9818
+ async deleteMessages(uids, chunkSize = 1e3) {
9819
+ if (!uids.length)
9820
+ return;
9821
+ for (let i = 0; i < uids.length; i += chunkSize) {
9822
+ const set = uidSequenceSet(uids.slice(i, i + chunkSize));
9823
+ const tag = nextTag();
9824
+ const responses = await this.sendCommand(tag, storeCommand(tag, set, "+FLAGS.SILENT", ["\\Deleted"]));
9825
+ const tagged = responses.find((r) => r.tag === tag);
9826
+ if (!tagged || tagged.type !== "OK")
9827
+ throw new Error(`STORE +FLAGS \\Deleted (${uids.length} uids) failed: ${tagged?.text || "unknown"}`);
9828
+ }
9829
+ await this.expunge();
9830
+ }
9791
9831
  /** Expunge deleted messages */
9792
9832
  async expunge() {
9793
9833
  const tag = nextTag();
@@ -10752,6 +10792,19 @@ var CompatImapClient = class {
10752
10792
  await this.native.deleteMessage(uid);
10753
10793
  await this.native.closeMailbox();
10754
10794
  }
10795
+ /** Delete many messages by UID in one mailbox — chunked STORE + one
10796
+ * EXPUNGE (see ImapNative.deleteMessages). 2026-09-16 Claude Code. */
10797
+ async deleteMessagesByUid(mailbox, uids) {
10798
+ if (!uids.length)
10799
+ return;
10800
+ await this.ensureConnected();
10801
+ await this.native.select(mailbox);
10802
+ try {
10803
+ await this.native.deleteMessages(uids);
10804
+ } finally {
10805
+ await this.native.closeMailbox();
10806
+ }
10807
+ }
10755
10808
  /** Move a message between mailboxes (same server) */
10756
10809
  async moveMessage(msg, fromMailbox, toMailbox) {
10757
10810
  await this.ensureConnected();