Skip to content

Latest commit

 

History

History
469 lines (395 loc) · 25.3 KB

README-JA.md

File metadata and controls

469 lines (395 loc) · 25.3 KB

License Perl CPAN codecov

Important

2024年2月2日の時点でこのリポジトリのデフォルトブランチは5-stable (Sisimai 5)になりました。 もし古いバージョンを使いたい場合は4-stable1 ブランチを見てください。またmainmasterブランチはもうこのリポジトリでは使用していません。

Caution

Sisimai 4.25.14p11およびそれ以前のバージョンには 正規表現に関する脆弱性 ReDoS: CVE-2022-4891があります。 該当するバージョンをお使いの場合はv4.25.14p12以降へアップグレードしてください。

Warning

Sisimai 5はPerl 5.26以上が必要です。インストール/アップグレードを実行する前にperl -vコマンドで システムに入っているPerlのバージョンを確認してください。

Note

SisimaiはPerlモジュールまたはRuby Gemですが、PHPやPython、GoやRustなどJSONを読める言語であれば どのような環境においても解析結果を得ることでバウンスの発生状況を捉えるのにとても有用です。

What is sisimai

Sisimai(シシマイ)は複雑で多種多様なバウンスメールを解析してバウンスした理由や宛先メールアドレスなど 配信が失敗した結果を構造化データで出力するライブラリでJSONでの出力も可能です

The key features of Sisimai

  • バウンスメールを構造化したデータに変換
    • 以下26項目の情報を含むデータ構造2
      • 基本的情報: timestamp, origin
      • 発信者情報: addresser, senderdomain,
      • 受信者情報: recipient, destination, alias
      • 配信の情報: action, replycode, deliverystatus, command
      • エラー情報: reason, diagnosticcode, diagnostictype, feedbacktype, feedbackid, hardbounce
      • メール情報: subject, messageid, listid,
      • その他情報: decodedby, timezoneoffset, lhost, rhost, token, catch
    • 出力可能な形式
      • Perl (Hash, Array)
      • JSON (JSONモジュールを使用)
      • YAML (YAMLモジュールまたは YAML::Syckモジュールが必要)
  • インストールも使用も簡単
    • cpan, cpanm, cpm install
    • git clone & make
  • 高い解析精度

Command line demo

次の画像のように、Perl版シシマイ(p5-sisimai)はコマンドラインから簡単にバウンスメールを解析すること ができます。

Setting Up Sisimai

System requirements

シシマイの動作環境についての詳細はSisimai | シシマイを使ってみる をご覧ください。

Install

From CPAN

$ cpanm --sudo Sisimai
--> Working on Sisimai
Fetching http://www.cpan.org/authors/id/A/AK/AKXLIX/Sisimai-5.2.1.tar.gz ... OK
...
1 distribution installed
$ perldoc -l Sisimai
/usr/local/lib/perl5/site_perl/5.30.0/Sisimai.pm

From GitHub

Warning

Sisimai 5はPerl 5.26以上が必要です。インストール/アップグレードを実行する前にperl -vコマンドで システムに入っているPerlバージョンを確認してください。

$ perl -v

This is perl 5, version 30, subversion 0 (v5.30.0) built for darwin-2level

Copyright 1987-2019, Larry Wall
...

$ cd /usr/local/src
$ git clone https://github.com/sisimai/p5-sisimai.git
$ cd ./p5-sisimai

$ make install-from-local
./cpanm --sudo . || ( make cpm && ./cpm install --sudo -v . )
--> Working on .
Configuring Sisimai-v5.2.1 ... OK
Building and testing Sisimai-v5.2.1 ... Password: <sudo password here>
OK
Successfully installed Sisimai-v5.2.1
1 distribution installed

$ perl -MSisimai -lE 'print Sisimai->version'
5.2.1

Usage

Basic usage

下記のようにSisimaiのrise()メソッドをmboxかMaildir/のPATHを引数にして実行すると解析結果が配列 リファレンスで返ってきます。v4.25.6から元データとなった電子メールファイルへのPATHを保持するorigin が利用できます。

#! /usr/bin/env perl
use Sisimai;
my $v = Sisimai->rise('/path/to/mbox'); # またはMaildir/へのPATH

# v4.23.0からSisimaiクラスのrise()メソッドとdump()メソッドはPATH以外にもバウンスメール全体を文字列
# として読めるようになりました
use IO::File;
my $r = '';
my $f = IO::File->new('/path/to/mbox'); # またはMaildir/へのPATH
{ local $/ = undef; $r = <$f>; $f->close }
my $v = Sisimai->rise(\$r);

# もし"delivered"(配信成功)となる解析結果も必要な場合は以下に示すとおりrise()メソッドに"delivered"
# オプションを指定してください
my $v = Sisimai->rise('/path/to/mbox', 'delivered' => 1);

# v5.0.0からSisimaiはバウンス理由が"vacation"となる解析結果をデフォルトで返さなくなりました。もし
# "vacation"となる解析結果も必要な場合は次のコードで示すようにrise()メソッドに"vacation"オプション
# を指定してください。
my $v = Sisimai->rise('/path/to/mbox', 'vacation' => 1);

if( defined $v ) {
    for my $e ( @$v ) {
        print ref $e;                   # Sisimai::Fact
        print ref $e->recipient;        # Sisimai::Address
        print ref $e->timestamp;        # Sisimai::Time

        print $e->addresser->address;   # "michitsuna@example.org" # From
        print $e->recipient->address;   # "kijitora@example.jp"    # To
        print $e->recipient->host;      # "example.jp"
        print $e->deliverystatus;       # "5.1.1"
        print $e->replycode;            # "550"
        print $e->reason;               # "userunknown"
        print $e->origin;               # "/var/spool/bounce/new/1740074341.eml"
        print $e->hardbounce;           # 0

        my $h = $e->damn();             # Hashリファレンスに変換
        my $j = $e->dump('json');       # JSON(文字列)に変換
        print $e->dump('json');         # JSON化したバウンスメールの解析結果を表示
    }
}

Convert to JSON

下記のようにSisimaiのdump()メソッドをmboxかMaildir/のPATHを引数にして実行すると解析結果が文字列 (JSON)で返ってきます。

# メールボックスまたはMaildir/から解析した結果をJSONにする
my $j = Sisimai->dump('/path/to/mbox'); # またはMaildir/へのPATH
                                        # dump()メソッドはv4.1.27で追加されました
print $j;                               # JSON化した解析結果を表示

# dump()メソッドは"delivered"オプションや"vacation"オプションも指定可能
my $j = Sisimai->dump('/path/to/mbox', 'delivered' => 1, 'vacation' => 1);

Callback feature

Sisimai->riseSisimai->dumpc___引数(c_が三個/魚用の釣り針に見える)はコールバック機能 で呼び出されるコードリファンレンスを保持する配列リファレンスです。 c___の1番目の要素にはSisimai::Message->siftで呼び出されるコードリファレンスでメールヘッダと本文 に対して行う処理を、2番目の要素には、解析対象のメールファイルに対して行う処理をそれぞれ入れます。

各コードリファレンスで処理した結果はSisimai::Fact->catchを通して得られます。

[0] メールヘッダと本文に対して

c___に渡す配列リファレンスの最初の要素に入れたコードリファレンスはSisimai::Message->sift()で 呼び出されます。

#! /usr/bin/env perl
use Sisimai;
my $code = sub {
    my $args = shift;               # (*Hash)
    my $head = $args->{'headers'};  # (*Hash)  メールヘッダー
    my $body = $args->{'message'};  # (String) メールの本文
    my $adds = { 'x-mailer' => '', 'queue-id' => '' };

    if( $body =~ m/^X-Postfix-Queue-ID:\s*(.+)$/m ) {
        $adds->{'queue-id'} = $1;
    }

    $adds->{'x-mailer'} = $head->{'x-mailer'} || '';
    return $adds;
};
my $data = Sisimai->rise('/path/to/mbox', 'c___' => [$code, undef]);
my $json = Sisimai->dump('/path/to/mbox', 'c___' => [$code, undef]);

print $data->[0]->catch->{'x-mailer'};    # "Apple Mail (2.1283)"
print $data->[0]->catch->{'queue-id'};    # "43f4KX6WR7z1xcMG"

[1] 各メールのファイルに対して

