
Spam Scanner is a Node.js anti-spam, email filtering, and phishing prevention tool and service. Built for @ladjs, @forwardemail, @cabinjs, @breejs, and @lassjs.
A spam filter for Node.js, the command line and mail servers. It catches spam, phishing, scams and malware in any language, explains every decision, and can ask a language model about close calls.
spamscanner.net · Getting started · Documentation
v1agra spellings and styled letters are undone before counting. Links, senders, HTML and attachments count too, not only words.pаypal.com with a Cyrillic а, paypa1.com, punycode), links whose text shows another address, brand names in display names, and Cloudflare's malware and adult-content resolvers..pdf; double extensions; right-to-left filename tricks; executables in ZIP files; Office macros; active PDFs; and ClamAV.X-Spam-* headers.npm install --global spamscanner # the command line
npm install spamscanner # the library
Or a standalone binary, with nothing else to install:
curl -fsSL https://github.com/spamscanner/spamscanner/releases/latest/download/install.sh | bash
The package needs Node.js 18 or later.
spamscanner scan message.eml
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
import SpamScanner from 'spamscanner';
const scanner = new SpamScanner();
const result = await scanner.scan(rawMessage, {
session: {remoteAddress: '203.0.113.5', envelope: {rcptTo: [{address: '[email protected]'}]}},
});
result.isSpam; // true
result.action; // 'accept', 'tag' or 'reject'
result.tests; // [{name: 'DECEPTIVE_LINK', score: 3, description: '...'}, ...]
With Postfix:
spamscanner milter --port 7831 --auth --subject-tag "[SPAM]"
sudo postconf -e smtpd_milters=inet:127.0.0.1:7831 milter_default_action=accept
sudo postfix reload
With a local language model:
ollama pull qwen3.5:4b
spamscanner scan message.eml --llm ollama --llm-model qwen3.5:4b
The same pages are in docs/ in this repository. The website and documentation are also in 24 other languages; see i18n/.
npm install
npm test # lint, build, and every test, with 100% coverage required
npm run test:e2e # end-to-end tests against Postfix, ClamAV, spamc and Ollama; see test/e2e/
npm run model:train # rebuild the bundled model from public datasets
npm run site:build # build spamscanner.net into _site/
npm run site:serve # preview it at http://localhost:8080
npm run i18n:check # check the translations against the English pages