@bobfrankston/iflow-direct 0.1.49 → 0.1.50
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 +1 -0
- package/imap-compat.js +1 -1
- package/imap-native.d.ts +7 -1
- package/imap-native.js +27 -1
- package/package.json +1 -1
package/imap-compat.d.ts
CHANGED
|
@@ -160,6 +160,7 @@ export declare class CompatImapClient {
|
|
|
160
160
|
watchMailbox(mailbox: string, onNew: (count: number) => void, opts?: {
|
|
161
161
|
notifySpec?: string;
|
|
162
162
|
onMailboxStatus?: (mailbox: string, data: proto.StatusData) => void;
|
|
163
|
+
onExpunge?: () => void;
|
|
163
164
|
}): Promise<() => Promise<void>>;
|
|
164
165
|
/** Copy a message to another server (cross-account) */
|
|
165
166
|
moveMessageToServer(msg: any, fromMailbox: string, targetClient: CompatImapClient, toMailbox: string): Promise<void>;
|
package/imap-compat.js
CHANGED
|
@@ -349,7 +349,7 @@ export class CompatImapClient {
|
|
|
349
349
|
this.native.onMailboxStatus = opts.onMailboxStatus;
|
|
350
350
|
if (opts?.notifySpec)
|
|
351
351
|
await this.native.notify(opts.notifySpec);
|
|
352
|
-
return this.native.startIdle(onNew);
|
|
352
|
+
return this.native.startIdle(onNew, opts?.onExpunge);
|
|
353
353
|
}
|
|
354
354
|
/** Copy a message to another server (cross-account) */
|
|
355
355
|
async moveMessageToServer(msg, fromMailbox, targetClient, toMailbox) {
|
package/imap-native.d.ts
CHANGED
|
@@ -113,6 +113,12 @@ export declare class NativeImapClient {
|
|
|
113
113
|
private _connected;
|
|
114
114
|
private idleTag;
|
|
115
115
|
private idleCallback;
|
|
116
|
+
/** Fires when the SELECTED mailbox loses messages while parked in IDLE —
|
|
117
|
+
* an EXISTS decrease, or an unsolicited `* EXPUNGE` / `* VANISHED`
|
|
118
|
+
* (RFC 5465 NOTIFY SELECTED MessageExpunge). Lets the caller reconcile
|
|
119
|
+
* a server-side deletion in real time instead of waiting for the next
|
|
120
|
+
* periodic poll. Distinct from `idleCallback` (new mail only). */
|
|
121
|
+
private idleExpungeCallback;
|
|
116
122
|
private idleRefreshTimer;
|
|
117
123
|
/** RFC 5465 NOTIFY: fires on unsolicited STATUS responses for non-selected
|
|
118
124
|
* mailboxes (the server pushes these when the client has issued NOTIFY
|
|
@@ -257,7 +263,7 @@ export declare class NativeImapClient {
|
|
|
257
263
|
* SELECT and BEFORE startIdle — the server holds the spec for the
|
|
258
264
|
* lifetime of the connection. */
|
|
259
265
|
notify(spec: string): Promise<void>;
|
|
260
|
-
startIdle(onNewMail: (count: number) => void): Promise<() => Promise<void>>;
|
|
266
|
+
startIdle(onNewMail: (count: number) => void, onExpunge?: () => void): Promise<() => Promise<void>>;
|
|
261
267
|
/**
|
|
262
268
|
* If IDLE is currently active, send DONE and wait for its tagged OK so the
|
|
263
269
|
* connection is free to accept a new command. Saves the active callback so
|
package/imap-native.js
CHANGED
|
@@ -39,6 +39,12 @@ export class NativeImapClient {
|
|
|
39
39
|
_connected = false;
|
|
40
40
|
idleTag = null;
|
|
41
41
|
idleCallback = null;
|
|
42
|
+
/** Fires when the SELECTED mailbox loses messages while parked in IDLE —
|
|
43
|
+
* an EXISTS decrease, or an unsolicited `* EXPUNGE` / `* VANISHED`
|
|
44
|
+
* (RFC 5465 NOTIFY SELECTED MessageExpunge). Lets the caller reconcile
|
|
45
|
+
* a server-side deletion in real time instead of waiting for the next
|
|
46
|
+
* periodic poll. Distinct from `idleCallback` (new mail only). */
|
|
47
|
+
idleExpungeCallback = null;
|
|
42
48
|
idleRefreshTimer = null;
|
|
43
49
|
/** RFC 5465 NOTIFY: fires on unsolicited STATUS responses for non-selected
|
|
44
50
|
* mailboxes (the server pushes these when the client has issued NOTIFY
|
|
@@ -731,8 +737,9 @@ export class NativeImapClient {
|
|
|
731
737
|
}
|
|
732
738
|
}
|
|
733
739
|
// ── IDLE ──
|
|
734
|
-
async startIdle(onNewMail) {
|
|
740
|
+
async startIdle(onNewMail, onExpunge) {
|
|
735
741
|
this.idleCallback = onNewMail;
|
|
742
|
+
this.idleExpungeCallback = onExpunge ?? null;
|
|
736
743
|
this.idleStopped = false;
|
|
737
744
|
const beginIdleCycle = async () => {
|
|
738
745
|
const tag = proto.nextTag();
|
|
@@ -764,6 +771,7 @@ export class NativeImapClient {
|
|
|
764
771
|
const tag = this.idleTag;
|
|
765
772
|
this.idleTag = null;
|
|
766
773
|
this.idleCallback = null;
|
|
774
|
+
this.idleExpungeCallback = null;
|
|
767
775
|
if (tag) {
|
|
768
776
|
// Arm tagged-wait BEFORE DONE — avoid missing the OK.
|
|
769
777
|
const waitTag = this.waitForTagged(tag);
|
|
@@ -1291,6 +1299,24 @@ export class NativeImapClient {
|
|
|
1291
1299
|
this.mailboxInfo.exists = count;
|
|
1292
1300
|
this.idleCallback(newCount);
|
|
1293
1301
|
}
|
|
1302
|
+
else if (count < this.mailboxInfo.exists) {
|
|
1303
|
+
// Count dropped — a message was expunged on the selected
|
|
1304
|
+
// mailbox (another client / Thunderbird deleted it).
|
|
1305
|
+
// Signal the caller to reconcile the deletion now.
|
|
1306
|
+
this.mailboxInfo.exists = count;
|
|
1307
|
+
if (this.idleExpungeCallback)
|
|
1308
|
+
this.idleExpungeCallback();
|
|
1309
|
+
}
|
|
1310
|
+
continue;
|
|
1311
|
+
}
|
|
1312
|
+
// During IDLE, an unsolicited `* n EXPUNGE` / `* VANISHED` for the
|
|
1313
|
+
// selected mailbox (RFC 5465 NOTIFY SELECTED MessageExpunge, or a
|
|
1314
|
+
// plain post-EXPUNGE notification). Push a deletion reconcile.
|
|
1315
|
+
if (this.idleTag && resp.tag === "*" && (resp.type === "EXPUNGE" || resp.type === "VANISHED")) {
|
|
1316
|
+
if (this.mailboxInfo.exists > 0)
|
|
1317
|
+
this.mailboxInfo.exists--;
|
|
1318
|
+
if (this.idleExpungeCallback)
|
|
1319
|
+
this.idleExpungeCallback();
|
|
1294
1320
|
continue;
|
|
1295
1321
|
}
|
|
1296
1322
|
// RFC 5465 NOTIFY: unsolicited STATUS responses for non-selected
|