|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Sisimai::Lhost::MailRu;  | 
| 
2
 | 
32
 | 
 
 | 
 
 | 
  
32
  
 | 
 
 | 
6321
 | 
 use parent 'Sisimai::Lhost';  | 
| 
 
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
65
 | 
    | 
| 
 
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
248
 | 
    | 
| 
3
 | 
32
 | 
 
 | 
 
 | 
  
32
  
 | 
 
 | 
2080
 | 
 use feature ':5.10';  | 
| 
 
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
74
 | 
    | 
| 
 
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2306
 | 
    | 
| 
4
 | 
32
 | 
 
 | 
 
 | 
  
32
  
 | 
 
 | 
180
 | 
 use strict;  | 
| 
 
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
86
 | 
    | 
| 
 
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
667
 | 
    | 
| 
5
 | 
32
 | 
 
 | 
 
 | 
  
32
  
 | 
 
 | 
172
 | 
 use warnings;  | 
| 
 
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
54
 | 
    | 
| 
 
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52267
 | 
    | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Based on Sisimai::Lhost::Exim  | 
| 
8
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
1
  
 | 
1204
 | 
 sub description { '@mail.ru: https://mail.ru' }  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub make {  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Detect an error from @mail.ru  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # @param    [Hash] mhead    Message headers of a bounce email  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # @param    [String] mbody  Message body of a bounce email  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # @return   [Hash]          Bounce data list and message/rfc822 part  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # @return   [Undef]         failed to parse or the arguments are missing  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # @since v4.1.4  | 
| 
16
 | 
403
 | 
 
 | 
 
 | 
  
403
  
 | 
  
1
  
 | 
1175
 | 
     my $class = shift;  | 
| 
17
 | 
403
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
1040
 | 
     my $mhead = shift // return undef;  | 
| 
18
 | 
402
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
854
 | 
     my $mbody = shift // return undef;  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Message-Id:   | 
| 
21
 | 
402
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2591
 | 
     return undef unless lc($mhead->{'from'}) =~ /[<]?mailer-daemon[@].*mail[.]ru[>]?/;  | 
| 
22
 | 
51
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
404
 | 
     return undef unless $mhead->{'message-id'} =~ /[.](?:mail[.]ru|smailru[.]net)[>]\z/;  | 
| 
23
 | 
51
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
705
 | 
     return undef unless $mhead->{'subject'} =~ qr{(?:  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          Mail[ ]delivery[ ]failed(:[ ]returning[ ]message[ ]to[ ]sender)?  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         |Warning:[ ]message[ ].+[ ]delayed[ ]+  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         |Delivery[ ]Status[ ]Notification  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         |Mail[ ]failure  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         |Message[ ]frozen  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         |error[(]s[)][ ]in[ ]forwarding[ ]or[ ]filtering  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         )  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }x;  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
33
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
158
 | 
     state $indicators = __PACKAGE__->INDICATORS;  | 
| 
34
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
102
 | 
     state $rebackbone = qr|^------ This is a copy of the message, including all the headers[.] ------|m;  | 
| 
35
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
92
 | 
     state $startingof = { 'message' => ['This message was created automatically by mail delivery software.'] };  | 
| 
36
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
126
 | 
     state $recommands = [  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         qr/SMTP error from remote (?:mail server|mailer) after ([A-Za-z]{4})/,  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         qr/SMTP error from remote (?:mail server|mailer) after end of ([A-Za-z]{4})/,  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ];  | 
| 
40
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
122
 | 
     state $messagesof = {  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         'expired'     => [  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'retry timeout exceeded',  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'No action is required on your part',  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ],  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         'userunknown' => ['user not found'],  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         'hostunknown' => [  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'all host address lookups failed permanently',  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'all relevant MX records point to non-existent hosts',  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'Unrouteable address',  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ],  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         'mailboxfull' => [  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'mailbox is full',  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'error: quota exceed',  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ],  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         'notaccept'   => [  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'an MX or SRV record indicated no SMTP service',  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'no host found for existing SMTP connection',  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ],  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         'systemerror' => [  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'delivery to file forbidden',  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'delivery to pipe forbidden',  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'local delivery failed',  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ],  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         'contenterror'=> ['Too many "Received" headers '],  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
67
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
197
 | 
     my $dscontents = [__PACKAGE__->DELIVERYSTATUS];  | 
| 
68
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
352
 | 
     my $emailsteak = Sisimai::RFC5322->fillet($mbody, $rebackbone);  | 
| 
69
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
179
 | 
     my $readcursor = 0;     # (Integer) Points the current cursor position  | 
| 
70
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
153
 | 
     my $recipients = 0;     # (Integer) The number of 'Final-Recipient' header  | 
| 
71
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
92
 | 
     my $localhost0 = '';    # (String) Local MTA  | 
| 
72
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
128
 | 
     my $v = undef;  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
74
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
559
 | 
     for my $e ( split("\n", $emailsteak->[0]) ) {  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Read error messages and delivery status lines from the head of the email  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # to the previous line of the beginning of the original message.  | 
| 
77
 | 
1091
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1489
 | 
         unless( $readcursor ) {  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # Beginning of the bounce message or message/delivery-status part  | 
| 
79
 | 
724
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1443
 | 
             $readcursor |= $indicators->{'deliverystatus'} if index($e, $startingof->{'message'}->[0]) == 0;  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
81
 | 
1091
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1711
 | 
         next unless $readcursor & $indicators->{'deliverystatus'};  | 
| 
82
 | 
418
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
630
 | 
         next unless length $e;  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Это письмо создано автоматически  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # сервером Mail.Ru, # отвечать на него не  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # нужно.  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         #  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # К сожалению, Ваше письмо не может  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # быть# доставлено одному или нескольким  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # получателям:  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         #  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # **********************  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         #  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # This message was created automatically by mail delivery software.  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         #  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # A message that you sent could not be delivered to one or more of its  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # recipients. This is a permanent error. The following address(es) failed:  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         #  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         #  kijitora@example.jp  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         #    SMTP error from remote mail server after RCPT TO::  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         #    host neko.example.jp [192.0.2.222]: 550 5.1.1 ... User Unknown  | 
| 
102
 | 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
377
 | 
         $v = $dscontents->[-1];  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
104
 | 
316
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1251
 | 
         if( $e =~ /\A[ \t]+([^ \t]+[@][^ \t]+[.][a-zA-Z]+)\z/ ) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             #   kijitora@example.jp  | 
| 
106
 | 
56
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
190
 | 
             if( $v->{'recipient'} ) {  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 # There are multiple recipient addresses in the message body.  | 
| 
108
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
                 push @$dscontents, __PACKAGE__->DELIVERYSTATUS;  | 
| 
109
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
                 $v = $dscontents->[-1];  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
111
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
192
 | 
             $v->{'recipient'} = $1;  | 
| 
112
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
130
 | 
             $recipients++;  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif( scalar @$dscontents == $recipients ) {  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # Error message  | 
| 
116
 | 
107
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
247
 | 
             next unless length $e;  | 
| 
117
 | 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
376
 | 
             $v->{'diagnosis'} .= $e.' ';  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # Error message when email address above does not include '@'  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # and domain part.  | 
| 
122
 | 
153
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
434
 | 
             next unless $e =~ /\A[ \t]{4}/;  | 
| 
123
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $v->{'alterrors'} .= $e.' ';  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
127
 | 
51
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
286
 | 
     unless( $recipients ) {  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Fallback for getting recipient addresses  | 
| 
129
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if( defined $mhead->{'x-failed-recipients'} ) {  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # X-Failed-Recipients: kijitora@example.jp  | 
| 
131
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             my @rcptinhead = split(',', $mhead->{'x-failed-recipients'});  | 
| 
132
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $_ =~ y/ //d for @rcptinhead;  | 
| 
133
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $recipients = scalar @rcptinhead;  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
135
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             for my $e ( @rcptinhead ) {  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 # Insert each recipient address into @$dscontents  | 
| 
137
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 $dscontents->[-1]->{'recipient'} = $e;  | 
| 
138
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 next if scalar @$dscontents == $recipients;  | 
| 
139
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 push @$dscontents, __PACKAGE__->DELIVERYSTATUS;  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
143
 | 
51
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
144
 | 
     return undef unless $recipients;  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
145
 | 
51
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
129
 | 
     if( scalar @{ $mhead->{'received'} } ) {  | 
| 
 
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
179
 | 
    | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Get the name of local MTA  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Received: from marutamachi.example.org (c192128.example.net [192.0.2.128])  | 
| 
148
 | 
51
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
364
 | 
         $localhost0 = $1 if $mhead->{'received'}->[-1] =~ /from[ \t]([^ ]+) /;  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
151
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
135
 | 
     for my $e ( @$dscontents ) {  | 
| 
152
 | 
56
 | 
  
  0
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
136
 | 
         if( exists $e->{'alterrors'} && $e->{'alterrors'} ) {  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # Copy alternative error message  | 
| 
154
 | 
  
0
  
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
             $e->{'diagnosis'} ||= $e->{'alterrors'};  | 
| 
155
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
             if( index($e->{'diagnosis'}, '-') == 0 || substr($e->{'diagnosis'}, -2, 2) eq '__' ) {  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 # Override the value of diagnostic code message  | 
| 
157
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 $e->{'diagnosis'} = $e->{'alterrors'} if $e->{'alterrors'};  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
159
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             delete $e->{'alterrors'};  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
161
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
379
 | 
         $e->{'diagnosis'} =  Sisimai::String->sweep($e->{'diagnosis'});  | 
| 
162
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
331
 | 
         $e->{'diagnosis'} =~ s/\b__.+\z//;  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
164
 | 
56
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
196
 | 
         unless( $e->{'rhost'} ) {  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # Get the remote host name  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # host neko.example.jp [192.0.2.222]: 550 5.1.1 ... User Unknown  | 
| 
167
 | 
56
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
381
 | 
             $e->{'rhost'} = $1 if $e->{'diagnosis'} =~ /host[ \t]+([^ \t]+)[ \t]\[.+\]:[ \t]/;  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
169
 | 
56
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
175
 | 
             unless( $e->{'rhost'} ) {  | 
| 
170
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
28
 | 
                 if( scalar @{ $mhead->{'received'} } ) {  | 
| 
 
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
53
 | 
    | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     # Get localhost and remote host name from Received header.  | 
| 
172
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
                     my $r0 = $mhead->{'received'};  | 
| 
173
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
                     $e->{'rhost'} = pop @{ Sisimai::RFC5322->received($r0->[-1]) };  | 
| 
 
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
51
 | 
    | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
177
 | 
56
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
296
 | 
         $e->{'lhost'} ||= $localhost0;  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
179
 | 
56
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
144
 | 
         unless( $e->{'command'} ) {  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # Get the SMTP command name for the session  | 
| 
181
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
148
 | 
             SMTP: for my $r ( @$recommands ) {  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 # Verify each regular expression of SMTP commands  | 
| 
183
 | 
76
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
568
 | 
                 next unless $e->{'diagnosis'} =~ $r;  | 
| 
184
 | 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
151
 | 
                 $e->{'command'} = uc $1;  | 
| 
185
 | 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
134
 | 
                 last;  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
188
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
91
 | 
             REASON: while(1) {  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 # Detect the reason of bounce  | 
| 
190
 | 
56
 | 
  
100
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
381
 | 
                 if( $e->{'command'} eq 'MAIL' ) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     # MAIL | Connected to 192.0.2.135 but sender was rejected.  | 
| 
192
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
                     $e->{'reason'} = 'rejected';  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif( $e->{'command'} eq 'HELO' || $e->{'command'} eq 'EHLO' ) {  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     # HELO | Connected to 192.0.2.135 but my name was rejected.  | 
| 
196
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     $e->{'reason'} = 'blocked';  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } else {  | 
| 
199
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
250
 | 
                     SESSION: for my $r ( keys %$messagesof ) {  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         # Verify each regular expression of session errors  | 
| 
201
 | 
313
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
341
 | 
                         next unless grep { index($e->{'diagnosis'}, $_) > -1 } @{ $messagesof->{ $r } };  | 
| 
 
 | 
626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1649
 | 
    | 
| 
 
 | 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
577
 | 
    | 
| 
202
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
56
 | 
                         $e->{'reason'} = $r;  | 
| 
203
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
                         last;  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
206
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
124
 | 
                 last;  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
209
 | 
56
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
204
 | 
         $e->{'command'} ||= '';  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
211
 | 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
294
 | 
     return { 'ds' => $dscontents, 'rfc822' => $emailsteak->[1] };  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |