@bobfrankston/mailx-imap 0.1.47 → 0.1.49

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 (2) hide show
  1. package/index.js +30 -3
  2. package/package.json +5 -5
package/index.js CHANGED
@@ -81,6 +81,14 @@ function toEmailAddress(addr) {
81
81
  address: addr?.address || ""
82
82
  };
83
83
  }
84
+ /** Coerce a message date to a finite epoch-ms for the `messages.date NOT NULL`
85
+ * column. An unparseable envelope date yields an *Invalid Date* — truthy and
86
+ * `instanceof Date`, but `.getTime()` is NaN, which binds as NULL and fails
87
+ * the constraint, aborting the whole sync batch. Default non-finite to now. */
88
+ function toFiniteDateMs(d) {
89
+ const ms = d instanceof Date ? d.getTime() : typeof d === "number" ? d : NaN;
90
+ return Number.isFinite(ms) ? ms : Date.now();
91
+ }
84
92
  /** Convert array of iflow addresses */
85
93
  function toEmailAddresses(addrs) {
86
94
  if (!addrs)
@@ -963,7 +971,7 @@ export class ImapManager extends EventEmitter {
963
971
  messageId: msg.messageId || "",
964
972
  inReplyTo: msg.inReplyTo || "",
965
973
  references: [],
966
- date: msg.date instanceof Date ? msg.date.getTime() : (typeof msg.date === "number" ? msg.date : Date.now()),
974
+ date: toFiniteDateMs(msg.date),
967
975
  subject: msg.subject || "",
968
976
  from: toEmailAddress(msg.from?.[0] || {}),
969
977
  to: toEmailAddresses(msg.to || []),
@@ -1475,7 +1483,7 @@ export class ImapManager extends EventEmitter {
1475
1483
  messageId: msg.messageId || "",
1476
1484
  inReplyTo: msg.inReplyTo || "",
1477
1485
  references: [],
1478
- date: msg.date instanceof Date ? msg.date.getTime() : (typeof msg.date === "number" ? msg.date : Date.now()),
1486
+ date: toFiniteDateMs(msg.date),
1479
1487
  subject: msg.subject || "",
1480
1488
  from: toEmailAddress(msg.from?.[0] || {}),
1481
1489
  to: toEmailAddresses(msg.to || []),
@@ -2447,10 +2455,29 @@ export class ImapManager extends EventEmitter {
2447
2455
  this.syncFolder(accountId, folder.id).catch(e => console.error(` [notify] sync ${mailboxPath} failed: ${e.message}`));
2448
2456
  }
2449
2457
  : undefined;
2458
+ // Deletion push: when the server expunges a message from
2459
+ // INBOX while we're parked in IDLE (e.g. the user deletes it
2460
+ // in Thunderbird), reconcile it locally right away instead of
2461
+ // waiting for the 5-minute poll. Debounced — a cleanup pass
2462
+ // fires a burst of EXPUNGE notifications; collapse them into
2463
+ // one syncFolder. syncFolder's set-diff drops the gone rows.
2464
+ let expungeTimer = null;
2465
+ const onExpunge = () => {
2466
+ if (expungeTimer)
2467
+ clearTimeout(expungeTimer);
2468
+ expungeTimer = setTimeout(() => {
2469
+ expungeTimer = null;
2470
+ const inbox = this.db.getFolders(accountId).find(f => f.specialUse === "inbox");
2471
+ if (!inbox)
2472
+ return;
2473
+ console.log(` [idle] ${accountId}: INBOX expunge pushed → reconcile`);
2474
+ this.syncFolder(accountId, inbox.id).catch(e => console.error(` [idle] expunge reconcile failed: ${e.message}`));
2475
+ }, 2000);
2476
+ };
2450
2477
  const stop = await watchClient.watchMailbox("INBOX", (newCount) => {
2451
2478
  console.log(` [idle] ${accountId}: ${newCount} new message(s)`);
2452
2479
  this.syncInboxNewOnly(accountId).catch(e => console.error(` [idle] sync error: ${e.message}`));
2453
- }, { notifySpec, onMailboxStatus });
2480
+ }, { notifySpec, onMailboxStatus, onExpunge });
2454
2481
  this.watchers.set(accountId, async () => {
2455
2482
  await stop();
2456
2483
  await watchClient.logout();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx-imap",
3
- "version": "0.1.47",
3
+ "version": "0.1.49",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -11,8 +11,8 @@
11
11
  "dependencies": {
12
12
  "@bobfrankston/mailx-types": "^0.1.14",
13
13
  "@bobfrankston/mailx-settings": "^0.1.17",
14
- "@bobfrankston/mailx-store": "^0.1.26",
15
- "@bobfrankston/iflow-direct": "^0.1.46",
14
+ "@bobfrankston/mailx-store": "^0.1.28",
15
+ "@bobfrankston/iflow-direct": "^0.1.50",
16
16
  "@bobfrankston/tcp-transport": "^0.1.6",
17
17
  "@bobfrankston/smtp-direct": "^0.1.8",
18
18
  "@bobfrankston/mailx-sync": "^0.1.17",
@@ -39,8 +39,8 @@
39
39
  "dependencies": {
40
40
  "@bobfrankston/mailx-types": "^0.1.14",
41
41
  "@bobfrankston/mailx-settings": "^0.1.17",
42
- "@bobfrankston/mailx-store": "^0.1.26",
43
- "@bobfrankston/iflow-direct": "^0.1.46",
42
+ "@bobfrankston/mailx-store": "^0.1.28",
43
+ "@bobfrankston/iflow-direct": "^0.1.50",
44
44
  "@bobfrankston/tcp-transport": "^0.1.6",
45
45
  "@bobfrankston/smtp-direct": "^0.1.8",
46
46
  "@bobfrankston/mailx-sync": "^0.1.17",