@bobfrankston/rmfmail 1.1.235 → 1.1.237
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/client/app.bundle.js +6 -1
- package/client/app.bundle.js.map +2 -2
- package/client/components/message-viewer.js +13 -2
- package/client/components/message-viewer.js.map +1 -1
- package/client/components/message-viewer.ts +13 -2
- package/package.json +5 -5
- package/packages/mailx-imap/index.d.ts.map +1 -1
- package/packages/mailx-imap/index.js +34 -8
- package/packages/mailx-imap/index.js.map +1 -1
- package/packages/mailx-imap/index.ts +31 -4
- package/packages/mailx-imap/package-lock.json +2 -2
- package/packages/mailx-imap/package.json +1 -1
- package/packages/mailx-store/package.json +1 -1
- package/packages/mailx-types/package.json +1 -1
|
@@ -4131,11 +4131,28 @@ export class ImapManager extends EventEmitter {
|
|
|
4131
4131
|
const [, original, host, pidStr] = m;
|
|
4132
4132
|
if (host !== this.hostname) continue;
|
|
4133
4133
|
const pid = parseInt(pidStr);
|
|
4134
|
-
if (pid === myPid) continue; // it's us
|
|
4135
|
-
let alive = false;
|
|
4136
|
-
try { process.kill(pid, 0); alive = true; } catch { /* dead */ }
|
|
4137
4134
|
let ageMs = Infinity;
|
|
4138
4135
|
try { ageMs = Date.now() - fs.statSync(path.join(dir, f)).mtimeMs; } catch { /* */ }
|
|
4136
|
+
if (pid === myPid) {
|
|
4137
|
+
// Our own claim. Normally we're actively sending it — leave
|
|
4138
|
+
// it. But the send is now bounded (60s APPEND timeout), so
|
|
4139
|
+
// an OWN claim older than STALE_CLAIM_MS means the send
|
|
4140
|
+
// hung past its timeout, or a prior tick orphaned it (the
|
|
4141
|
+
// release rename failed). Without reclaiming it the file
|
|
4142
|
+
// sits in `.sending-` forever — recovery used to skip every
|
|
4143
|
+
// own-PID claim unconditionally, so a transient connection
|
|
4144
|
+
// wedge pinned the message even after the link recovered
|
|
4145
|
+
// (Bob 2026-06-11: two messages stuck .sending-<ourpid>
|
|
4146
|
+
// while SELECT Outbox was already succeeding again).
|
|
4147
|
+
if (ageMs < STALE_CLAIM_MS) continue;
|
|
4148
|
+
try {
|
|
4149
|
+
fs.renameSync(path.join(dir, f), path.join(dir, original));
|
|
4150
|
+
console.log(` [outbox] Recovered our own stale claim ${f} → ${original} (hung ${Math.round(ageMs / 60_000)}m)`);
|
|
4151
|
+
} catch { /* ignore */ }
|
|
4152
|
+
continue;
|
|
4153
|
+
}
|
|
4154
|
+
let alive = false;
|
|
4155
|
+
try { process.kill(pid, 0); alive = true; } catch { /* dead */ }
|
|
4139
4156
|
// Live PID + recent mtime → genuine sibling owner, leave it.
|
|
4140
4157
|
// Live PID + ancient mtime → recycled PID, sweep. Dead PID → sweep.
|
|
4141
4158
|
if (alive && ageMs < STALE_CLAIM_MS) continue;
|
|
@@ -4261,7 +4278,17 @@ export class ImapManager extends EventEmitter {
|
|
|
4261
4278
|
}
|
|
4262
4279
|
try {
|
|
4263
4280
|
const raw = fs.readFileSync(claimedPath, "utf-8");
|
|
4264
|
-
|
|
4281
|
+
// Bound the APPEND. On a wedged connection (Dovecot
|
|
4282
|
+
// ETIMEDOUT storm) the bare await can hang the full
|
|
4283
|
+
// 300s inactivity timeout, pinning the file in
|
|
4284
|
+
// `.sending-` state the whole time and reading to the
|
|
4285
|
+
// user as "stuck, not sending" (Bob 2026-06-11). A
|
|
4286
|
+
// 60s cap force-closes the socket and throws, so the
|
|
4287
|
+
// catch below releases the claim and the next tick
|
|
4288
|
+
// retries instead of hanging for 5 minutes.
|
|
4289
|
+
await withTimeout(
|
|
4290
|
+
client.appendMessage(outboxPath, raw, ["\\Seen"]),
|
|
4291
|
+
60_000, client, `outbox APPEND ${file}`);
|
|
4265
4292
|
fs.renameSync(claimedPath, path.join(sentDir, file));
|
|
4266
4293
|
console.log(` [outbox] Moved ${file} to IMAP Outbox → sent/`);
|
|
4267
4294
|
} catch (e: any) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx-imap",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.86",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bobfrankston/mailx-imap",
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.86",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@bobfrankston/iflow-direct": "^0.1.27",
|