Sisimai->rise()Sisimai->dump()の両メソッドに渡せる引数c___(配列リファレンス)の2番目に入れた コードリファレンスは解析したメールのファイルごとに呼び出されます。

my $path = '/path/to/maildir';
my $code = sub {
    my $args = shift;           # (*Hash)
    my $kind = $args->{'kind'}; # (String)  Sisimai::Mail->kind
    my $mail = $args->{'mail'}; # (*String) Entire email message
    my $path = $args->{'path'}; # (String)  Sisimai::Mail->path
    my $fact = $args->{'fact'}; # (*Array)  List of Sisimai::Fact

    for my $e ( @$fact ) {
        # "catch"アクセサの中に独自の情報を保存する
        $e->{'catch'} ||= {};
        $e->{'catch'}->{'size'} = length $$mail;
        $e->{'catch'}->{'kind'} = ucfirst $kind;

        if( $$mail =~ /^Return-Path: (.+)$/m ) {
            # Return-Path: <MAILER-DAEMON>
            $e->{'catch'}->{'return-path'} = $1;
        }

        # "X-Sisimai-Parsed:"ヘッダーを追加して別のPATHに元メールを保存する
        my $a = sprintf("X-Sisimai-Parsed: %d\n", scalar @$fact);
        my $p = sprintf("/path/to/another/directory/sisimai-%s.eml", $e->token);
        my $f = IO::File->new($p, 'w');
        my $v = $$mail; $v =~ s/^(From:.+)$/$a$1/m;
        print $f $v; $f->close;
    }

    # 解析が終わったらMaildir/にあるファイルを削除する
    unlink $path if $kind eq 'maildir';

    # 特に何か値をReturnする必要はない
};

my $list = Sisimai->rise($path, 'c___' => [undef, $code]);
print $list->[0]->{'catch'}->{'size'};          # 2202
print $list->[0]->{'catch'}->{'kind'};          # "Maildir"
print $list->[0]->{'catch'}->{'return-path'};   # "<MAILER-DAEMON>"

コールバック機能のより詳細な使い方は Sisimai | 解析方法 - コールバック機能をご覧ください。

One-Liner

Sisimai 4.1.27から登場したdump()メソッドを使うとワンライナーでJSON化した解析結果が得られます。

$ perl -MSisimai -lE 'print Sisimai->dump(shift)' /path/to/mbox

Output example

[
  {
    "destination": "google.example.com",
    "lhost": "gmail-smtp-in.l.google.com",
    "hardbounce": 0,
    "reason": "authfailure",
    "catch": null,
    "addresser": "michitsuna@example.jp",
    "alias": "nekochan@example.co.jp",
    "decodedby": "Postfix",
    "command": "DATA",
    "senderdomain": "example.jp",
    "listid": "",
    "action": "failed",
    "feedbacktype": "",
    "messageid": "hwK7pzjzJtz0RF9Y@relay3.example.com",
    "origin": "./gmail-5.7.26.eml",
    "recipient": "kijitora@google.example.com",
    "rhost": "gmail-smtp-in.l.google.com",
    "subject": "Nyaan",
    "timezoneoffset": "+0900",
    "replycode": 550,
    "token": "84656774898baa90660be3e12fe0526e108d4473",
    "diagnostictype": "SMTP",
    "timestamp": 1650119685,
    "diagnosticcode": "host gmail-smtp-in.l.google.com[64.233.187.27] said: This mail has been blocked because the sender is unauthenticated. Gmail requires all senders to authenticate with either SPF or DKIM. Authentication results: DKIM = did not pass SPF [relay3.example.com] with ip: [192.0.2.22] = did not pass For instructions on setting up authentication, go to https://support.google.com/mail/answer/81126#authentication c2-202200202020202020222222cat.127 - gsmtp (in reply to end of DATA command)",
    "deliverystatus": "5.7.26"
  }
]

Differences between Sisimai 4 and Sisimai 5

Sisimai 4.25.16p1Sisimai 5には下記のような違いがあります。 それぞれの詳細はSisimai | 違いの一覧を参照してください。

Features

Sisimai 5.0.0からPerl 5.26.0以上が必要になります。

