spamscanner 7.0.12 → 7.0.14
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/dist/cjs/index.cjs +66 -25
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/esm/cli.js +65 -24
- package/dist/esm/cli.js.map +2 -2
- package/dist/esm/index.js +65 -24
- package/dist/esm/index.js.map +2 -2
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -5695,8 +5695,8 @@ var MAX_EMBEDDED_LENGTH = 10 * 1024 * 1024;
|
|
|
5695
5695
|
var MAX_ATTACHED = 100;
|
|
5696
5696
|
var MAX_ATTACHED_BYTES = 50 * 1024 * 1024;
|
|
5697
5697
|
var MAX_READ_TIME = 5e3;
|
|
5698
|
-
var MAX_CARD_BYTES = 4 * 1024 * 1024;
|
|
5699
5698
|
var MAX_SHOWN_BYTES = 1024 * 1024;
|
|
5699
|
+
var MAX_CARD_TEXT = 8 * 1024 * 1024;
|
|
5700
5700
|
function isHostCode2(code) {
|
|
5701
5701
|
return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 45 || code === 46;
|
|
5702
5702
|
}
|
|
@@ -5816,9 +5816,22 @@ function* attributesOf(html) {
|
|
|
5816
5816
|
}
|
|
5817
5817
|
}
|
|
5818
5818
|
var MAX_VALUE2 = 1024 * 1024;
|
|
5819
|
+
var MAX_REFERENCES = 64 * 1024;
|
|
5820
|
+
function isCut(value) {
|
|
5821
|
+
if (value.length <= MAX_VALUE2) {
|
|
5822
|
+
return false;
|
|
5823
|
+
}
|
|
5824
|
+
let references = 0;
|
|
5825
|
+
for (let index = value.indexOf("&"); index !== -1; index = value.indexOf("&", index + 1)) {
|
|
5826
|
+
if (++references > MAX_REFERENCES) {
|
|
5827
|
+
return true;
|
|
5828
|
+
}
|
|
5829
|
+
}
|
|
5830
|
+
return false;
|
|
5831
|
+
}
|
|
5819
5832
|
var LONG_VALUE = 64 * 1024;
|
|
5820
5833
|
function linksOf(name, value, { add, embed, cut }) {
|
|
5821
|
-
if (value
|
|
5834
|
+
if (isCut(value)) {
|
|
5822
5835
|
cut();
|
|
5823
5836
|
value = value.slice(0, MAX_VALUE2);
|
|
5824
5837
|
}
|
|
@@ -6241,14 +6254,27 @@ function quotedPrintableValues(text) {
|
|
|
6241
6254
|
}
|
|
6242
6255
|
return out.join("\n");
|
|
6243
6256
|
}
|
|
6244
|
-
function
|
|
6257
|
+
function hasQuotedPrintable(text) {
|
|
6258
|
+
const unfolded = text.replaceAll(FOLD, "");
|
|
6259
|
+
if (!/quoted-printable/i.test(unfolded)) {
|
|
6260
|
+
return false;
|
|
6261
|
+
}
|
|
6262
|
+
return unfolded.split(LINE_BREAK).some((line) => {
|
|
6263
|
+
const colon = valueColon(line);
|
|
6264
|
+
return colon !== -1 && QUOTED_PRINTABLE.test(line.slice(0, colon));
|
|
6265
|
+
});
|
|
6266
|
+
}
|
|
6267
|
+
function shownText(text, full = true) {
|
|
6245
6268
|
const unfolded = text.replaceAll(FOLD, "");
|
|
6246
6269
|
const shown = /* @__PURE__ */ new Set([text, readEscapes(unfolded)]);
|
|
6247
|
-
|
|
6248
|
-
if (
|
|
6249
|
-
|
|
6250
|
-
if (
|
|
6251
|
-
shown.add(
|
|
6270
|
+
let decoded = unfolded;
|
|
6271
|
+
if (full) {
|
|
6272
|
+
decoded = quotedPrintableValues(unfolded);
|
|
6273
|
+
if (decoded !== unfolded) {
|
|
6274
|
+
shown.add(readEscapes(decoded));
|
|
6275
|
+
if (unfolded !== text) {
|
|
6276
|
+
shown.add(quotedPrintableValues(text));
|
|
6277
|
+
}
|
|
6252
6278
|
}
|
|
6253
6279
|
}
|
|
6254
6280
|
if (/\\[^nN,;\\]/.test(decoded)) {
|
|
@@ -6281,40 +6307,50 @@ function htmlDescriptions(text) {
|
|
|
6281
6307
|
return html.join("\n");
|
|
6282
6308
|
}
|
|
6283
6309
|
var BINARY = /;\s*(?:(?:encoding\s*=\s*)?"?(?:b|base64)"?|value\s*=\s*"?binary"?)\s*(?:;|$)/i;
|
|
6284
|
-
function withoutBinaryValues(text) {
|
|
6310
|
+
function withoutBinaryValues(text, limit = Number.POSITIVE_INFINITY) {
|
|
6285
6311
|
if (!/base64|binary|encoding\s*=\s*"?b|;\s*b\s*[;:]/i.test(text)) {
|
|
6286
6312
|
return text;
|
|
6287
6313
|
}
|
|
6288
6314
|
const lines2 = text.split(LINE_BREAK);
|
|
6289
6315
|
const out = [];
|
|
6316
|
+
let length = 0;
|
|
6317
|
+
const push = (line) => {
|
|
6318
|
+
out.push(line);
|
|
6319
|
+
length += line.length + 1;
|
|
6320
|
+
};
|
|
6290
6321
|
for (let i = 0; i < lines2.length; i++) {
|
|
6322
|
+
if (length > limit) {
|
|
6323
|
+
break;
|
|
6324
|
+
}
|
|
6291
6325
|
const line = lines2[i];
|
|
6292
6326
|
const colon = valueColon(line);
|
|
6293
6327
|
if (colon === -1 || !BINARY.test(line.slice(0, colon))) {
|
|
6294
|
-
|
|
6328
|
+
push(line);
|
|
6295
6329
|
continue;
|
|
6296
6330
|
}
|
|
6297
|
-
|
|
6331
|
+
let base64 = /^[\w+/=\s]*$/.test(line.slice(colon + 1));
|
|
6298
6332
|
let next = i + 1;
|
|
6299
6333
|
while (next < lines2.length && (lines2[next].startsWith(" ") || lines2[next].startsWith(" "))) {
|
|
6300
|
-
|
|
6334
|
+
base64 &&= /^[\w+/=\s]*$/.test(lines2[next]);
|
|
6335
|
+
next++;
|
|
6301
6336
|
}
|
|
6302
|
-
if (!
|
|
6337
|
+
if (!base64) {
|
|
6303
6338
|
for (let index = i; index < next; index++) {
|
|
6304
|
-
|
|
6339
|
+
push(lines2[index]);
|
|
6305
6340
|
}
|
|
6306
6341
|
i = next - 1;
|
|
6307
6342
|
continue;
|
|
6308
6343
|
}
|
|
6309
6344
|
while (next < lines2.length && lines2[next] !== "" && /^[\w+/=]+$/.test(lines2[next])) {
|
|
6310
|
-
|
|
6345
|
+
next++;
|
|
6311
6346
|
}
|
|
6347
|
+
const end = next;
|
|
6312
6348
|
if (next < lines2.length && lines2[next] === "") {
|
|
6313
6349
|
next++;
|
|
6314
6350
|
}
|
|
6315
|
-
i = next - 1;
|
|
6316
6351
|
const name = line.slice(0, colon).split(";")[0].split(".").pop().trim().toLowerCase();
|
|
6317
|
-
|
|
6352
|
+
push(MEDIA_PROPERTIES.has(name) ? line.slice(0, colon + 1) : line.slice(0, colon + 1) + Buffer7.from([line.slice(colon + 1), ...lines2.slice(i + 1, end)].join("").replaceAll(/\s/g, ""), "base64").toString("utf8"));
|
|
6353
|
+
i = next - 1;
|
|
6318
6354
|
}
|
|
6319
6355
|
return out.join("\n");
|
|
6320
6356
|
}
|
|
@@ -6399,16 +6435,20 @@ function* documentsOf(attachments, state, late) {
|
|
|
6399
6435
|
yield { text };
|
|
6400
6436
|
continue;
|
|
6401
6437
|
}
|
|
6402
|
-
let readable = withoutBinaryValues(text
|
|
6403
|
-
if (
|
|
6438
|
+
let readable = withoutBinaryValues(text, MAX_CARD_TEXT);
|
|
6439
|
+
if (readable.length > MAX_CARD_TEXT) {
|
|
6440
|
+
state.tooComplex = true;
|
|
6441
|
+
readable = readable.slice(0, MAX_CARD_TEXT);
|
|
6442
|
+
}
|
|
6443
|
+
const full = readable.length <= MAX_SHOWN_BYTES;
|
|
6444
|
+
if (!full && hasQuotedPrintable(readable)) {
|
|
6404
6445
|
state.tooComplex = true;
|
|
6405
|
-
readable = readable.slice(0, MAX_SHOWN_BYTES);
|
|
6406
6446
|
}
|
|
6407
6447
|
if (late()) {
|
|
6408
6448
|
state.incomplete = true;
|
|
6409
6449
|
return;
|
|
6410
6450
|
}
|
|
6411
|
-
yield { text: shownText(readable) };
|
|
6451
|
+
yield { text: shownText(readable, full) };
|
|
6412
6452
|
if (late()) {
|
|
6413
6453
|
state.incomplete = true;
|
|
6414
6454
|
return;
|
|
@@ -6597,10 +6637,11 @@ function carriedLinkHosts(mail, {
|
|
|
6597
6637
|
if (done() || spend(link.length)) {
|
|
6598
6638
|
break;
|
|
6599
6639
|
}
|
|
6600
|
-
|
|
6640
|
+
const cut = isCut(link);
|
|
6641
|
+
if (cut) {
|
|
6601
6642
|
state.tooComplex = true;
|
|
6602
6643
|
}
|
|
6603
|
-
add(decodeEntities(link.slice(0, MAX_VALUE2), { attribute: true }));
|
|
6644
|
+
add(decodeEntities(cut ? link.slice(0, MAX_VALUE2) : link, { attribute: true }));
|
|
6604
6645
|
}
|
|
6605
6646
|
}
|
|
6606
6647
|
for (const chunk2 of chunksOf(text)) {
|
|
@@ -8278,7 +8319,7 @@ function scoreResults(results, options) {
|
|
|
8278
8319
|
var package_default = {
|
|
8279
8320
|
name: "spamscanner",
|
|
8280
8321
|
description: "Spam, phishing and malware filter for email in any language: a trainable classifier, link and attachment checks, SPF/DKIM/DMARC, and an optional AI second opinion from any LLM, including local Ollama models. Works as a library, CLI, Postfix milter or HTTP API.",
|
|
8281
|
-
version: "7.0.
|
|
8322
|
+
version: "7.0.14",
|
|
8282
8323
|
author: "Forward Email (https://forwardemail.net)",
|
|
8283
8324
|
bin: {
|
|
8284
8325
|
spamscanner: "./dist/esm/cli.js"
|