@bobfrankston/mailx-store 0.1.93 → 0.1.97
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 +5 -5
- package/store.d.ts +4 -1
- package/store.js +17 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx-store",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.97",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@bobfrankston/mailx-types": "^0.1.
|
|
13
|
-
"@bobfrankston/mailx-settings": "^0.1.
|
|
12
|
+
"@bobfrankston/mailx-types": "^0.1.65",
|
|
13
|
+
"@bobfrankston/mailx-settings": "^0.1.63",
|
|
14
14
|
"@bobfrankston/mailx-bus": "^0.1.2",
|
|
15
15
|
"mailparser": "^3.7.2"
|
|
16
16
|
},
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
".transformedSnapshot": {
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@bobfrankston/mailx-types": "^0.1.
|
|
33
|
-
"@bobfrankston/mailx-settings": "^0.1.
|
|
32
|
+
"@bobfrankston/mailx-types": "^0.1.65",
|
|
33
|
+
"@bobfrankston/mailx-settings": "^0.1.63",
|
|
34
34
|
"@bobfrankston/mailx-bus": "^0.1.2",
|
|
35
35
|
"mailparser": "^3.7.2"
|
|
36
36
|
}
|
package/store.d.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* be able to consume it without depending on mailx-service — that's the
|
|
20
20
|
* "arrow points the right way" property of the architecture.
|
|
21
21
|
*/
|
|
22
|
-
import { type TrustFinding } from "@bobfrankston/mailx-types";
|
|
22
|
+
import { type TrustFinding, type SpamScore } from "@bobfrankston/mailx-types";
|
|
23
23
|
import type { ParsedInvite } from "@bobfrankston/mailx-types";
|
|
24
24
|
import { MailxDB } from "./db.js";
|
|
25
25
|
import { FileMessageStore } from "./file-store.js";
|
|
@@ -57,6 +57,9 @@ export interface StoreMessage extends MessageEnvelope {
|
|
|
57
57
|
/** Evidence that this message is forged — empty for ordinary mail. See
|
|
58
58
|
* assessMessageTrust; the viewer renders these above the body. */
|
|
59
59
|
trust: TrustFinding[];
|
|
60
|
+
/** The receiving server SpamAssassin score, present or not, flagged or
|
|
61
|
+
* not. Shown as a badge so a below-threshold score is still visible. */
|
|
62
|
+
spamScore: SpamScore;
|
|
60
63
|
listUnsubscribe: string;
|
|
61
64
|
listUnsubscribeMail: string;
|
|
62
65
|
listUnsubscribeHttp: string;
|
package/store.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import * as fs from "node:fs";
|
|
23
23
|
import { parseSerial } from "./parse-serial.js";
|
|
24
|
-
import { assessMessageTrust } from "@bobfrankston/mailx-types";
|
|
24
|
+
import { assessMessageTrust, spamScoreOf } from "@bobfrankston/mailx-types";
|
|
25
25
|
import { parseInvite } from "@bobfrankston/mailx-types";
|
|
26
26
|
import { storeBus } from "./bus.js";
|
|
27
27
|
import { sanitizeHtml, htmlToPlainText } from "@bobfrankston/mailx-types";
|
|
@@ -543,12 +543,24 @@ export class Store {
|
|
|
543
543
|
// needs no configuration and it is exactly the address a self-spoof
|
|
544
544
|
// forges, so an alias the user never got round to listing is still
|
|
545
545
|
// covered. (Claude Code 2026-08-25)
|
|
546
|
-
const
|
|
547
|
-
|
|
546
|
+
const trustHeaderLines = (parsed.headerLines || []).map(h => ({ key: h.key, line: h.line }));
|
|
547
|
+
const trustInput = {
|
|
548
|
+
headerLines: trustHeaderLines,
|
|
548
549
|
fromAddress: envelope.from?.address || "",
|
|
549
550
|
ownAddresses: [...recipients, (deliveredTo.match(/[^\s<>]+@[^\s<>]+/) || [""])[0]].filter(Boolean),
|
|
550
551
|
bodyHtml,
|
|
551
|
-
|
|
552
|
+
bodyText,
|
|
553
|
+
};
|
|
554
|
+
const trust = assessMessageTrust(trustInput);
|
|
555
|
+
// The server's score travels separately from the findings: a finding is
|
|
556
|
+
// an accusation and fires only on evidence, this is a measurement the
|
|
557
|
+
// reader asked to see either way (Bob 2026-08-25). A 2.7 against a 4.5
|
|
558
|
+
// threshold is "did not quite trip the wire", which is not the same
|
|
559
|
+
// thing as clean — and that is exactly the message that got through.
|
|
560
|
+
// Same input as the findings, so the chip and the banner are computed
|
|
561
|
+
// from one analysis and cannot contradict each other about whether the
|
|
562
|
+
// sender was proved. (Claude Code 2026-08-27)
|
|
563
|
+
const spamScore = spamScoreOf(trustInput);
|
|
552
564
|
if (bodyHtml && !allowRemote) {
|
|
553
565
|
const result = sanitizeHtml(bodyHtml);
|
|
554
566
|
bodyHtml = result.html;
|
|
@@ -560,7 +572,7 @@ export class Store {
|
|
|
560
572
|
hasRemoteContent, remoteAllowed: allowRemote,
|
|
561
573
|
attachments,
|
|
562
574
|
cached: true,
|
|
563
|
-
deliveredTo, returnPath, trust,
|
|
575
|
+
deliveredTo, returnPath, trust, spamScore,
|
|
564
576
|
listUnsubscribe, listUnsubscribeMail, listUnsubscribeHttp, listUnsubscribeOneClick,
|
|
565
577
|
// body_path in the DB is stored relative to the body-store
|
|
566
578
|
// basePath; resolve to absolute so the UI's "Source" button
|