Forward Email

Spam Scannerは、オープンソースでプライバシー重視のメールサービスであるForward Emailが、自社のメールサーバーのために開発しました。Forward Emailはメッセージ内容のログを残さないため、外部のフィルタリングサービスは使えませんでした。フィルターは自社のサーバーで動作し、人がメールを読まなくても各判定を説明できる必要がありました。

このページでは、Forward Emailのようなメールサーバーでの使い方と、Spam Scanner 5または6向けに書かれたコードから何が変わったかを説明します。

受信メールサーバーで#

Forward Emailはsmtp-serverでメールを受信します。smtp-serverで構築したサーバーであれば、次のパターンを使えます。

JavaScript
const SpamScanner = require('spamscanner');

const scanner = new SpamScanner({
  clamav: true,                  // clamd on its default socket
  authentication: true,          // SPF, DKIM, DMARC, ARC
  dnsbl: {ip: ['zen.spamhaus.org'], domain: ['dbl.spamhaus.org']},
  dns: {servers: ['127.0.0.1']}, // a local caching resolver
});

async function onData(stream, session, callback) {
  const scan = await scanner.scan(stream, {
    session: {
      remoteAddress: session.remoteAddress,
      resolvedClientHostname: session.clientHostname,
      helo: session.hostNameAppearsAs,
      envelope: session.envelope,
    },
  });

  if (scan.results.viruses.length > 0) {
    return callback(Object.assign(new Error(`Message contains a virus: ${scan.results.viruses[0]}`), {responseCode: 554}));
  }

  if (scan.action === 'reject') {
    // A temporary error: the sender retries, and a wrong decision can be undone.
    return callback(Object.assign(new Error(`Message rejected as spam: ${scan.message}`), {responseCode: 421}));
  }

  // scan.isSpam: deliver to the Junk folder, or add scan's headers (spamHeaders) and forward.
  callback();
}

scanner.scan()はSMTPストリームを直接受け付けます。mailauthの結果がすでに手元にある場合は、authenticationを省き、IPアドレスだけを渡してください。

421または451で応答すると、送信側のサーバーはメッセージをキューに入れ、後で再試行します。新しい拒否ルールは一時的なコードで始め、結果を確認してから550に切り替えれば、その間にメールを失うことはありません。

バージョン5または6からのアップグレード#

バージョン7は全面的な書き直しです。バージョン5と6のコードが使うコンストラクター、scan()、結果のフィールドはそのまま動きます。分類器、モデル、オプションのTensorFlowによる検査は変わりました。

変わらないもの#

  • new SpamScanner(options)とawait scanner.scan(source)。
  • require('spamscanner')はクラスを返し、import SpamScanner from 'spamscanner'も使えます。
  • result.isSpam、result.message、そしてresult.results.classification、.phishing、.executables、.arbitrary、.viruses、.macros、.idnHomographAttack。
  • results.phishing、.executables、.arbitrary、.virusesの各項目は、以前と同じ種類のメッセージ文字列に変換されます(String(item)、テンプレートリテラル、message.includes('adult-related content'))。各項目は現在、type、message、詳細を持つオブジェクトです。
  • getTokensAndMailFromSource()、getClassification()、getTokens()。
  • 次のオプションは新しい名前に対応付けられます。clamscanはclamavに、enableMacroDetection: falseはmacros: falseに、enableArbitraryDetection: falseはarbitrary: falseに、enableAuthenticationとauthOptionsはauthenticationとsessionに、enableReputationとreputationOptions.apiUrlはreputationに、strictIDNDetectionはphishing.homograph.strictModeに対応し、allowlistとdenylistはそのままです。loggerとmemoizeは受け付けますが無視します。

変わったもの#

以前現在
scan('path/to/file.eml')はファイルを読んでいた文字列はメッセージのテキストとして扱う。scanFile(path)を使うか、Bufferを渡す
単語の単純ベイズモデル(classifier.json)。現在は読み込めない新しい分類器とモデル形式。spamscanner trainで再学習する(学習)
有害性とNSFWの検査は、初回使用時にネットワークからTensorFlowのモデルを読み込んでいた自分でモデルを用意する。toxicity: {model}とnsfw: {model}は、classify()メソッドを持つ任意のオブジェクトを受け取る(例:@tensorflow-models/toxicityとnsfwjs)
results.arbitraryは一致したすべてのパターンを列挙していた単独でスパムと判定できるほど強いルールを列挙する。すべてのルールはresult.testsにある
はい・いいえの回答result.score、result.action(accept、tag、reject)、result.tests。各テストに点数と理由が付く
isSpamは分類器または単一の検査で決まっていたisSpamはスコア5以上を意味する。しきい値と点数は変更できる
Forward Emailのエンドポイントに対するレピュテーション検査汎用のレピュテーションサービス。reputation.apiUrlを設定しない限り無効

新機能#

  • 際どい判定のための、ローカルまたはホスト型の言語モデル。
  • SPFSender Policy Framework。あるドメインのメールの送信を許可されたサーバーを列挙するDNSレコード。、DKIMDomainKeys Identified Mail。メッセージに付ける署名で、送信者のDNSで公開された公開鍵を使って検証します。、DMARCあるドメインを名乗るメールがSPFとDKIMのアライメントに失敗したとき、受信側がどう扱うべきかを示すDNSのポリシー。、ARCAuthenticated Received Chain。転送サーバーを経由しても認証結果を引き継ぐための署名。、DNSブロックリスト、Cloudflareのフィルタリング用リゾルバー。
  • 内容に基づく添付ファイルの検査:偽装した実行ファイル、アーカイブ、マクロ、アクティブなPDF。
  • milter、HTTP API、TCPサーバー、spamdサーバーとコマンドライン。
  • コマンドラインまたはAPIからの学習、評価、報告からの学習。

このページをGitHubで編集 · Markdown ·