모든 언어를 읽고 모든 판정을 설명하는 스팸 필터.
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 방식으로 세고 결합하며, 단서가 서로 엇갈리면 솔직하게 "unsure"로 답합니다.
판정 방식모든 언어를 신중하게
중국어, 일본어, 태국어의 유니코드 단어 분리, 위장 문자 복원, 그리고 모델이 ham을 거의 학습하지 못한 언어에 대한 불이익 없음.
언어피싱
키릴 문자나 뒤바뀐 글자를 쓴 유사 도메인, 링크 텍스트에 다른 주소가 표시된 링크, 표시 이름에 들어간 브랜드명, 그리고 Cloudflare의 악성코드 차단 리졸버.
피싱 검사첨부 파일
바이트로 식별하는 실행 파일(.pdf로 이름을 바꾼 경우 포함), 이중 확장자, ZIP 파일 안의 프로그램, Office 매크로, 동적 PDF, ClamAV.
첨부 파일 검사인증
SPF, DKIM, DMARC, ARC, DNS 차단 목록, 허용 목록과 거부 목록, 그리고 자기 도메인을 사칭하는 메일에 대한 규칙.
인증언어 모델
애매한 메시지는 모델에 보냅니다. 직접 운영하는 컴퓨터의 Ollama나 Claude, ChatGPT, Gemini, 그 밖의 OpenAI 호환 서버를 사용할 수 있습니다.
언어 모델
추측 없이 모든 언어를
단어는 유니코드 규칙으로 찾으므로 띄어쓰기 없이 쓰는 언어도 처리되며, 위장된 글자는 세기 전에 원래대로 되돌립니다. 아래는 분류기가 세는 단어로, 이 페이지를 빌드할 때 계산했습니다.
번들 모델이 ham을 거의 학습하지 못한 언어는 "spam" 대신 "unsure"로 판정합니다. 따라서 아랍어나 한국어로 된 평범한 메일이 문자 체계 때문에 스팸으로 표시되는 일은 없습니다. 언어
Claim your fr␣ee prіze: V1agra 𝐅𝐑𝐄𝐄
- claim
- your
- free
- prize
- viagra
- free
폭 없는 공백, 키릴 문자 і, 글자 대신 쓴 숫자, 수학용 굵은 글자
恭喜您获得一百万元大奖
- 恭喜
- 您
- 获得
- 一
- 百万
- 元
- 大奖
사전으로 단어 분리
ยินดีด้วยคุณได้รับรางวัลหนึ่งล้านบาท
- ยินดี
- ด้วย
- คุณ
- ได้
- รับ
- รางวัล
- หนึ่ง
- ล้าน
- บาท
사전으로 단어 분리
Поздравляем! Вы выиграли миллион
- поздравляем
- вы
- выиграли
- миллион
유니코드 규칙에 따라 소문자로 변환
메일 서버에 바로 연동
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 1SpamAssassin 호환 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 가이드
판단이 애매한 메시지를 위한 언어 모델
명백한 스팸과 명백한 ham은 모델까지 가지 않습니다. 점수가 경계에 가깝거나 분류기가 확신하지 못하면 모델이 메시지를 읽고 spam, phishing, scam, malware, ham 중 하나로 답합니다. 직접 운영하는 컴퓨터에서 실행하거나 호스팅 모델을 사용할 수 있으며, 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% |
분류기만 사용해, 공개 학습 데이터에서 열 번째마다 학습에서 제외해 둔 메시지로 측정했습니다. unsure 메시지는 놓친 것으로 계산합니다. 독일어, 이탈리아어, 스페인어는 레이블에 오류가 섞인 합성 데이터 세트에서 가져왔습니다. 번들 모델 정보
Forward Email을 위해 개발
Forward Email은 메시지 내용을 기록하지 않으므로 외부 필터링 서비스로 메일을 보낼 수 없었습니다. Spam Scanner는 직접 운영하는 서버에서 실행되고, 설정하지 않는 한 어디에도 데이터를 보내지 않으며, 사람이 메일을 읽지 않고도 모든 판정을 설명합니다. Forward Email과 업그레이드
개인정보 보호 중심 이메일 서비스 Forward Email의 프로젝트입니다.
