@bobfrankston/mailx-imap 0.1.46 → 0.1.48
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/index.js +28 -1
- package/package.json +9 -9
package/index.js
CHANGED
|
@@ -1213,10 +1213,18 @@ export class ImapManager extends EventEmitter {
|
|
|
1213
1213
|
// emits them only via state-change FETCH if their flags
|
|
1214
1214
|
// changed since modSeq, which is unreliable. Pull them
|
|
1215
1215
|
// explicitly via the existing incremental path.
|
|
1216
|
+
// INSTRUMENTATION (2026-05-15): phase timestamps so the
|
|
1217
|
+
// log pinpoints which operation eats wall-clock during a
|
|
1218
|
+
// slow sync. The 27 s INBOX block had a silent log hole;
|
|
1219
|
+
// these markers fill it.
|
|
1220
|
+
const __t1 = Date.now();
|
|
1216
1221
|
const fetched = await client.fetchMessagesSinceUid(folder.path, highestUid, { source: false });
|
|
1222
|
+
console.log(` [qr-phase] ${folder.path}: fetchMessagesSinceUid → ${fetched.length} msgs in ${Date.now() - __t1}ms`);
|
|
1217
1223
|
const newOnes = fetched.filter((m) => m.uid > highestUid);
|
|
1218
1224
|
if (newOnes.length > 0) {
|
|
1225
|
+
const __t2 = Date.now();
|
|
1219
1226
|
await this.storeMessages(accountId, folderId, folder, newOnes, highestUid);
|
|
1227
|
+
console.log(` [qr-phase] ${folder.path}: storeMessages(${newOnes.length}) in ${Date.now() - __t2}ms`);
|
|
1220
1228
|
}
|
|
1221
1229
|
// Persist new watermark — next resync starts here.
|
|
1222
1230
|
if (qr.newHighestModSeq !== undefined) {
|
|
@@ -2439,10 +2447,29 @@ export class ImapManager extends EventEmitter {
|
|
|
2439
2447
|
this.syncFolder(accountId, folder.id).catch(e => console.error(` [notify] sync ${mailboxPath} failed: ${e.message}`));
|
|
2440
2448
|
}
|
|
2441
2449
|
: undefined;
|
|
2450
|
+
// Deletion push: when the server expunges a message from
|
|
2451
|
+
// INBOX while we're parked in IDLE (e.g. the user deletes it
|
|
2452
|
+
// in Thunderbird), reconcile it locally right away instead of
|
|
2453
|
+
// waiting for the 5-minute poll. Debounced — a cleanup pass
|
|
2454
|
+
// fires a burst of EXPUNGE notifications; collapse them into
|
|
2455
|
+
// one syncFolder. syncFolder's set-diff drops the gone rows.
|
|
2456
|
+
let expungeTimer = null;
|
|
2457
|
+
const onExpunge = () => {
|
|
2458
|
+
if (expungeTimer)
|
|
2459
|
+
clearTimeout(expungeTimer);
|
|
2460
|
+
expungeTimer = setTimeout(() => {
|
|
2461
|
+
expungeTimer = null;
|
|
2462
|
+
const inbox = this.db.getFolders(accountId).find(f => f.specialUse === "inbox");
|
|
2463
|
+
if (!inbox)
|
|
2464
|
+
return;
|
|
2465
|
+
console.log(` [idle] ${accountId}: INBOX expunge pushed → reconcile`);
|
|
2466
|
+
this.syncFolder(accountId, inbox.id).catch(e => console.error(` [idle] expunge reconcile failed: ${e.message}`));
|
|
2467
|
+
}, 2000);
|
|
2468
|
+
};
|
|
2442
2469
|
const stop = await watchClient.watchMailbox("INBOX", (newCount) => {
|
|
2443
2470
|
console.log(` [idle] ${accountId}: ${newCount} new message(s)`);
|
|
2444
2471
|
this.syncInboxNewOnly(accountId).catch(e => console.error(` [idle] sync error: ${e.message}`));
|
|
2445
|
-
}, { notifySpec, onMailboxStatus });
|
|
2472
|
+
}, { notifySpec, onMailboxStatus, onExpunge });
|
|
2446
2473
|
this.watchers.set(accountId, async () => {
|
|
2447
2474
|
await stop();
|
|
2448
2475
|
await watchClient.logout();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx-imap",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.48",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
},
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@bobfrankston/mailx-types": "^0.1.
|
|
12
|
+
"@bobfrankston/mailx-types": "^0.1.14",
|
|
13
13
|
"@bobfrankston/mailx-settings": "^0.1.17",
|
|
14
|
-
"@bobfrankston/mailx-store": "^0.1.
|
|
15
|
-
"@bobfrankston/iflow-direct": "^0.1.
|
|
14
|
+
"@bobfrankston/mailx-store": "^0.1.27",
|
|
15
|
+
"@bobfrankston/iflow-direct": "^0.1.50",
|
|
16
16
|
"@bobfrankston/tcp-transport": "^0.1.6",
|
|
17
17
|
"@bobfrankston/smtp-direct": "^0.1.8",
|
|
18
|
-
"@bobfrankston/mailx-sync": "^0.1.
|
|
18
|
+
"@bobfrankston/mailx-sync": "^0.1.17",
|
|
19
19
|
"@bobfrankston/oauthsupport": "^1.0.26"
|
|
20
20
|
},
|
|
21
21
|
"repository": {
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
},
|
|
38
38
|
".transformedSnapshot": {
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@bobfrankston/mailx-types": "^0.1.
|
|
40
|
+
"@bobfrankston/mailx-types": "^0.1.14",
|
|
41
41
|
"@bobfrankston/mailx-settings": "^0.1.17",
|
|
42
|
-
"@bobfrankston/mailx-store": "^0.1.
|
|
43
|
-
"@bobfrankston/iflow-direct": "^0.1.
|
|
42
|
+
"@bobfrankston/mailx-store": "^0.1.27",
|
|
43
|
+
"@bobfrankston/iflow-direct": "^0.1.50",
|
|
44
44
|
"@bobfrankston/tcp-transport": "^0.1.6",
|
|
45
45
|
"@bobfrankston/smtp-direct": "^0.1.8",
|
|
46
|
-
"@bobfrankston/mailx-sync": "^0.1.
|
|
46
|
+
"@bobfrankston/mailx-sync": "^0.1.17",
|
|
47
47
|
"@bobfrankston/oauthsupport": "^1.0.26"
|
|
48
48
|
}
|
|
49
49
|
}
|