logo
Free, unlimited AI code reviews that run on commit
git-lrc git-lrc GitHub Install Now We'd appreciate a star git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

Sisimai - Mail Analyzing Interface for bounce mails.

Author

       azumakuniyuki

Basic Usage

"rise('/path/to/mbox')"
       rise() method provides the feature for getting decoded data as Perl Hash reference from bounced email
       messages as the following. Beginning with v4.25.6, new accessor "origin" which keeps the path to email
       file as a data source is available.

           use Sisimai;
           my $v = Sisimai->rise('/path/to/mbox'); # or path to Maildir/

           # In v4.23.0, the rise() and dump() methods of the Sisimai class can now read the entire bounce
           # email as a string, in addition to the PATH to the email file or mailbox.
           use IO::File;
           my $r = '';
           my $f = IO::File->new('/path/to/mbox'); # or path to Maildir/
           { local $/ = undef; $r = <$f>; $f->close }
           my $v = Sisimai->rise(\$r);

           # If you also need analysis results that are "delivered" (successfully delivered), please
           # specify the "delivered" option to the rise() method as shown below.
           my $v = Sisimai->rise('/path/to/mbox', 'delivered' => 1);

           # From v5.0.0, Sisimai no longer returns analysis results with a bounce reason of "vacation" by
           # default. If you also need analysis results that show a "vacation" reason, please specify the
           # "vacation" option to the rise() method as shown in the following code.
           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;           # 1

                   my $h = $e->damn();             # Convert to HASH reference
                   my $j = $e->dump('json');       # Convert to JSON string
                   print $e->dump('json');         # JSON formatted bounce data
               }
           }

   "dump('/path/to/mbox')"
       dump() method provides the feature for getting decoded data as JSON string from bounced email messages
       like the following code:

           use Sisimai;

           # Get JSON string from path of a mailbox or a Maildir/
           my $j = Sisimai->dump('/path/to/mbox'); # or path to Maildir/
                                                   # dump() is added in v4.1.27
           print $j;                               # decoded data as JSON

           # dump() method also accepts "delivered" and "vacation" option like the following code:
           my $j = Sisimai->dump('/path/to/mbox', 'delivered' => 1, 'vacation' => 1);

Description

Sisimai is a library that decodes complex and diverse bounce emails and outputs the results of the
       delivery failure, such as the reason for the bounce and the recipient email address, in structured data.
       It is also possible to output in JSON format.

License

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

perl v5.40.1                                       2025-04-12                                       Sisimai(3pm)

Name

       Sisimai - Mail Analyzing Interface for bounce mails.

Other Methods

"engine()"
       "engine" method provides table including decoding engine list and it's description.

           use Sisimai;
           my $v = Sisimai->engine();
           for my $e ( keys %$v ) {
               print $e;           # Sisimai::MTA::Sendmail
               print $v->{ $e };   # V8Sendmail: /usr/sbin/sendmail
           }

   "reason()"
       "reason" method provides table including all the reasons Sisimai can detect

           use Sisimai;
           my $v = Sisimai->reason();
           for my $e ( keys %$v ) {
               print $e;           # Blocked
               print $v->{ $e };   # 'Email rejected due to client IP address or a hostname'
           }

   "match()"
       "match" method receives an error message as a string and returns a reason name like the following:

           use Sisimai;
           my $v = '550 5.1.1 User unknown';
           my $r = Sisimai->match($v);
           print $r;   # "userunknown"

   "version()"
       "version" method returns the version number of Sisimai.

           use Sisimai;
           print Sisimai->version; # 5.0.1

Other Ways To Decode

ReademaildatafromSTDIN
       If you want to pass email data from STDIN, specify STDIN at the first argument of dump() and rise()
       method like following command:

           % cat ./path/to/bounce.eml | perl -MSisimai -lE 'print Sisimai->dump(STDIN)'

   CallbackFeature
       "c___" ("c" and three "_"s, looks like a fishhook) argument of Sisimai->rise and "Sisimai-"dump()> is an
       array reference and is a parameter to receive code references for callback feature. The first element of
       "c___" argument is called at "Sisimai::Message-"sift()> for dealing email headers and entire message
       body. The second element of "c___" argument is called at the end of each email file processing. The
       result generated by the callback method is accessible via "Sisimai::Fact-"catch>.

       [0]Foremailheadersandthebody

       Callback method set in the first element of "c___" is called at "Sisimai::Message-"sift()>.

           use Sisimai;
           my $code = sub {
               my $args = shift;               # (*Hash)
               my $head = $args->{'headers'};  # (*Hash)  Email headers
               my $body = $args->{'message'};  # (String) Message body
               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]Foreachemailfile

       Callback method set in the second element of "c___" is called at "Sisimai-"rise()> method for dealing
       each email file.

           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 ) {
                   # Store custom information in the "catch" accessor.
                   $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;
                   }

                   # Save the original email with an additional "X-Sisimai-Decoded:" header to a different PATH.
                   my $a = sprintf("X-Sisimai-Decoded: %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;
               }

               # Remove the email file in Maildir/ after decoding
               unlink $path if $kind eq 'maildir';

               # Need to not return a value
           };

           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>"

       More information about the callback feature is available at <https://libsisimai.org/en/usage/#callback>

Repository

       <https://github.com/sisimai/p5-sisimai> - Sisimai on GitHub

See Also

       Sisimai::Mail - Mailbox or Maildir object
       Sisimai::Fact - Decoded data object
       <https://libsisimai.org/> - Sisimai - Mail Analyzing Interface Library
       <https://tools.ietf.org/html/rfc3463> - RFC3463: Enhanced Mail System Status Codes
       <https://tools.ietf.org/html/rfc3464> - RFC3464: An Extensible Message Format for Delivery Status
       Notifications
       <https://tools.ietf.org/html/rfc5321> - RFC5321: Simple Mail Transfer Protocol
       <https://tools.ietf.org/html/rfc5322> - RFC5322: Internet Message Format

Synopsis

           use Sisimai;

Web Site

       <https://libsisimai.org/> - Mail Analyzing Interface Library

       <https://github.com/sisimai/rb-sisimai> - Ruby version of Sisimai

See Also