Een spamfilter dat elke taal leest en elke beslissing uitlegt.
Spam Scanner vangt spam, phishing, oplichting en malware voor Node.js, de opdrachtregel en mailservers zoals Postfix, Exim en Haraka. Elk resultaat noemt de tests die afgingen en waarom.
npm install -g spamscanner
Aan de slagBekijk de video (1:58)
- Node.js 18+
- Milter, spamd, HTTP
- Ollama, Claude, ChatGPT
- Geen telemetrie
$ 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 $ echo $? 1
Hoe een bericht wordt beoordeeld
Elke controle voegt punten toe of trekt ze af, en het totaal beslist. Drempels en punten zijn aan te passen en niets is een black box: het resultaat noemt elke test.
Lezen
Het bericht wordt geparsed en de tekst genormaliseerd: opgemaakte letters, onzichtbare tekens en lookalike-alfabetten worden ongedaan gemaakt.
Controleren
De classifier en de controles op links, bijlagen, authenticatie, blocklists en regels draaien tegelijk, elk met een time-out.
Score
Elke test voegt punten toe of trekt ze af. Bij 5 is een bericht spam; bij 15 hoort een mailserver het te weigeren.
Vragen
Twijfelgevallen kunnen naar een taalmodel gaan, dat tot 6 punten toevoegt of tot 3 aftrekt.
- onder 5accepteren
- 5 tot 15als spam markeren
- 15 en hogerweigeren
Wat het controleert
Woorden zijn één signaal. Links, afzenders, bijlagen en authenticatie zeggen evenveel, en geen daarvan hangt af van de taal van het bericht.
Een classifier voor elk schrift
Woorden, woordparen, links, afzenders, HTML en bijlagen, geteld en gecombineerd zoals SpamBayes dat doet, met een eerlijk „onzeker” als de aanwijzingen elkaar tegenspreken.
Hoe het beslistElke taal, zorgvuldig
Unicode-woordsegmentatie voor Chinees, Japans en Thai, vermommingen ongedaan gemaakt, en geen straf voor een taal waarin het model weinig ham zag.
TalenPhishing
Lookalike-domeinen met Cyrillische of verwisselde letters, links waarvan de tekst een ander adres toont, merknamen in weergavenamen en de malware-resolver van Cloudflare.
Controles op phishingBijlagen
Uitvoerbare bestanden herkend aan hun bytes, ook als ze hernoemd zijn naar .pdf; dubbele extensies; programma's in ZIP-bestanden; Office-macro's; actieve pdf's; ClamAV.
Controles op bijlagenAuthenticatie
SPF, DKIM, DMARC en ARC, DNS-blocklists, allow- en denylists, en een regel voor mail die je eigen domein vervalst.
AuthenticatieTaalmodellen
Twijfelgevallen gaan naar een model: Ollama op je eigen machine, of Claude, ChatGPT, Gemini en elke met OpenAI compatibele server.
Taalmodellen
Elke taal, zonder te gokken
Woorden worden gevonden met de Unicode-regels, zodat talen die zonder spaties worden geschreven werken, en vermommingen worden ongedaan gemaakt voor het tellen. Dit zijn de woorden die de classifier telt, berekend toen deze pagina werd gebouwd.
Een taal waarin het meegeleverde model weinig ham zag, krijgt „onzeker” in plaats van „spam”, zodat gewone mail in het Arabisch of Koreaans nooit om het schrift wordt gemarkeerd. Talen
Claim your fr␣ee prіze: V1agra 𝐅𝐑𝐄𝐄
- claim
- your
- free
- prize
- viagra
- free
Een spatie zonder breedte, een Cyrillische і, een cijfer in plaats van een letter en wiskundige vette letters
恭喜您获得一百万元大奖
- 恭喜
- 您
- 获得
- 一
- 百万
- 元
- 大奖
Gesegmenteerd met een woordenboek
ยินดีด้วยคุณได้รับรางวัลหนึ่งล้านบาท
- ยินดี
- ด้วย
- คุณ
- ได้
- รับ
- รางวัล
- หนึ่ง
- ล้าน
- บาท
Gesegmenteerd met een woordenboek
Поздравляем! Вы выиграли миллион
- поздравляем
- вы
- выиграли
- миллион
Naar kleine letters volgens de Unicode-regels
Sluit aan op je mailserver
Een milter voor Postfix en Sendmail, een met SpamAssassin compatibele spamd-server voor spamc, Exim en Haraka, een contentfilter, een HTTP API, een TCP-server en de bibliotheek.
Ze voegen allemaal X-Spam-Flag, X-Spam-Score, X-Spam-Status-headers toe en verwijderen headers die een afzender heeft vervalst.
spamscanner milter --port 7831 --auth --subject-tag "[SPAM]"
# /etc/postfix/main.cf
smtpd_milters = inet:127.0.0.1:7831
milter_default_action = acceptEen milter controleert mail tijdens de SMTP-sessie, zodat spam op de weigerdrempel wordt geweigerd voordat hij wordt geaccepteerd. Handleiding Postfix
spamscanner spamd --port 783 --auth
spamc -c < message.eml # prints 16.3/5.0 and exits 1Een spamd-server die compatibel is met SpamAssassin: stop spamd, start Spam Scanner op dezelfde poort en SpamAssassin-clients blijven werken. handleiding spamd
import SpamScanner from 'spamscanner';
const scanner = new SpamScanner({authentication: true});
const result = await scanner.scan(stream, {session});
if (result.action === 'reject') {
// refuse with a 4xx or 5xx reply
}De bibliotheek, voor smtp-server, Haraka-plug-ins of elke dienst die mail verwerkt. API-referentie
spamscanner http --port 7832 --token "$TOKEN"
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
--data-binary @message.eml "http://127.0.0.1:7832/scan?ip=203.0.113.5"Voor elke programmeertaal en elke server die een HTTP-verzoek kan doen. Handleiding HTTP API
Een taalmodel voor de twijfelgevallen
Duidelijke spam en duidelijke ham komen er nooit langs. Als de score krap is of de classifier onzeker is, leest een model het bericht en antwoordt het met spam, phishing, oplichting, malware of ham. Draai er een op je eigen machine of gebruik een gehost model, met elke URL, poort en authenticatie.
Instructies voor AI-filters die in een bericht verborgen zijn, worden als spam gescoord, en het model krijgt te horen dat het bericht data is. De end-to-endtests controleren dit tegen een echt model via Ollama.
- Ollama
- LM Studio
- llama.cpp server
- vLLM
- LocalAI
- Jan
- OpenAI
- Anthropic (Claude)
- Google Gemini
- Mistral AI
- Groq
- OpenRouter
- DeepSeek
- xAI
- Together AI
- Fireworks AI
- Cerebras
- Hugging Face Inference Providers
- Azure OpenAI
- Cloudflare Clef
- Cloudflare Clef Flash
- TypeSafe Jev
- TypeSafe Jev on OpenRouter
- Any decision model server
ollama pull qwen3.5:4b
spamscanner llm-test --llm ollama --llm-model qwen3.5:4b
spamscanner milter --llm ollama --llm-model qwen3.5:4bOmlijnd: draait op je eigen machine. Persoonsgegevens worden verwijderd voordat een bericht naar een gehoste aanbieder gaat.
| Ollama | Licentie | Grootte |
|---|---|---|
qwen3.5:0.8b | Apache-2.0 | 1.3 GB |
gemma4:e2b | Apache-2.0 | 4.6 GB |
qwen3.5:4b | Apache-2.0 | 3.3 GB |
qwen3.5:9b | Apache-2.0 | 6.6 GB |
gpt-oss-safeguard:20b | Apache-2.0 | 14 GB |
Aanbevolen open modellen. Alle aanbevelingen
Gemeten en te trainen
Het meegeleverde model is getraind op openbare datasets en getest op berichten die het niet had gezien. Een model dat op je eigen mail is getraind, doet het beter: train het met mbox-bestanden, Maildirs of datasets, meet het en leer het bij via knoppen voor „spam melden”.
| Achtergehouden berichten | Berichten | Precisie | Recall | Fout-positieven |
|---|---|---|---|---|
| Engels | 6.564 | 100,0% | 97,1% | 0,0% |
| Russisch | 1.682 | 100,0% | 97,4% | 0,0% |
| Italiaans | 1.389 | 98,1% | 85,3% | 1,8% |
| Duits | 1.309 | 97,7% | 76,1% | 2,2% |
| Spaans | 1.281 | 97,5% | 82,6% | 2,6% |
| Alle | 13.840 | 99,2% | 85,1% | 0,6% |
Alleen de classifier, op elk tiende bericht van de openbare trainingsdata, achtergehouden. Onzekere berichten tellen als gemist. Duits, Italiaans en Spaans komen uit synthetische datasets met onbetrouwbare labels. Over het meegeleverde model
Gebouwd voor Forward Email
Forward Email bewaart geen logs van berichtinhoud en kon mail dus niet naar een externe filterdienst sturen. Spam Scanner draait op je eigen servers, stuurt nergens iets heen tenzij je dat instelt, en legt elke beslissing uit zonder dat iemand de mail leest. Forward Email en upgraden
Een project van Forward Email, de e-maildienst die privacy voorop stelt.
