תיעוד API

JavaScript
import SpamScanner from 'spamscanner';             // ESM
const SpamScanner = require('spamscanner');        // CommonJS

const scanner = new SpamScanner(options);
const result = await scanner.scan(rawMessage, scanOptions);

כדאי ליצור סורק אחד ולהשתמש בו שוב: הוא טוען את המודל פעם אחת ושומר במטמון תשובות DNS ותשובות של מודל השפה.

אפשרויות#

אפשר להעביר כל אפשרות לבנאי. את רובן אפשר להעביר גם ל-scan() עבור הודעה אחת, ואז הן ממוזגות מעל האפשרויות של הבנאי.

אפשרותברירת מחדלמשמעות
threshold5הניקוד שבו הודעה היא ספאם
rejectThreshold15הניקוד שבו action הוא reject
scores{}נקודות לכל בדיקה: מפתחות הגדרה או שמות בדיקות (בדיקות וניקוד)
classifierהמודל המצורף‏Classifier, אובייקט מודל, נתיב לקובץ מודל, או false
classifierOptions{}אפשרויות למודל המצורף (ראו Classifier)
allowedLanguages[]קודי ISO 639-1; שפות אחרות מקבלות LANGUAGE_NOT_ALLOWED
phishing.cloudflaretrueלשאול את שרתי ה-DNS המסננים של Cloudflare על המארחים שבקישורים
phishing.adulttrueלשאול גם את שרת ה-DNS המשפחתי, שחוסם אתרים למבוגרים
phishing.maxHosts25מספר המארחים מקישורים שנבדקים בכל הודעה
phishing.homograph{}brands (מחליף את הרשימה המובנית), extraBrands, allowlist (דומיינים שלעולם לא מסומנים), strictMode
dnsbl{ip: [], domain: []}אזורי רשימות שחורות ב-DNS עבור ה-IP של הלקוח ועבור דומיינים מקישורים
dns{servers: null, timeout: 3000}שרתי שמות לבדיקות DNS (ברירת מחדל: של המערכת)
attachmentstrueלבדוק קבצים מצורפים
macrostrueלסמן פקודות מאקרו, קובצי PDF פעילים ואובייקטי RTF
arbitrarytrueלהריץ את הכללים
authenticationfalsetrue, או {dnsServers, timeout, mta, weights}: SPF,‏ DKIM,‏ DMARC,‏ ARC
reputationfalse{allowlist, denylist, apiUrl, headers, timeout}
allowlist, denylistכתובות IP, דומיינים או כתובות; קיצור של reputation
clamavfalsetrue (ה-socket ברירת המחדל), {socket} או {host, port}
llmnullהגדרות מודל השפה, עם mode, minScore, maxScore
toxicityfalse{model, threshold = 0.7}: מודל שה-classify([text]) שלו עונה כמו @tensorflow-models/toxicity
nsfwfalse{model, threshold = 0.6}: מודל שה-classify(imageBuffer) שלו עונה כמו nsfwjs
maxLength100000מספר התווים מגוף ההודעה שנקראים
timeout10000אלפיות השנייה שמוקצות לכל בדיקת רשת
session{}פרטי ברירת מחדל של שיחת ה-SMTP

scan() מקבלת גם session:

JavaScript
await scanner.scan(raw, {
  session: {
    remoteAddress: '203.0.113.5',             // the client's IP address
    resolvedClientHostname: 'mx.example.com', // its verified reverse DNS name
    helo: 'mx.example.com',
    envelope: {
      mailFrom: {address: 'alice@example.com'},
      rcptTo: [{address: 'bob@example.org'}],
    },
  },
});

