@bobfrankston/rmfmail 1.2.312 → 1.2.313
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/.commitmsg +19 -36
- package/.llm/trusted-lists.md +5 -2
- package/TODO.md +2 -2
- package/client/app.bundle.js +34 -7
- package/client/app.bundle.js.map +2 -2
- package/client/components/message-viewer.js +55 -9
- package/client/components/message-viewer.js.map +1 -1
- package/client/components/message-viewer.ts +53 -9
- package/client/styles/components.css +3 -0
- package/docs/allowlist.md +7 -5
- package/docs/spam-false-positives.md +1 -1
- package/npmchanges.md +42 -0
- package/package.json +5 -5
- package/packages/mailx-settings/docs/allowlist.md +7 -5
|
@@ -1516,24 +1516,37 @@ export async function showMessage(accountId, uid, folderId, specialUse, isRetry
|
|
|
1516
1516
|
// Offered from the chip's own advice, which is the only
|
|
1517
1517
|
// thing an unflagged list post shows; the banner has its
|
|
1518
1518
|
// own button.
|
|
1519
|
+
//
|
|
1520
|
+
// Offered on every proved post, trusted or not: the write
|
|
1521
|
+
// is a toggle, and once the list is trusted the chip and
|
|
1522
|
+
// banner are gone, so this menu is the only place an
|
|
1523
|
+
// approval can be undone without editing allowlist.jsonc
|
|
1524
|
+
// by hand (Bob 2026-09-09: "how would I undo an approval").
|
|
1519
1525
|
const listSpam = msg.spamScore;
|
|
1520
|
-
if (listSpam?.listProved && listSpam.listId
|
|
1526
|
+
if (listSpam?.listProved && listSpam.listId) {
|
|
1521
1527
|
const listId = listSpam.listId;
|
|
1528
|
+
const untrust = !!listSpam.listTrusted;
|
|
1522
1529
|
items.push({
|
|
1523
|
-
label: `✓ Trust the ${listId} mailing list`,
|
|
1530
|
+
label: untrust ? `✗ Stop trusting the ${listId} mailing list` : `✓ Trust the ${listId} mailing list`,
|
|
1524
1531
|
action: async () => {
|
|
1525
1532
|
const st = document.getElementById("status-sync");
|
|
1526
1533
|
try {
|
|
1527
|
-
//
|
|
1528
|
-
//
|
|
1534
|
+
// A toggle: the answer says which way it went,
|
|
1535
|
+
// and it must match what was asked for — a
|
|
1536
|
+
// mismatch means the write did not land.
|
|
1529
1537
|
const res = await trustSenderOrDomain("list", listId);
|
|
1530
|
-
if (!res
|
|
1538
|
+
if (!res || !!res.trusted === untrust)
|
|
1531
1539
|
throw new Error("the list did not save");
|
|
1532
|
-
listSpam.listTrusted =
|
|
1533
|
-
|
|
1534
|
-
|
|
1540
|
+
listSpam.listTrusted = res.trusted;
|
|
1541
|
+
if (res.trusted) {
|
|
1542
|
+
document.querySelector(".mv-spamscore")?.remove();
|
|
1543
|
+
document.querySelector(".mv-spamscore-action")?.remove();
|
|
1544
|
+
document.querySelector(".mv-trust")?.remove();
|
|
1545
|
+
}
|
|
1535
1546
|
if (st)
|
|
1536
|
-
st.textContent =
|
|
1547
|
+
st.textContent = res.trusted
|
|
1548
|
+
? `Trusting the ${listId} mailing list`
|
|
1549
|
+
: `No longer trusting the ${listId} mailing list — reopen the message to see its score again`;
|
|
1537
1550
|
}
|
|
1538
1551
|
catch (e) {
|
|
1539
1552
|
// The reader chose an action and must know whether it took.
|
|
@@ -1910,6 +1923,39 @@ export async function showMessage(accountId, uid, folderId, specialUse, isRetry
|
|
|
1910
1923
|
: "");
|
|
1911
1924
|
chip.textContent = `spam score ${spam.score} of ${spam.threshold}`;
|
|
1912
1925
|
bodyEl.appendChild(chip);
|
|
1926
|
+
// The action beside the warning it answers (Bob 2026-09-09: "it
|
|
1927
|
+
// would be nice to have an [approve this list] on the red warning
|
|
1928
|
+
// banner"). An unflagged list post has no banner — the chip IS
|
|
1929
|
+
// the warning — so the button sits next to it. Same write as the
|
|
1930
|
+
// From-menu item and the banner button: trustedLists by List-Id.
|
|
1931
|
+
if (spam.listProved && spam.listId && !spam.listTrusted) {
|
|
1932
|
+
const listId = spam.listId;
|
|
1933
|
+
const b = document.createElement("button");
|
|
1934
|
+
b.className = "mv-trust-action mv-spamscore-action";
|
|
1935
|
+
b.textContent = `Trust the ${listId} list`;
|
|
1936
|
+
b.title = `Delivered by the ${listId} mailing list, which your server proved sent it. Trusting the list hides this score on every post the list delivers.`;
|
|
1937
|
+
b.addEventListener("click", async () => {
|
|
1938
|
+
b.disabled = true;
|
|
1939
|
+
try {
|
|
1940
|
+
// Only ever ADDS, so anything but `trusted: true` means
|
|
1941
|
+
// the write did not land — never hide the chip on a
|
|
1942
|
+
// failed save.
|
|
1943
|
+
const res = await trustSenderOrDomain("list", listId);
|
|
1944
|
+
if (!res?.trusted)
|
|
1945
|
+
throw new Error("the list did not save");
|
|
1946
|
+
spam.listTrusted = true;
|
|
1947
|
+
chip.remove();
|
|
1948
|
+
b.remove();
|
|
1949
|
+
document.querySelector(".mv-trust")?.remove();
|
|
1950
|
+
}
|
|
1951
|
+
catch (e) {
|
|
1952
|
+
// The reader pressed a button and must know whether it took.
|
|
1953
|
+
b.disabled = false;
|
|
1954
|
+
b.textContent = `Could not save: ${e?.message || e}`;
|
|
1955
|
+
}
|
|
1956
|
+
});
|
|
1957
|
+
bodyEl.appendChild(b);
|
|
1958
|
+
}
|
|
1913
1959
|
}
|
|
1914
1960
|
const trust = (msg.trust || []);
|
|
1915
1961
|
if (trust.length) {
|