File Coverage

lib/Sisimai.pm
Criterion Covered Total %
statement 76 76 100.0
branch 14 16 87.5
condition 8 10 80.0
subroutine 12 12 100.0
pod 6 8 75.0
total 116 122 95.0


line stmt bran cond sub pod time code
1             package Sisimai;
2 9     9   580144 use feature ':5.10';
  9         111  
  9         1293  
3 9     9   60 use strict;
  9         38  
  9         171  
4 9     9   45 use warnings;
  9         21  
  9         243  
5 9     9   4279 use version; our $VERSION = version->declare('v4.25.16'); our $PATCHLV = 0;
  9         17690  
  9         47  
6              
7 1 50   1 1 18 sub version { return substr($VERSION->stringify, 1).($PATCHLV > 0 ? 'p'.$PATCHLV : '') }
8 1     1 0 1975 sub sysname { 'bouncehammer' }
9 1     1 0 8 sub libname { 'Sisimai' }
10              
11             sub make {
12             # Wrapper method for parsing mailbox or Maildir/
13             # @param [String] argv0 Path to mbox or Maildir/
14             # @param [Hash] argv0 or Hash (decoded JSON)
15             # @param [Handle] argv0 or STDIN
16             # @param [Hash] argv1 Parser options
17             # @options argv1 [Integer] delivered 1 = Including "delivered" reason
18             # @options argv1 [Code] hook Code reference to a callback method
19             # @return [Array] Parsed objects
20             # @return [Undef] Undef if the argument was wrong or an empty array
21 49     49 1 4004927 my $class = shift;
22 49 100 100     161 my $argv0 = shift // return undef; die ' ***error: wrong number of arguments' if scalar @_ % 2;
  48         604  
23 47         98 my $argv1 = { @_ };
24              
25 47         2216 require Sisimai::Data;
26 47         2030 require Sisimai::Message;
27 47         1657 require Sisimai::Mail;
28              
29 47         112 my $list = [];
30 47   50     199 my $mail = Sisimai::Mail->new($argv0) || return undef;
31 47         186 while( my $r = $mail->data->read ) {
32             # Read and parse each email file
33 2297         8205 my $p = { 'data' => $r, 'hook' => $argv1->{'hook'} };
34 2297 100       16244 next unless my $mesg = Sisimai::Message->new(%$p);
35              
36 2292         8716 $p = { 'data' => $mesg, 'delivered' => $argv1->{'delivered'}, 'origin' => $mail->data->path };
37 2292         33143 my $data = Sisimai::Data->make(%$p);
38 2292 100       32417 push @$list, @$data if scalar @$data;
39             }
40 47 100       221 return undef unless scalar @$list;
41 45         427 return $list;
42             }
43              
44             sub dump {
45             # Wrapper method to parse mailbox/Maildir and dump as JSON
46             # @param [String] argv0 Path to mbox or Maildir/
47             # @param [Hash] argv0 or Hash (decoded JSON)
48             # @param [Handle] argv0 or STDIN
49             # @param [Hash] argv1 Parser options
50             # @options argv1 [Integer] delivered 1 = Including "delivered" reason
51             # @options argv1 [Code] hook Code reference to a callback method
52             # @return [String] Parsed data as JSON text
53 6     6 1 417451 my $class = shift;
54 6 100 100     30 my $argv0 = shift // return undef; die ' ***error: wrong number of arguments' if scalar @_ % 2;
  5         38  
55 4         12 my $argv1 = { @_ };
56 4   100     22 my $nyaan = __PACKAGE__->make($argv0, %$argv1) // [];
57              
58 4         74 for my $e ( @$nyaan ) {
59             # Set UTF8 flag before converting to JSON string
60 579         1449 utf8::decode $e->{'subject'};
61 579         1958 utf8::decode $e->{'diagnosticcode'};
62             }
63              
64 4         732 require Module::Load;
65 4         1335 Module::Load::load('JSON', '-convert_blessed_universally');
66 4         1311 my $jsonparser = JSON->new->allow_blessed->convert_blessed->utf8;
67 4         123 my $jsonstring = $jsonparser->encode($nyaan);
68              
69 4 50       132 utf8::encode $jsonstring if utf8::is_utf8 $jsonstring;
70 4         5307 return $jsonstring;
71             }
72              
73             sub engine {
74             # Parser engine list (MTA modules)
75             # @return [Hash] Parser engine table
76 1     1 1 990 my $class = shift;
77 1         5 my $table = {};
78              
79 1         6 for my $e ('Lhost', 'ARF', 'RFC3464', 'RFC3834') {
80 4         10 my $r = 'Sisimai::'.$e;
81 4         13 (my $loads = $r) =~ s|::|/|g;
82 4         18 require $loads.'.pm';
83              
84 4 100       13 if( $e eq 'Lhost' ) {
85             # Sisimai::Lhost::*
86 1         2 for my $ee ( @{ $r->index } ) {
  1         9  
87             # Load and get the value of "description" from each module
88 55         83 my $rr = 'Sisimai::'.$e.'::'.$ee;
89 55         141 ($loads = $rr) =~ s|::|/|g;
90 55         187 require $loads.'.pm';
91 55         221 $table->{ $rr } = $rr->description;
92             }
93             } else {
94             # Sisimai::ARF, Sisimai::RFC3464, and Sisimai::RFC3834
95 3         18 $table->{ $r } = $r->description;
96             }
97             }
98 1         3 return $table;
99             }
100              
101             sub reason {
102             # Reason list Sisimai can detect
103             # @return [Hash] Reason list table
104 2     2 1 49320 my $class = shift;
105 2         5 my $table = {};
106              
107             # These reasons are not included in the results of Sisimai::Reason->index
108 2         12 require Sisimai::Reason;
109 2         5 my @names = (@{ Sisimai::Reason->index }, qw|Delivered Feedback Undefined Vacation|);
  2         14  
110              
111 2         8 for my $e ( @names ) {
112             # Call ->description() method of Sisimai::Reason::*
113 58         123 my $r = 'Sisimai::Reason::'.$e;
114 58         211 (my $loads = $r) =~ s|::|/|g;
115 58         9226 require $loads.'.pm';
116 58         420 $table->{ $e } = $r->description;
117             }
118 2         20 return $table;
119             }
120              
121             sub match {
122             # Try to match with message patterns
123             # @param [String] Error message text
124             # @return [String] Reason text
125 93     93 1 380 my $class = shift;
126 93   50     162 my $argvs = shift || return undef;
127              
128 93         274 require Sisimai::Reason;
129 93         251 return Sisimai::Reason->match(lc $argvs);
130             }
131              
132             1;
133             __END__