שרת שכבר בדק SPFSender Policy Framework: רשומת DNS שמפרטת את השרתים שמורשים לשלוח דואר עבור דומיין.,‏ DKIMDomainKeys Identified Mail: חתימה על הודעה, שנבדקת בעזרת מפתח ציבורי שמפורסם ב-DNS של השולח.,‏ DMARCמדיניות DNS שאומרת לשרתים המקבלים מה לעשות כשדואר שמתיימר להגיע מדומיין נכשל בהתאמת SPF ו-DKIM. ו-ARC (בעזרת mailauth) יכול להעביר את התוצאות שלו כ-authenticationResults, והן מקבלות ניקוד במקום להיבדק שוב:

JavaScript
import {authenticate} from 'mailauth';

const auth = await authenticate(raw, {ip, helo, sender, mta});
await scanner.scan(raw, {authenticationResults: auth});

מתודות#

מתודהמחזירה
scan(source, options)את התוצאה. source הוא Buffer, מחרוזת, Uint8Array או זרם קריא
scanFile(path, options)את התוצאה עבור קובץ הודעה
learn(source, 'spam' | 'ham')מלמדת את המסווג הודעה אחת
unlearn(source, 'spam' | 'ham')מבטלת learn
saveModel(path, options)כותבת את המסווג לקובץ (options: minCount, maxFeatures, metadata)
getClassifier()את ה-Classifier שבשימוש, או null
getClassification(features)את פסק הדין של המסווג עבור מאפיינים מ-getFeatures
getFeatures(mail){features, words, language, script, links, hosts, text, hidden} של הודעה
getTokens(text, locale)את המילים של טקסט
getTokensAndMailFromSource(source){tokens, features, mail}
parse(source){raw, mail}, כש-mail מגיע מ-mailparser

ב-getFeatures, ‏text הוא הטקסט שתוכנת דואר מציגה, שממנו נקראות המילים, ו-hidden הוא מספר התווים של טקסט שה-HTML מסתיר.

scanner.metrics מכיל את totalScans, ‏averageTime ו-lastScanTime.

התוצאה#

JavaScript
{
  isSpam: true,
  score: 16.25,
  threshold: 5,
  rejectThreshold: 15,
  action: 'reject',                       // 'accept', 'tag' or 'reject'
  message: 'Spam (BAYES_999, PHISHING_LOOKALIKE_DOMAIN, DECEPTIVE_LINK, FROM_NAME_BRAND)',
  tests: [
    {name: 'BAYES_999', score: 6.25, description: 'Classifier spam probability 99.9%'},
    {name: 'PHISHING_LOOKALIKE_DOMAIN', score: 5, description: '"paypa1-secure.top" imitates paypal by swapping characters'},
    // ...
  ],
  results: {
    classification: {probability, category, spam, ham, clues, coverage},
    phishing: [],        // lookalike domains, deceptive links, Cloudflare and URIBL findings
    uncheckedHosts: 0,   // link hosts beyond phishing.maxHosts, not looked up
    attachments: [],     // every attachment finding
    executables: [],     // the executable findings among them
    macros: [],          // macros, active PDFs, RTF objects
    viruses: [],         // ClamAV findings: {filename, virus: [names], message}
    arbitrary: [],       // rules strong enough to mark spam alone
    obfuscation: {invisible, mixed, styled},
    authentication: null, // mailauth's results with a score, when checked
    reputation: null,
    dnsbl: [],           // {zone, value} for each listing
    language: {language, script, notAllowed},
    llm: null,           // the language model's verdict, when asked
    toxicity: [],
    nsfw: [],
    idnHomographAttack: {detected, domains, riskScore},
  },
  links: ['http://paypa1-secure.top/login'],
  language: 'en',
  tokens: ['dear', 'customer', /* ... */],
  mail: {/* the parsed message, from mailparser */},
  version: '7.0.0',
  metrics: {totalTime: 42},
}

ממצאים ב-phishing, ‏attachments, ‏executables, ‏macros, ‏viruses ו-arbitrary הם אובייקטים עם type ו-message. ‏String(finding) הוא ההודעה.

ייצואים#

