@bobfrankston/mailx-imap 0.1.89 → 0.1.91

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 +39 -0
  2. package/package.json +5 -5
package/index.js CHANGED
@@ -2829,6 +2829,15 @@ export class ImapManager extends EventEmitter {
2829
2829
  }
2830
2830
  if (!this.configs.has(accountId))
2831
2831
  return null;
2832
+ // Back off a body that recently hung / failed. One un-fetchable message
2833
+ // (the server stalls on its BODY[] — Bob 2026-06-12, UID 4966060) was
2834
+ // being re-fetched on every view + prefetch tick, each attempt hanging
2835
+ // ~90s and tying up the ops queue, so user actions (delete, open) were
2836
+ // delayed until the client timed out. The 5min→12h backoff (shared with
2837
+ // prefetch via isPrefetchEmpty) stops the tight re-fetch loop; the body
2838
+ // simply shows as unavailable until the backoff lapses and one retry runs.
2839
+ if (this.isPrefetchEmpty(accountId, folderId, uid))
2840
+ return null;
2832
2841
  const folder = this.db.getFolders(accountId).find(f => f.id === folderId);
2833
2842
  if (!folder)
2834
2843
  return null;
@@ -2859,6 +2868,12 @@ export class ImapManager extends EventEmitter {
2859
2868
  if (e?.isNotFound)
2860
2869
  throw e;
2861
2870
  console.error(` Body fetch error (${accountId}/${uid}): ${e?.message || e}`);
2871
+ // Record so the next view / prefetch backs off instead of
2872
+ // re-attempting a hanging fetch and re-congesting the queue.
2873
+ try {
2874
+ this.markPrefetchEmpty(accountId, folderId, uid);
2875
+ }
2876
+ catch { /* */ }
2862
2877
  return null;
2863
2878
  }
2864
2879
  }
@@ -3575,6 +3590,30 @@ export class ImapManager extends EventEmitter {
3575
3590
  }
3576
3591
  break;
3577
3592
  }
3593
+ case "copy": {
3594
+ const target = folders.find(f => f.id === action.targetFolderId);
3595
+ if (!target) {
3596
+ console.error(` [sync] Copy target folder ${action.targetFolderId} missing — dropping action UID ${action.uid}`);
3597
+ throw new Error(`copy target folder ${action.targetFolderId} not found`);
3598
+ }
3599
+ // Copy = fetch the raw message and APPEND it to the
3600
+ // target; it stays in the source folder too. The
3601
+ // compat client has no native IMAP COPY, but
3602
+ // fetch+append is equivalent and reuses existing
3603
+ // primitives. The new copy is pulled into the local
3604
+ // store by a target-folder sync below.
3605
+ const msg = await client.fetchMessageByUid(folder.path, action.uid, { source: true });
3606
+ if (!msg || !msg.source) {
3607
+ console.log(` [sync] Copy UID ${action.uid} in ${folder.path}: message gone (attempt ${action.attempts + 1}); dropping action`);
3608
+ break;
3609
+ }
3610
+ const copyFlags = (msg.flags || []).filter((f) => f !== "\\Recent");
3611
+ await client.appendMessage(target.path, msg.source, copyFlags);
3612
+ console.log(` [sync] Copied UID ${action.uid}: ${folder.path} → ${target.path}`);
3613
+ // Import the new copy so it appears in the target folder.
3614
+ this.syncFolder(accountId, target.id).catch(() => { });
3615
+ break;
3616
+ }
3578
3617
  }
3579
3618
  // Success: the local action reached the server. Lift the
3580
3619
  // in-flight delete/move suppression so the destination
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx-imap",
3
- "version": "0.1.89",
3
+ "version": "0.1.91",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -11,11 +11,11 @@
11
11
  "dependencies": {
12
12
  "@bobfrankston/mailx-types": "^0.1.19",
13
13
  "@bobfrankston/mailx-settings": "^0.1.26",
14
- "@bobfrankston/mailx-store": "^0.1.46",
14
+ "@bobfrankston/mailx-store": "^0.1.47",
15
15
  "@bobfrankston/iflow-direct": "^0.1.53",
16
16
  "@bobfrankston/tcp-transport": "^0.1.7",
17
17
  "@bobfrankston/smtp-direct": "^0.1.9",
18
- "@bobfrankston/mailx-sync": "^0.1.20",
18
+ "@bobfrankston/mailx-sync": "^0.1.22",
19
19
  "@bobfrankston/oauthsupport": "^1.0.32"
20
20
  },
21
21
  "repository": {
@@ -39,11 +39,11 @@
39
39
  "dependencies": {
40
40
  "@bobfrankston/mailx-types": "^0.1.19",
41
41
  "@bobfrankston/mailx-settings": "^0.1.26",
42
- "@bobfrankston/mailx-store": "^0.1.46",
42
+ "@bobfrankston/mailx-store": "^0.1.47",
43
43
  "@bobfrankston/iflow-direct": "^0.1.53",
44
44
  "@bobfrankston/tcp-transport": "^0.1.7",
45
45
  "@bobfrankston/smtp-direct": "^0.1.9",
46
- "@bobfrankston/mailx-sync": "^0.1.20",
46
+ "@bobfrankston/mailx-sync": "^0.1.22",
47
47
  "@bobfrankston/oauthsupport": "^1.0.32"
48
48
  }
49
49
  }