Начало работы

Spam Scanner требует Node.js 18 или новее, а с автономным исполняемым файлом не требует ничего.

Установка#

Как инструмент командной строки:

Shell
npm install --global spamscanner
spamscanner version

Как библиотека в проекте на Node.js:

Shell
npm install spamscanner

Как автономный исполняемый файл для Linux или macOS со встроенными Node.js и моделью:

Shell
curl -fsSL https://github.com/spamscanner/spamscanner/releases/latest/download/install.sh | bash

Исполняемые файлы для Linux (x64 и arm64), macOS (Intel и Apple silicon) и Windows прикреплены к каждому релизу.

Проверка письма#

Сохраните письмо в файл (в большинстве почтовых программ это называется «Сохранить как» или «Показать оригинал») и проверьте его:

Shell
spamscanner scan message.eml
Text
SPAM  score 16.3 (spam at 5.0, reject at 15.0)  action: reject  language: en
     +6.3  BAYES_999                    Classifier spam probability 99.9%
     +5.0  PHISHING_LOOKALIKE_DOMAIN    "paypa1-secure.top" imitates paypal by swapping characters
     +3.0  DECEPTIVE_LINK               A link shows "https://www.paypal.com/signin" but goes to paypa1-secure.top
     +2.0  FROM_NAME_BRAND              Display name says "paypal" but the message is from paypa1-secure.top

Код выхода равен 0 для hamНужная почта: противоположность спама., 1 для спама и 2 при ошибке, поэтому скрипты могут использовать его напрямую. --json выводит полный результат, а --headers выводит письмо с добавленными заголовками X-Spam-*.

Письма также можно передавать через стандартный ввод:

Shell
cat message.eml | spamscanner scan -

Использование из Node.js#

JavaScript
import SpamScanner from 'spamscanner';
import {readFile} from 'node:fs/promises';

const scanner = new SpamScanner();
const result = await scanner.scan(await readFile('message.eml'));

console.log(result.isSpam, result.score, result.action);
for (const test of result.tests) {
  console.log(test.name, test.score, test.description);
}

CommonJS тоже работает:

JavaScript
const SpamScanner = require('spamscanner');

scan() принимает исходное письмо как Buffer, строку, Uint8Array или поток для чтения. Строка всегда считается текстом письма: Spam Scanner никогда не читает файл только потому, что строка похожа на путь. Для файлов используйте scanner.scanFile(path).

Сведения об SMTP-сессии#

IP-адрес клиента, его проверенное имя хоста, имя из HELO и конверт делают результат точнее: аутентификации нужен IP-адрес, а правилу о подделке собственного домена нужны получатели.

JavaScript
const result = await scanner.scan(raw, {
  session: {
    remoteAddress: '203.0.113.5',
    resolvedClientHostname: 'mail.example.com',
    helo: 'mail.example.com',
    envelope: {
      mailFrom: {address: 'alice@example.com'},
      rcptTo: [{address: 'bob@example.org'}],
    },
  },
});

То же из командной строки:

Shell
spamscanner scan message.eml --ip 203.0.113.5 --helo mail.example.com \
  --from alice@example.com --to bob@example.org --auth

Дополнительные проверки#

Ни одна из них не включена по умолчанию, потому что каждой нужен сервис или решение:

ПроверкаПараметр библиотекиКомандная строка
SPF, DKIM, DMARC, ARCauthentication: true--auth
Чёрный список IPdnsbl: {ip: ['zen.spamhaus.org']}--dnsbl zen.spamhaus.org
Чёрный список доменов для ссылокdnsbl: {domain: ['dbl.spamhaus.org']}--uribl dbl.spamhaus.org
ClamAVclamav: true или clamav: {socket}--clamav [socket]
Языковая модельllm: {provider: 'ollama', model: 'qwen3.5:4b'}--llm ollama
Белые и чёрные спискиallowlist: [...], denylist: [...]--allowlist, --denylist

Фильтрующие резолверы Cloudflare (1.1.1.2 для вредоносных программ, 1.1.1.3 для контента для взрослых) по умолчанию получают запросы о хостах из ссылок. Это отключается через phishing: {cloudflare: false} или --no-cloudflare. Что покидает машину

Spamhaus и некоторые другие чёрные списки не отвечают на запросы через публичные резолверы, такие как 8.8.8.8 или 1.1.1.1. Используйте их с локальным кеширующим резолвером и проверьте их условия использования для вашего объёма почты.

Дальнейшие шаги#

Редактировать эту страницу на GitHub · Markdown ·