File Coverage

lib/Sisimai/Lhost/TrendMicro.pm
Criterion Covered Total %
statement 47 53 88.6
branch 22 30 73.3
condition 19 25 76.0
subroutine 6 6 100.0
pod 2 2 100.0
total 96 116 82.7


line stmt bran cond sub pod time code
1             package Sisimai::Lhost::TrendMicro;
2 41     41   4373 use parent 'Sisimai::Lhost';
  41         99  
  41         276  
3 41     41   3439 use v5.26;
  41         169  
4 41     41   227 use strict;
  41         91  
  41         1188  
5 41     41   185 use warnings;
  41         141  
  41         33824  
6              
7 1     1 1 5 sub description { 'TREND VISION ONE(Email and Collaboration Security)' }
8             sub inquire {
9             # Detect an error from TREND VISION ONE: Email and Collaboration Security
10             # https://www.trendmicro.com/en_us/business/products/email-and-collaboration.html
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 decode or the arguments are missing
15             # @since v4.1.2
16 930     930 1 3457 my $class = shift;
17 930   100     2522 my $mhead = shift // return undef;
18 929   100     2490 my $mbody = shift // return undef;
19 928         3165 my $tryto = [
20             'Mail could not be delivered',
21             'メッセージを配信できません。',
22             'メール配信に失敗しました',
23             ];
24 928 100 50     3641 my $match = 0; $match ||= 1 if index($mhead->{'from'}, '"InterScan MSS"') == 0;
  928         4031  
25 928 50 0     3639 $match ||= 1 if index($mhead->{'from'}, '"InterScan Notification"') == 0;
26 928 100 100     2212 $match ||= 1 if grep { $mhead->{'subject'} eq $_ } @$tryto;
  2784         8260  
27 928 100       3436 return undef unless $match;
28              
29 16         112 require Sisimai::SMTP::Command;
30 16         42 state $boundaries = ['Content-type: message/rfc822'];
31              
32 16         119 my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; my $v = undef;
  16         41  
33 16         125 my $emailparts = Sisimai::RFC5322->part($mbody, $boundaries);
34 16         38 my $recipients = 0; # (Integer) The number of 'Final-Recipient' header
35              
36 16         220 for my $e ( split("\n", $emailparts->[0]) ) {
37             # Read error messages and delivery status lines from the head of the email to the previous
38             # line of the beginning of the original message.
39 544 100       1037 next unless length $e;
40              
41 408         549 $v = $dscontents->[-1];
42 408         614 my $p1 = index($e, ' <<< '); # Sent <<< ...
43 408         675 my $p2 = index($e, ' >>> '); # Received >>> ...
44 408 100 100     1336 if( index($e, '@') > 1 && index($e, ' <') > 1 && ($p1 > 1 || $p2 > 1 || index($e, 'Unable to deliver ') > -1) ) {
      100        
      100        
45             # Sent <<< RCPT TO:
46             # Received >>> 550 5.1.1 ... user unknown
47             # Received >>> 550 5.1.1 unknown user.
48             # Unable to deliver message to
49             # Unable to deliver message to (and other recipients in the same domain).
50 22         106 my $cr = substr($e, rindex($e, '<') + 1, rindex($e, '>') - rindex($e, '<') - 1);
51 22 50 66     102 if( $v->{'recipient'} && $cr ne $v->{'recipient'} ) {
52             # There are multiple recipient addresses in the message body.
53 0         0 push @$dscontents, __PACKAGE__->DELIVERYSTATUS;
54 0         0 $v = $dscontents->[-1];
55             }
56 22         59 $v->{'recipient'} = $cr;
57 22 100       69 $v->{'diagnosis'} = $e if index($e, 'Unable to deliver ') > -1;
58 22         49 $recipients = scalar @$dscontents;
59             }
60              
61 408 100 33     1742 if( index($e, 'Sent <<< ') == 0 ) {
    100          
    50          
62             # Sent <<< RCPT TO:
63 6         69 $v->{'command'} = Sisimai::SMTP::Command->find($e);
64              
65             } elsif( index($e, 'Received >>> ') == 0 ) {
66             # Received >>> 550 5.1.1 ... user unknown
67 6         29 $v->{'diagnosis'} = substr($e, index($e, ' >>> ') + 4, );
68              
69             } elsif( $p1 > 0 || $p2 > 0 ) {
70             # Error message in non-English
71 0 0       0 $v->{'command'} = Sisimai::SMTP::Command->find($e) if index($e, ' >>> ') > -1;
72 0 0       0 my $p3 = index($e, ' <<< '); next if $p3 == -1;
  0         0  
73 0         0 $v->{'diagnosis'} = substr($e, $p3 + 4,);
74             }
75             }
76 16 50       137 return undef unless $recipients;
77              
78 16         50 for my $e ( @$dscontents ) {
79             # Set default values if each value is empty.
80 16         168 $e->{'diagnosis'} = Sisimai::String->sweep($e->{'diagnosis'});
81 16 100       93 $e->{'reason'} = 'userunknown' if index($e->{'diagnosis'}, 'Unable to deliver') > -1;
82             }
83 16         135 return {"ds" => $dscontents, "rfc822" => $emailparts->[1]};
84             }
85              
86             1;
87             __END__