JavaScript
import SpamScanner, {
  Classifier, getFeatures, segmentWords, detectLanguage,
  LLMClassifier, PROVIDERS, RECOMMENDED_MODELS, CLASSIFIER_MODELS,
  DEFAULT_SCORES, scoreResults, spamHeaders, rewriteMessage,
  loadModel, saveModel, defaultModelPath, loadDefaultModel,
  train, evaluate, readExamples,
  MilterServer, createHttpServer, createTcpServer, createSpamdServer,
  DEFAULTS, VERSION,
} from 'spamscanner';

import ArfParser from 'spamscanner/arf';

Classifier#

JavaScript
const classifier = new Classifier({spamCutoff: 0.99, hamCutoff: 0.2});
classifier.learn(getFeatures(mail).features, 'spam');
classifier.classify(features); // {probability, category, spam, ham, clues, coverage}
אפשרותברירת מחדלמשמעות
strength, unknown0.45, 0.5ה-s וה-x של Robinson: כמה חזק מאפיינים נדירים נמשכים לכיוון 0.5
minDistance0.1מאפיינים שקרובים ל-0.5 יותר מזה מתעלמים מהם
maxClues150מספר המאפיינים החזקים ביותר שמשולבים בכל הודעה
hamCutoff, spamCutoff0.2, 0.99גבולות הטווח unsure
minLanguageExamples, languageShare1000, 0.02מספר ההודעות מכל סוג שנדרשות בשפה כדי להגיע לביטחון מלא
languagePriortrueלשקול מילים מול הספירות של השפה שלהן

גם merge(other), ‏toJSON(options), ‏Classifier.fromJSON(json), ‏size ו-entries() זמינים.

אימון#

JavaScript
import {train, evaluate, saveModel} from 'spamscanner';

const {classifier, spam, ham} = await train({
  spam: ['/mail/Junk'],
  ham: ['/mail/Archive', '/mail/archive.mbox'],
  datasets: [{file: 'extra.csv', textColumn: 'body', labelColumn: 'kind'}],
});
saveModel(classifier, 'model.json');

evaluate(classifier, examples) מקבלת פריטי {label, features}, או את readExamples(sources), שקוראת את אותם מקורות כמו train, ומחזירה ספירות, דיוק, רגישות, F1, נכונות ושיעורי חיוביות שגויות, שליליות שגויות ו„לא בטוח”.

שרתים#

JavaScript
import SpamScanner, {MilterServer, createHttpServer, createSpamdServer} from 'spamscanner';

const scanner = new SpamScanner({authentication: true});
const milter = new MilterServer(scanner, {reject: true, rejectCode: 451, subjectTag: '[SPAM]'});
milter.on('scan', ({session, result}) => console.log(session.remoteAddress, result.score));
await milter.listen(7831);

createHttpServer(scanner, {token: process.env.SPAMSCANNER_TOKEN}).listen(7832, '127.0.0.1');
createSpamdServer(scanner).listen(783, '127.0.0.1');

דוחות ARF#

spamscanner/arf קורא וכותב דוחות משוב על שימוש לרעה (RFC 5965), הפורמט שספקי תיבות דואר משתמשים בו כדי לדווח על תלונות ספאם:

JavaScript
import ArfParser from 'spamscanner/arf';

const report = await ArfParser.parse(rawReport);
console.log(report.feedbackType, report.sourceIp, report.originalHeaders.subject);

const raw = ArfParser.create({
  feedbackType: 'abuse', userAgent: 'MyService/1.0',
  from: 'abuse@example.com', to: 'fbl@example.net',
  originalMessage, sourceIp: '192.0.2.1',
});

ArfParser.tryParse() מחזירה null במקום לזרוק שגיאה עבור הודעות שאינן דוחות, ו-isArfMessage(mail) בודקת הודעה מפוענחת.

עריכת הדף ב-GitHub · Markdown ·