@bobfrankston/rmfmail 1.2.335 → 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.
@@ -8752,6 +8752,18 @@ function searchCommand(tag, criteria) {
8752
8752
  function storeCommand(tag, uid, action, flags) {
8753
8753
  return buildCommand(tag, `UID STORE ${uid} ${action} (${flags.join(" ")})`);
8754
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
+ }
8755
8767
  function copyCommand(tag, uid, destination) {
8756
8768
  return buildCommand(tag, `UID COPY ${uid} ${quoteMailbox(destination)}`);
8757
8769
  }
@@ -9796,6 +9808,26 @@ var NativeImapClient = class {
9796
9808
  await this.addFlags(uid, ["\\Deleted"]);
9797
9809
  await this.expunge();
9798
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
+ }
9799
9831
  /** Expunge deleted messages */
9800
9832
  async expunge() {
9801
9833
  const tag = nextTag();
@@ -10760,6 +10792,19 @@ var CompatImapClient = class {
10760
10792
  await this.native.deleteMessage(uid);
10761
10793
  await this.native.closeMailbox();
10762
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
+ }
10763
10808
  /** Move a message between mailboxes (same server) */
10764
10809
  async moveMessage(msg, fromMailbox, toMailbox) {
10765
10810
  await this.ensureConnected();