機能 Sisimai 4 Sisimai 5
動作環境(Perl) 5.10 - 5.26 -
元メールファイルを操作可能なコールバック機能 なし あり3
解析エンジン(MTA/ESPモジュール)の数 68 59
検出可能なバウンス理由の数 29 36
依存もジュール数(Perlのコアモジュールを除く) 2 モジュール 2 モジュール
ソースコードの行数 10,800 行 9,900 行
テスト件数(t/とxt/ディレクトリ) 270,000 件 320,000 件
1秒間に解析できるバウンスメール数4 750 通 750 通
ライセンス 2条項BSD 2条項BSD
開発会社による商用サポート 提供中 提供中

Decoding Method

いくつかの解析メソッド名、クラス名、パラメーター名がSisimai 5で変更になっています。解析済みデータの 各項目はLIBSISIMAI.ORG/JA/DATAを参照してください。

解析用メソッド周辺の変更箇所 Sisimai 4 Sisimai 5
解析メソッド名 Sisimai->make Sisimai->rise
出力メソッド名 Sisimai->dump Sisimai->dump
解析メソッドが返すオブジェクトのクラス Sisimai::Data Sisimai::Fact
コールバック用のパラメーター名 hook c___5
ハードバウンスかソフトバウンスかを識別するメソッド名 softbounce hardbounce
"vacation"をデフォルトで検出するかどうか 検出する 検出しない
Sisimai::Messageがオブジェクトを返すかどうか 返す 返さない
MIME解析用クラスの名前 Sisimai::MIME Sisimai::RFC2045
SMTPセッションの解析をするかどうか しない する6

MTA/ESP Module Names

Sisimai 5で3個のESPモジュール名(解析エンジン)が変更になりました。詳細はMTA/ESPモジュールの一覧/ LIBSISIMAI.ORG/JA/ENGINEを参照してください。

Sisimai:: Sisimai 4 Sisimai 5
Apple iCloud Mail (added at v5.1.0) なし Rhost::Apple
Microsoft Exchange Online Rhost::ExchangeOnline Rhost::Microsoft
Google Workspace Rhost::GoogleApps Rhost::Google
Tencent Rhost::TencentQQ Rhost::Tencent
Yahoo Mail (added at v5.1.0) なし Rhost::YahooInc
DragonFly Mail Agent (added at v5.1.0) なし Lhost::DragonFly

Bounce Reasons

Sisimai 5では新たに5個のバウンス理由が増えました。検出可能なバウンス理由の一覧は LIBSISIMAI.ORG/JA/REASONを参照してください。

バウンスした理由 Sisimai 4 Sisimai 5
ドメイン認証によるもの(SPF,DKIM,DMARC) SecurityError AuthFailure
送信者のドメイン・IPアドレスの低いレピュテーション Blocked BadReputation
PTRレコードが未設定または無効なPTRレコード Blocked RequirePTR
RFCに準拠していないメール7 SecurityError NotCompliantRFC
単位時間の流量制限・送信速度が速すぎる SecurityError Speeding
STARTTLS関連のエラー (added at v5.2.0) SecurityError FailedSTARTTLS
宛先がサプレッションリストに一致 (added at v5.2.0) OnHold Suppressed

Contributing

Bug report

もしもSisimaiにバグを発見した場合はIssuesにて連絡を いただけると助かります。

Emails could not be decoded

Sisimaiで解析できないバウンスメールは set-of-emails/to-be-debugged-because/sisimai-cannot-parse-yetリポジトリに追加してPull-Requestを送ってください。

Other Information

Related sites

See also

Author

@azumakuniyuki

Copyright

Copyright (C) 2014-2025 azumakuniyuki, All Rights Reserved.

License

This software is distributed under The BSD 2-Clause License.

Footnotes

  1. 4系をcloneする場合はgit clone -b 4-stable https://github.com/sisimai/p5-sisimai.git

  2. コールバック機能を使用するとcatchアクセサの下に独自のデータを追加できます

  3. Sisimai->riseメソッドで指定するc___パラメーター第二引数で指定可能

  4. macOS Monterey/1.6GHz Dual-Core Intel Core i5/16GB-RAM/Perl 5.30

  5. c___は漁港で使う釣り針に見える

  6. Sisimai::SMTP::Transcript->riseメソッドによる

  7. RFC5322など