@bobfrankston/mailx-types 0.1.65 → 0.1.67
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 +1 -1
- package/trust.js +43 -4
package/package.json
CHANGED
package/trust.js
CHANGED
|
@@ -242,6 +242,28 @@ function analyzeServerSpam(input) {
|
|
|
242
242
|
: present("other") ? "unclassified"
|
|
243
243
|
: rules.length ? "bulk"
|
|
244
244
|
: "unclassified";
|
|
245
|
+
// Two proofs SpamAssassin states in its own rule list, which mail that
|
|
246
|
+
// never crossed a trust boundary carries INSTEAD of an Authentication-Results
|
|
247
|
+
// header — Bob's own message to John Levine about spam handling, 2026-08-27,
|
|
248
|
+
// had neither AR nor DMARC and got a caution banner reading "links and
|
|
249
|
+
// attachments here should not be opened" on prose he had just written:
|
|
250
|
+
//
|
|
251
|
+
// ALL_TRUSTED Passed through trusted hosts only via SMTP
|
|
252
|
+
// DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain
|
|
253
|
+
//
|
|
254
|
+
// DKIM_VALID_AU is the same evidence DMARC alignment rests on — the author
|
|
255
|
+
// domain signed it and the signature verified — so it proves the From line on
|
|
256
|
+
// its own. ALL_TRUSTED says the message reached the mailbox without passing
|
|
257
|
+
// through a host the server distrusts, which is Bob's own authenticated
|
|
258
|
+
// submission; nothing could have injected it in transit. (What flagged his
|
|
259
|
+
// message was URIBL_DBL_SPAM 8.0 on blueorchestra.org — the domain he was
|
|
260
|
+
// quoting IN a discussion about spam. Guilt by association at its purest.)
|
|
261
|
+
const has = (name) => rules.some(r => r.name === name);
|
|
262
|
+
const provedBy = dmarc.pass ? "dmarc"
|
|
263
|
+
: has("DKIM_VALID_AU") ? "dkim"
|
|
264
|
+
: has("ALL_TRUSTED") ? "trusted"
|
|
265
|
+
: "";
|
|
266
|
+
const fromDomain = (bare(input.fromAddress).split("@")[1] || "").toLowerCase();
|
|
245
267
|
const reasons = rules
|
|
246
268
|
.filter(r => r.cls !== "neutral" && scored(r))
|
|
247
269
|
.sort((a, b) => (b.score || 0) - (a.score || 0))
|
|
@@ -252,7 +274,8 @@ function analyzeServerSpam(input) {
|
|
|
252
274
|
});
|
|
253
275
|
return {
|
|
254
276
|
score, threshold, flagged, rules, kind,
|
|
255
|
-
proved:
|
|
277
|
+
proved: !!provedBy, provedBy,
|
|
278
|
+
provedDomain: dmarc.domain || fromDomain, provedPolicy: dmarc.policy,
|
|
256
279
|
bayesHam: rules.some(r => r.name === "BAYES_00" || r.name === "BAYES_01"),
|
|
257
280
|
authFailures: dmarc.authFailures,
|
|
258
281
|
reasons,
|
|
@@ -282,6 +305,20 @@ function analyzeServerSpam(input) {
|
|
|
282
305
|
* cannot classify, which is never a
|
|
283
306
|
* reason to go quiet.
|
|
284
307
|
*/
|
|
308
|
+
/** How the From line was proved, in the reader's terms — named so it can be
|
|
309
|
+
* checked against the headers rather than believed. */
|
|
310
|
+
function provedNote(a) {
|
|
311
|
+
switch (a.provedBy) {
|
|
312
|
+
case "dmarc":
|
|
313
|
+
return `DMARC pass, aligned${a.provedPolicy ? `, policy ${a.provedPolicy}` : ""}.`;
|
|
314
|
+
case "dkim":
|
|
315
|
+
return `Valid signature from ${a.provedDomain}, the sending domain itself (DKIM_VALID_AU).`;
|
|
316
|
+
case "trusted":
|
|
317
|
+
return "It passed through trusted hosts only (ALL_TRUSTED) — nothing untrusted handled it.";
|
|
318
|
+
default:
|
|
319
|
+
return "";
|
|
320
|
+
}
|
|
321
|
+
}
|
|
285
322
|
function serverSpamVerdict(input) {
|
|
286
323
|
const a = analyzeServerSpam(input);
|
|
287
324
|
if (!a || !a.flagged)
|
|
@@ -304,8 +341,10 @@ function serverSpamVerdict(input) {
|
|
|
304
341
|
return {
|
|
305
342
|
id: "server-spam-verdict",
|
|
306
343
|
severity: "info",
|
|
307
|
-
text:
|
|
308
|
-
|
|
344
|
+
text: a.provedBy === "trusted"
|
|
345
|
+
? "Your mail server scored this as spam, but it reached you without leaving your own systems."
|
|
346
|
+
: `Your mail server scored this as spam, but ${a.provedDomain} proved it sent this.`,
|
|
347
|
+
detail: `${provedNote(a)} ${numbers}${why}${bayes}`,
|
|
309
348
|
};
|
|
310
349
|
if (a.kind === "bulk")
|
|
311
350
|
return {
|
|
@@ -314,7 +353,7 @@ function serverSpamVerdict(input) {
|
|
|
314
353
|
text: "Your mail server rates this bulk mail — nothing that scored tests who sent it.",
|
|
315
354
|
detail: `${numbers}${why}${bayes}`,
|
|
316
355
|
};
|
|
317
|
-
const proof = a.proved ? `${a
|
|
356
|
+
const proof = a.proved ? `${provedNote(a)} ` : "";
|
|
318
357
|
return {
|
|
319
358
|
id: "server-spam-verdict",
|
|
320
359
|
severity: "caution",
|