@bobfrankston/rmfmail 1.0.647 → 1.0.649

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/rmfmail",
3
- "version": "1.0.647",
3
+ "version": "1.0.649",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
@@ -443,18 +443,32 @@ export class MailxService {
443
443
  "Content-Type": "application/x-www-form-urlencoded",
444
444
  "User-Agent": "mailx/1.0 (https://github.com/BobFrankston/mailx)",
445
445
  };
446
+ // `redirect: "manual"` so we don't auto-issue a GET to whatever
447
+ // confirmation page the sender redirects to. Per RFC 8058 §4 the
448
+ // POST status is what indicates success; many senders redirect to
449
+ // a "you're unsubscribed" page that we never need to render. The
450
+ // pre-fix `redirect: "follow"` caused the user to see
451
+ // `Cannot GET /u/…` — that was the redirected GET hitting an
452
+ // unhandled route on the sender's confirmation host, NOT rmfmail
453
+ // using GET. Treat 2xx and 3xx as success.
446
454
  const resp = await fetch(url, {
447
455
  method: "POST",
448
456
  headers,
449
457
  body: "List-Unsubscribe=One-Click",
450
- redirect: "follow",
458
+ redirect: "manual",
451
459
  });
452
- const body = resp.ok ? "" : await resp.text().catch(() => "");
460
+ // status===0 with type==="opaqueredirect" is what `manual` returns
461
+ // for 30x; reflect that as success since the POST was accepted.
462
+ const isRedirect = resp.type === "opaqueredirect" || (resp.status >= 300 && resp.status < 400);
463
+ const ok = resp.ok || isRedirect;
464
+ const body = ok ? "" : await resp.text().catch(() => "");
465
+ const displayStatus = isRedirect ? 200 : resp.status;
466
+ const displayText = isRedirect ? "OK (redirect)" : resp.statusText;
453
467
  console.log(` [unsub] POST ${url} → ${resp.status} ${resp.statusText}${body ? `; body: ${body.slice(0, 200)}` : ""}`);
454
- const statusText = resp.ok
455
- ? resp.statusText
468
+ const statusText = ok
469
+ ? displayText
456
470
  : ((body.trim().split("\n")[0] || resp.statusText).slice(0, 200));
457
- return { ok: resp.ok, status: resp.status, statusText };
471
+ return { ok, status: displayStatus, statusText };
458
472
  }
459
473
 
460
474
  // ── External edit in Microsoft Word ──