@bobfrankston/rmfmail 1.2.290 → 1.2.292
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 +24 -34
- package/client/android-bootstrap.bundle.js +42 -1
- package/client/android-bootstrap.bundle.js.map +2 -2
- package/client/app.bundle.js +36 -2
- package/client/app.bundle.js.map +2 -2
- package/client/components/message-viewer.js +53 -2
- package/client/components/message-viewer.js.map +1 -1
- package/client/components/message-viewer.ts +53 -3
- package/client/compose/compose.bundle.js +5 -1
- package/client/compose/compose.bundle.js.map +2 -2
- package/client/lib/api-client.js +7 -1
- package/client/lib/api-client.js.map +1 -1
- package/client/lib/api-client.ts +9 -2
- package/client/lib/mailxapi.js +3 -0
- package/client/styles/components.css +25 -0
- package/npmchanges.md +76 -0
- package/package.json +5 -5
- package/packages/mailx-imap/package-lock.json +2 -2
- package/packages/mailx-imap/package.json +1 -1
- package/packages/mailx-service/index.d.ts +20 -0
- package/packages/mailx-service/index.d.ts.map +1 -1
- package/packages/mailx-service/index.js +37 -0
- package/packages/mailx-service/index.js.map +1 -1
- package/packages/mailx-service/index.ts +37 -1
- package/packages/mailx-service/jsonrpc.js +2 -0
- package/packages/mailx-service/jsonrpc.js.map +1 -1
- package/packages/mailx-service/jsonrpc.ts +2 -0
- package/packages/mailx-service/package.json +1 -1
- package/packages/mailx-settings/package.json +1 -1
- package/packages/mailx-store/package.json +1 -1
- package/packages/mailx-store/store.d.ts.map +1 -1
- package/packages/mailx-store/store.js +30 -5
- package/packages/mailx-store/store.js.map +1 -1
- package/packages/mailx-store/store.ts +30 -5
- package/packages/mailx-store-web/android-bootstrap.js +3 -0
- package/packages/mailx-store-web/android-bootstrap.js.map +1 -1
- package/packages/mailx-store-web/android-bootstrap.ts +3 -0
- package/packages/mailx-store-web/package.json +1 -1
- package/packages/mailx-store-web/web-jsonrpc.js +2 -0
- package/packages/mailx-store-web/web-jsonrpc.js.map +1 -1
- package/packages/mailx-store-web/web-jsonrpc.ts +2 -0
- package/packages/mailx-store-web/web-service.d.ts +9 -0
- package/packages/mailx-store-web/web-service.d.ts.map +1 -1
- package/packages/mailx-store-web/web-service.js +28 -0
- package/packages/mailx-store-web/web-service.js.map +1 -1
- package/packages/mailx-store-web/web-service.ts +23 -1
- package/packages/mailx-types/package.json +1 -1
- package/packages/mailx-types/trust.d.ts +11 -0
- package/packages/mailx-types/trust.d.ts.map +1 -1
- package/packages/mailx-types/trust.js +18 -0
- package/packages/mailx-types/trust.js.map +1 -1
- package/packages/mailx-types/trust.ts +29 -0
- /package/packages/mailx-imap/{node_modules.npmglobalize-stash-27100 → node_modules.npmglobalize-stash-50524}/.package-lock.json +0 -0
package/.commitmsg
CHANGED
|
@@ -1,39 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
Trusting a sender must not turn on their tracking pixels
|
|
2
2
|
|
|
3
|
-
Bob 2026-08-28
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Bob 2026-08-28, on a newsletter he subscribed to: "I don't need the spam
|
|
4
|
+
reminder but I don't want to say show remote content in order to prevent
|
|
5
|
+
tracking." He was right, and the shape of the bug is that the allowlist was
|
|
6
|
+
answering two different questions with one list. The only gesture in the whole
|
|
7
|
+
app that said "this correspondent is fine" was the remote-content banner's
|
|
8
|
+
"Always: …", which buys a tracking pixel with every vote of confidence.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
An unknown rule now keeps a proved sender at caution only when it could have
|
|
12
|
-
flagged the message BY ITSELF — its own scores summed against the server's own
|
|
13
|
-
threshold. That adds no constant to tune: "enough to condemn" already has a
|
|
14
|
-
number and it is the one the server used. KAM_BENEFICIARY, the case the policy
|
|
15
|
-
exists for, is worth 10.0 alone and still cautions; a 1.5 click-tracker cannot.
|
|
16
|
-
Unscored rules (no X-Spam-Report) leave the sum unknown, and unknown stays
|
|
17
|
-
cautious.
|
|
10
|
+
Two lists now, both in allowlist.jsonc:
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
senders / domains load their images, and I trust them
|
|
13
|
+
trustedSenders / trustedDomains ONLY stop warning me about them
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
a tracking domain the sending platform owns is not an abused redirect.
|
|
25
|
-
- KAM_*URIBL_* ("Body contains URI listed in PCCC WILD RBL", 9.0) and
|
|
26
|
-
SH_HBL_EMAILS ("Email address listed in email blocklist", 8.0) are the same
|
|
27
|
-
evidence as URIBL_SBL — somebody else's list about a host the message
|
|
28
|
-
mentions — and were the bulk of the remaining noise: a Business Insider
|
|
29
|
-
newsletter, an MIT cancer-center invitation, a campaign mailing.
|
|
30
|
-
KAM_INFOUSMEBIZ judges the TLD a domain lives in, which is guilt by
|
|
31
|
-
neighbourhood.
|
|
15
|
+
Both feed `senderTrusted` in the store; only the first feeds `allowRemote`, and
|
|
16
|
+
that line carries a comment saying why it must never be widened to the second.
|
|
32
17
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
18
|
+
The trust note gains the action it was missing: **"Stop warning about
|
|
19
|
+
‹address›"** and **"Stop warning about *@‹domain›"**, naming the sender rather
|
|
20
|
+
than saying "this one" so the choice is checkable afterwards. New IPC
|
|
21
|
+
`trustSenderOrDomain` (toggle, like flagSenderOrDomain) wired through all six
|
|
22
|
+
places — service, jsonrpc, web-service, web-jsonrpc, android-bootstrap,
|
|
23
|
+
api-client + mailxapi.js; the bridge-contract guard passes at 110 client calls.
|
|
24
|
+
|
|
25
|
+
The buttons appear only where the server's own verdict is the WHOLE finding and
|
|
26
|
+
the sender is proved. A forgery banner gets no such button: no list should be
|
|
27
|
+
able to silence "this message is not what it says it is", and there is nothing
|
|
28
|
+
to trust when identity is the thing in doubt. A failed write reports itself on
|
|
29
|
+
the button rather than looking like it worked.
|
|
@@ -2350,6 +2350,9 @@ function serverSpamVerdict(input) {
|
|
|
2350
2350
|
const a = analyzeServerSpam(input);
|
|
2351
2351
|
if (!a || !a.flagged)
|
|
2352
2352
|
return null;
|
|
2353
|
+
const trustedAndProved = input.senderTrusted && a.proved;
|
|
2354
|
+
if (trustedAndProved && a.kind !== "forgery" && !a.authFailures.length)
|
|
2355
|
+
return null;
|
|
2353
2356
|
const numbers = Number.isFinite(a.score) && Number.isFinite(a.threshold) ? `SpamAssassin score ${a.score} of ${a.threshold}` : "flagged by SpamAssassin";
|
|
2354
2357
|
const why = a.reasons.length ? ` \u2014 ${a.reasons.join("; ")}` : "";
|
|
2355
2358
|
const bayes = a.bayesHam ? "; your own trained filter puts it at 0-1% spam (BAYES_00)" : "";
|
|
@@ -2375,6 +2378,13 @@ function serverSpamVerdict(input) {
|
|
|
2375
2378
|
detail: `${numbers}${why}${bayes}`
|
|
2376
2379
|
};
|
|
2377
2380
|
const proof = a.proved ? `${provedNote(a)} ` : "";
|
|
2381
|
+
if (input.senderTrusted && !a.proved)
|
|
2382
|
+
return {
|
|
2383
|
+
id: "server-spam-verdict",
|
|
2384
|
+
severity: "caution",
|
|
2385
|
+
text: "This claims to be a sender you trust, but nothing proves it is.",
|
|
2386
|
+
detail: `No DMARC pass, no valid signature from the sending domain, and it passed through hosts your server does not trust. ${numbers}${why}`
|
|
2387
|
+
};
|
|
2378
2388
|
return {
|
|
2379
2389
|
id: "server-spam-verdict",
|
|
2380
2390
|
severity: "caution",
|
|
@@ -2534,6 +2544,7 @@ function spamScoreOf(input) {
|
|
|
2534
2544
|
kind: a.kind,
|
|
2535
2545
|
proved: a.proved,
|
|
2536
2546
|
provedBy: a.provedBy,
|
|
2547
|
+
trusted: !!input.senderTrusted && a.proved && a.kind !== "forgery" && !a.authFailures.length,
|
|
2537
2548
|
reasons: a.reasons
|
|
2538
2549
|
};
|
|
2539
2550
|
}
|
|
@@ -7002,6 +7013,31 @@ var WebMailxService = class _WebMailxService {
|
|
|
7002
7013
|
});
|
|
7003
7014
|
return { flagged };
|
|
7004
7015
|
}
|
|
7016
|
+
/** Trust (or untrust) a sender / domain for the spam banner ONLY — no
|
|
7017
|
+
* remote content. Mirrors MailxService.trustSenderOrDomain; the desktop
|
|
7018
|
+
* and Android halves must answer "is this sender trusted" the same way or
|
|
7019
|
+
* the same message reads differently on the phone. */
|
|
7020
|
+
async trustSenderOrDomain(type, value) {
|
|
7021
|
+
const v = (value || "").trim().toLowerCase();
|
|
7022
|
+
if (!v)
|
|
7023
|
+
return { trusted: false };
|
|
7024
|
+
let trusted = false;
|
|
7025
|
+
await updateAllowlist((list) => {
|
|
7026
|
+
const key = type === "sender" ? "trustedSenders" : "trustedDomains";
|
|
7027
|
+
const arr = Array.isArray(list[key]) ? list[key] : [];
|
|
7028
|
+
const idx = arr.findIndex((x) => (x || "").toLowerCase() === v);
|
|
7029
|
+
if (idx >= 0) {
|
|
7030
|
+
arr.splice(idx, 1);
|
|
7031
|
+
trusted = false;
|
|
7032
|
+
} else {
|
|
7033
|
+
arr.push(v);
|
|
7034
|
+
trusted = true;
|
|
7035
|
+
}
|
|
7036
|
+
list[key] = arr;
|
|
7037
|
+
return list;
|
|
7038
|
+
});
|
|
7039
|
+
return { trusted };
|
|
7040
|
+
}
|
|
7005
7041
|
async updateFlags(accountId, uid, flags) {
|
|
7006
7042
|
const envelope = this.db.getMessageByUid(accountId, uid);
|
|
7007
7043
|
await this.syncManager.updateFlagsLocal(accountId, uid, envelope?.folderId || 0, flags);
|
|
@@ -7018,7 +7054,9 @@ var WebMailxService = class _WebMailxService {
|
|
|
7018
7054
|
domains: list.domains || [],
|
|
7019
7055
|
recipients: list.recipients || [],
|
|
7020
7056
|
flaggedSenders: list.flaggedSenders || [],
|
|
7021
|
-
flaggedDomains: list.flaggedDomains || []
|
|
7057
|
+
flaggedDomains: list.flaggedDomains || [],
|
|
7058
|
+
trustedSenders: list.trustedSenders || [],
|
|
7059
|
+
trustedDomains: list.trustedDomains || []
|
|
7022
7060
|
};
|
|
7023
7061
|
}
|
|
7024
7062
|
async allowRemoteContent(type, value) {
|
|
@@ -12487,6 +12525,9 @@ function installBridge() {
|
|
|
12487
12525
|
return { ok: true };
|
|
12488
12526
|
},
|
|
12489
12527
|
getAllowlist: () => service.getAllowlist(),
|
|
12528
|
+
trustSenderOrDomain: async (type, value) => {
|
|
12529
|
+
return await service.trustSenderOrDomain(type, value);
|
|
12530
|
+
},
|
|
12490
12531
|
flagSenderOrDomain: async (type, value) => {
|
|
12491
12532
|
return await service.flagSenderOrDomain(type, value);
|
|
12492
12533
|
},
|