@bobfrankston/mailx-imap 0.1.90 → 0.1.92

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 +34 -8
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -636,14 +636,16 @@ export class ImapManager extends EventEmitter {
636
636
  const releaseHostSlot = skipSemaphore ? (() => { }) : await this.acquireHostSlot(host);
637
637
  let client;
638
638
  try {
639
- // Verbose IMAP wire trace for ops connections only — that's the
640
- // lane where commands have been hanging silently with no
641
- // heartbeat / wall-clock fire / reject. Need to see the actual
642
- // commands sent and bytes received to pinpoint where the
643
- // pendingCommand is getting lost. Fast lane (C123) shares the
644
- // verbose treatment so click-time wedges show too. Other lanes
645
- // (idle, quickCheck) stay quiet so the log doesn't drown.
646
- const cfgWithVerbose = (purpose === "ops" || purpose === "fast") ? { ...config, verbose: true } : config;
639
+ // Verbose IMAP wire trace diagnostic for silently-hanging
640
+ // commands. It was left permanently ON for the ops/fast lanes, but
641
+ // that logs every literal chunk (8000+ lines during a body-fetch
642
+ // burst), and on Windows the daemon's console.log writes to the log
643
+ // file SYNCHRONOUSLY so the trace itself blocked the main event
644
+ // loop during sync, starving the IPC reply relay and producing the
645
+ // 78s read stalls (Bob 2026-06-13). Now opt-in: set RMFMAIL_IMAP_TRACE=1
646
+ // to re-enable for a debugging session. Default is quiet.
647
+ const imapTrace = process.env.RMFMAIL_IMAP_TRACE === "1";
648
+ const cfgWithVerbose = (imapTrace && (purpose === "ops" || purpose === "fast")) ? { ...config, verbose: true } : config;
647
649
  client = new CompatImapClient(cfgWithVerbose, this.transportFactory);
648
650
  }
649
651
  catch (e) {
@@ -3590,6 +3592,30 @@ export class ImapManager extends EventEmitter {
3590
3592
  }
3591
3593
  break;
3592
3594
  }
3595
+ case "copy": {
3596
+ const target = folders.find(f => f.id === action.targetFolderId);
3597
+ if (!target) {
3598
+ console.error(` [sync] Copy target folder ${action.targetFolderId} missing — dropping action UID ${action.uid}`);
3599
+ throw new Error(`copy target folder ${action.targetFolderId} not found`);
3600
+ }
3601
+ // Copy = fetch the raw message and APPEND it to the
3602
+ // target; it stays in the source folder too. The
3603
+ // compat client has no native IMAP COPY, but
3604
+ // fetch+append is equivalent and reuses existing
3605
+ // primitives. The new copy is pulled into the local
3606
+ // store by a target-folder sync below.
3607
+ const msg = await client.fetchMessageByUid(folder.path, action.uid, { source: true });
3608
+ if (!msg || !msg.source) {
3609
+ console.log(` [sync] Copy UID ${action.uid} in ${folder.path}: message gone (attempt ${action.attempts + 1}); dropping action`);
3610
+ break;
3611
+ }
3612
+ const copyFlags = (msg.flags || []).filter((f) => f !== "\\Recent");
3613
+ await client.appendMessage(target.path, msg.source, copyFlags);
3614
+ console.log(` [sync] Copied UID ${action.uid}: ${folder.path} → ${target.path}`);
3615
+ // Import the new copy so it appears in the target folder.
3616
+ this.syncFolder(accountId, target.id).catch(() => { });
3617
+ break;
3618
+ }
3593
3619
  }
3594
3620
  // Success: the local action reached the server. Lift the
3595
3621
  // 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.90",
3
+ "version": "0.1.92",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",