@bobfrankston/iflow-direct 0.1.67 → 0.1.69
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.
- package/imap-compat.d.ts +7 -0
- package/imap-compat.js +6 -0
- package/imap-native.d.ts +18 -1
- package/imap-native.js +44 -2
- package/imap-protocol.d.ts +3 -0
- package/imap-protocol.js +5 -0
- package/package.json +1 -1
package/imap-compat.d.ts
CHANGED
|
@@ -65,6 +65,13 @@ export declare class CompatImapClient {
|
|
|
65
65
|
}): Promise<FetchedMessage | null>;
|
|
66
66
|
/** Get message count via STATUS (does not require SELECT) */
|
|
67
67
|
getMessagesCount(mailbox: string): Promise<number>;
|
|
68
|
+
/** Mailbox size in octets + message count. STATUS=SIZE when the server has it, else a
|
|
69
|
+
* size-only UID FETCH. See NativeImapClient.getFolderSize. (2026-09-16, Claude Code) */
|
|
70
|
+
getFolderSize(mailbox: string): Promise<{
|
|
71
|
+
messages: number;
|
|
72
|
+
bytes: number;
|
|
73
|
+
method: "status" | "fetch";
|
|
74
|
+
}>;
|
|
68
75
|
/** Get all UIDs in a mailbox */
|
|
69
76
|
getUids(mailbox: string): Promise<number[]>;
|
|
70
77
|
/** Get UIDs whose INTERNALDATE is on/after `since`. Bounded version of
|
package/imap-compat.js
CHANGED
|
@@ -160,6 +160,12 @@ export class CompatImapClient {
|
|
|
160
160
|
await this.ensureConnected();
|
|
161
161
|
return this.native.getMessageCount(mailbox);
|
|
162
162
|
}
|
|
163
|
+
/** Mailbox size in octets + message count. STATUS=SIZE when the server has it, else a
|
|
164
|
+
* size-only UID FETCH. See NativeImapClient.getFolderSize. (2026-09-16, Claude Code) */
|
|
165
|
+
async getFolderSize(mailbox) {
|
|
166
|
+
await this.ensureConnected();
|
|
167
|
+
return this.native.getFolderSize(mailbox);
|
|
168
|
+
}
|
|
163
169
|
/** Get all UIDs in a mailbox */
|
|
164
170
|
async getUids(mailbox) {
|
|
165
171
|
await this.ensureConnected();
|
package/imap-native.d.ts
CHANGED
|
@@ -192,7 +192,24 @@ export declare class NativeImapClient {
|
|
|
192
192
|
/** Close the currently selected mailbox */
|
|
193
193
|
closeMailbox(): Promise<void>;
|
|
194
194
|
listFolders(): Promise<NativeFolder[]>;
|
|
195
|
-
getStatus(mailbox: string): Promise<proto.StatusData>;
|
|
195
|
+
getStatus(mailbox: string, items?: string[]): Promise<proto.StatusData>;
|
|
196
|
+
/**
|
|
197
|
+
* Total size of a mailbox in octets plus its message count (for imail -sizes; added
|
|
198
|
+
* 2026-09-16 by Claude Code, Fable 5.1, at Bob's direction).
|
|
199
|
+
*
|
|
200
|
+
* Fast path: RFC 8438 `STATUS (MESSAGES SIZE)` — one round trip, no message traffic —
|
|
201
|
+
* when the server advertises STATUS=SIZE (Dovecot, Gmail do).
|
|
202
|
+
* Fallback: EXAMINE (read-only) + `UID FETCH 1:* (UID RFC822.SIZE)` summed here. That
|
|
203
|
+
* is one FETCH line per message but no envelopes or headers, so it stays cheap even
|
|
204
|
+
* on a folder of tens of thousands of messages.
|
|
205
|
+
*
|
|
206
|
+
* `method` says which path produced the number so a log can show it.
|
|
207
|
+
*/
|
|
208
|
+
getFolderSize(mailbox: string): Promise<{
|
|
209
|
+
messages: number;
|
|
210
|
+
bytes: number;
|
|
211
|
+
method: "status" | "fetch";
|
|
212
|
+
}>;
|
|
196
213
|
createMailbox(mailbox: string): Promise<void>;
|
|
197
214
|
deleteMailbox(mailbox: string): Promise<void>;
|
|
198
215
|
renameMailbox(from: string, to: string): Promise<void>;
|
package/imap-native.js
CHANGED
|
@@ -469,9 +469,11 @@ export class NativeImapClient {
|
|
|
469
469
|
console.error(` [imap] ${unparsed} LIST responses could not be parsed (${responses.length} total responses)`);
|
|
470
470
|
return folders;
|
|
471
471
|
}
|
|
472
|
-
|
|
472
|
+
// 2026-09-16 — Claude Code (Fable 5.1), at Bob's direction: `items` parameter added so a
|
|
473
|
+
// caller can ask for RFC 8438 SIZE. Default unchanged, so existing callers see no difference.
|
|
474
|
+
async getStatus(mailbox, items = ["MESSAGES", "UIDNEXT", "UNSEEN"]) {
|
|
473
475
|
const tag = proto.nextTag();
|
|
474
|
-
const responses = await this.sendCommand(tag, proto.statusCommand(tag, mailbox,
|
|
476
|
+
const responses = await this.sendCommand(tag, proto.statusCommand(tag, mailbox, items));
|
|
475
477
|
for (const r of responses) {
|
|
476
478
|
if (r.tag === "*" && r.type === "STATUS") {
|
|
477
479
|
const data = proto.parseStatusResponse(r.text);
|
|
@@ -481,6 +483,46 @@ export class NativeImapClient {
|
|
|
481
483
|
}
|
|
482
484
|
return {};
|
|
483
485
|
}
|
|
486
|
+
/**
|
|
487
|
+
* Total size of a mailbox in octets plus its message count (for imail -sizes; added
|
|
488
|
+
* 2026-09-16 by Claude Code, Fable 5.1, at Bob's direction).
|
|
489
|
+
*
|
|
490
|
+
* Fast path: RFC 8438 `STATUS (MESSAGES SIZE)` — one round trip, no message traffic —
|
|
491
|
+
* when the server advertises STATUS=SIZE (Dovecot, Gmail do).
|
|
492
|
+
* Fallback: EXAMINE (read-only) + `UID FETCH 1:* (UID RFC822.SIZE)` summed here. That
|
|
493
|
+
* is one FETCH line per message but no envelopes or headers, so it stays cheap even
|
|
494
|
+
* on a folder of tens of thousands of messages.
|
|
495
|
+
*
|
|
496
|
+
* `method` says which path produced the number so a log can show it.
|
|
497
|
+
*/
|
|
498
|
+
async getFolderSize(mailbox) {
|
|
499
|
+
if (this.capabilities.has("STATUS=SIZE")) {
|
|
500
|
+
const st = await this.getStatus(mailbox, ["MESSAGES", "SIZE"]);
|
|
501
|
+
if (typeof st.size === "number")
|
|
502
|
+
return { messages: st.messages || 0, bytes: st.size, method: "status" };
|
|
503
|
+
// Server claimed STATUS=SIZE but answered without SIZE — fall through to counting.
|
|
504
|
+
}
|
|
505
|
+
const info = await this.examine(mailbox);
|
|
506
|
+
try {
|
|
507
|
+
if (!info.exists)
|
|
508
|
+
return { messages: 0, bytes: 0, method: "fetch" };
|
|
509
|
+
let messages = 0, bytes = 0;
|
|
510
|
+
const tag = proto.nextTag();
|
|
511
|
+
await this.sendCommand(tag, proto.fetchCommand(tag, "1:*", ["UID", "RFC822.SIZE"]), (r) => {
|
|
512
|
+
if (r.tag !== "*" || r.type !== "FETCH")
|
|
513
|
+
return;
|
|
514
|
+
const m = r.text.match(/RFC822\.SIZE\s+(\d+)/);
|
|
515
|
+
if (!m)
|
|
516
|
+
return;
|
|
517
|
+
messages++;
|
|
518
|
+
bytes += parseInt(m[1]);
|
|
519
|
+
});
|
|
520
|
+
return { messages, bytes, method: "fetch" };
|
|
521
|
+
}
|
|
522
|
+
finally {
|
|
523
|
+
await this.closeMailbox();
|
|
524
|
+
}
|
|
525
|
+
}
|
|
484
526
|
async createMailbox(mailbox) {
|
|
485
527
|
const tag = proto.nextTag();
|
|
486
528
|
const responses = await this.sendCommand(tag, proto.createCommand(tag, mailbox));
|
package/imap-protocol.d.ts
CHANGED
|
@@ -58,6 +58,9 @@ export interface StatusData {
|
|
|
58
58
|
uidNext?: number;
|
|
59
59
|
uidValidity?: number;
|
|
60
60
|
unseen?: number;
|
|
61
|
+
/** Total mailbox size in octets — RFC 8438 `STATUS (SIZE)`, only when the
|
|
62
|
+
* server advertises STATUS=SIZE and the caller asked for it. */
|
|
63
|
+
size?: number;
|
|
61
64
|
}
|
|
62
65
|
/** Generate a unique command tag */
|
|
63
66
|
export declare function nextTag(): string;
|
package/imap-protocol.js
CHANGED
|
@@ -239,6 +239,9 @@ export function parseStatusResponse(text) {
|
|
|
239
239
|
data.uidValidity = val;
|
|
240
240
|
else if (key === "UNSEEN")
|
|
241
241
|
data.unseen = val;
|
|
242
|
+
// 2026-09-16 — Claude Code (Fable 5.1), at Bob's direction: RFC 8438 SIZE, for imail -sizes.
|
|
243
|
+
else if (key === "SIZE")
|
|
244
|
+
data.size = val;
|
|
242
245
|
}
|
|
243
246
|
return data;
|
|
244
247
|
}
|
|
@@ -267,6 +270,8 @@ export function parseStatusResponseFull(text) {
|
|
|
267
270
|
data.uidValidity = val;
|
|
268
271
|
else if (key === "UNSEEN")
|
|
269
272
|
data.unseen = val;
|
|
273
|
+
else if (key === "SIZE")
|
|
274
|
+
data.size = val; // RFC 8438 (2026-09-16)
|
|
270
275
|
}
|
|
271
276
|
return { mailbox, data };
|
|
272
277
|
}
|