能读懂所有语言、解释每一个判定的垃圾邮件过滤器。
Spam Scanner 为 Node.js、命令行以及 Postfix、Exim、Haraka 等邮件服务器识别垃圾邮件、钓鱼、诈骗和恶意软件。每个结果都会列出触发的测试及原因。
npm install -g spamscanner
- Node.js 18+
- Milter、spamd、HTTP
- Ollama, Claude, ChatGPT
- 无遥测
$ 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
如何判定一封邮件
每项检查都会加分或减分,由总分决定结果。阈值和分值都可以修改,没有任何黑箱:结果会列出每一项测试。
阅读
解析邮件并规范化文本:还原花式字母、不可见字符和形似字母。
检查
分类器、链接、附件、身份验证、黑名单和规则检查同时运行,每项都有超时。
分数
每项测试会加分或减分。达到 5 分即为垃圾邮件;达到 15 分时邮件服务器应当拒收。
询问
难以判断的邮件可以交给语言模型,最多加 6 分或减 3 分。
- 低于 5接收
- 5 到 15标记为垃圾邮件
- 15 及以上拒收
检查内容
词语只是一种信号。链接、发件人、附件和身份验证同样重要,而且都不依赖邮件的语言。
适用于所有文字的分类器
词语、词对、链接、发件人、HTML 和附件,按 SpamBayes 的方式统计和合并;线索相互矛盾时,如实给出“不确定”。
如何判定所有语言,审慎对待
对中文、日文和泰文进行 Unicode 分词,还原伪装,并且不惩罚模型很少见到其正常邮件的语言。
语言钓鱼
含西里尔字母或调换字母的仿冒域名,文字显示为另一个地址的链接,显示名称中的品牌,以及 Cloudflare 的恶意软件解析器。
钓鱼检查附件
按字节识别可执行文件,即使改名为 .pdf 也能识别;双重扩展名;ZIP 文件中的程序;Office 宏;含活动内容的 PDF;ClamAV。
附件检查身份验证
SPF、DKIM、DMARC 和 ARC,DNS 黑名单,允许列表和拒绝列表,以及针对冒充你自己域名的邮件的规则。
身份验证语言模型
难以判断的邮件交给模型:自己机器上的 Ollama,或 Claude、ChatGPT、Gemini 以及任何兼容 OpenAI 的服务器。
语言模型
所有语言,绝不猜测
按 Unicode 规则切分词语,因此不用空格的语言也能处理,伪装会在计数前还原。以下是分类器统计的词语,在构建本页时计算得出。
如果内置模型很少见到某种语言的 ham(正常邮件),该语言的邮件会得到“不确定”而不是“垃圾邮件”,因此阿拉伯语或韩语的普通邮件不会因为文字而被标记。 语言
Claim your fr␣ee prіze: V1agra 𝐅𝐑𝐄𝐄
- claim
- your
- free
- prize
- viagra
- free
零宽空格、西里尔字母 і、以数字代替字母,以及数学粗体字母
恭喜您获得一百万元大奖
- 恭喜
- 您
- 获得
- 一
- 百万
- 元
- 大奖
用词典分词
ยินดีด้วยคุณได้รับรางวัลหนึ่งล้านบาท
- ยินดี
- ด้วย
- คุณ
- ได้
- รับ
- รางวัล
- หนึ่ง
- ล้าน
- บาท
用词典分词
Поздравляем! Вы выиграли миллион
- поздравляем
- вы
- выиграли
- миллион
按 Unicode 规则转为小写
接入你的邮件服务器
用于 Postfix 和 Sendmail 的 milter,供 spamc、Exim 和 Haraka 使用的兼容 SpamAssassin 的 spamd 服务器,内容过滤器,HTTP API,TCP 服务器,以及库。
它们都会添加 X-Spam-Flag, X-Spam-Score, X-Spam-Status 邮件头,并移除发件人伪造的同名邮件头。
spamscanner milter --port 7831 --auth --subject-tag "[SPAM]"
# /etc/postfix/main.cf
smtpd_milters = inet:127.0.0.1:7831
milter_default_action = acceptmilter 在 SMTP 会话期间检查邮件,因此达到拒收阈值的垃圾邮件在被接收之前就会被拒绝。 Postfix 指南
spamscanner spamd --port 783 --auth
spamc -c < message.eml # prints 16.3/5.0 and exits 1兼容 SpamAssassin 的 spamd 服务器:停止 spamd,在同一端口启动 Spam Scanner,SpamAssassin 客户端照常工作。 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
}库,用于 smtp-server、Haraka 插件或任何处理邮件的服务。 API 参考
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"适用于任何能发出 HTTP 请求的语言和服务器。 HTTP API 指南
难以判断时交给语言模型
明确的垃圾邮件和明确的正常邮件不会交给它。当分数接近阈值或分类器不确定时,由模型阅读邮件,回答垃圾邮件、钓鱼、诈骗、恶意软件或正常邮件。可以在自己的机器上运行模型,也可以使用托管模型,URL、端口和身份验证均可自定。
邮件中针对 AI 过滤器隐藏的指令会按垃圾邮件计分,并且会告知模型邮件只是数据。端到端测试通过 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:4b带轮廓的:在你自己的机器上运行。邮件发送给托管服务商之前会移除个人数据。
| Ollama | 许可证 | 大小 |
|---|---|---|
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 |
推荐的开放模型。 全部推荐
可测量,可训练
内置模型在公开数据集上训练,并用它未见过的邮件测试。用你自己的邮件训练的模型效果更好:从 mbox 文件、Maildir 或数据集训练,测量其效果,并通过“举报垃圾邮件”按钮让它继续学习。
| 留出的邮件 | 邮件 | 精确率 | 召回率 | 误报 |
|---|---|---|---|---|
| 英语 | 6,564 | 100.0% | 97.1% | 0.0% |
| 俄语 | 1,682 | 100.0% | 97.4% | 0.0% |
| 意大利语 | 1,389 | 98.1% | 85.3% | 1.8% |
| 德语 | 1,309 | 97.7% | 76.1% | 2.2% |
| 西班牙语 | 1,281 | 97.5% | 82.6% | 2.6% |
| 全部 | 13,840 | 99.2% | 85.1% | 0.6% |
仅分类器本身,在其公开训练数据中每十封留出一封进行测试。“不确定”的邮件计为漏判。德语、意大利语和西班牙语来自标签有噪声的合成数据集。 关于内置模型
为 Forward Email 打造
Forward Email 不记录邮件内容,因此不能把邮件发送给外部过滤服务。Spam Scanner 运行在你自己的服务器上,除非另行配置,不会向任何地方发送任何内容,并且无需有人阅读邮件就能解释每一个判定。 Forward Email 与升级
Forward Email 的项目,一家注重隐私的电子邮件服务。
