File Coverage

lib/Sisimai/Lhost/TrendMicro.pm
Criterion Covered Total %
statement 46 52 88.4
branch 22 30 73.3
condition 19 25 76.0
subroutine 6 6 100.0
pod 2 2 100.0
total 95 115 82.6


line stmt bran cond sub pod time code
1             package Sisimai::Lhost::TrendMicro;
2 42     42   3602 use parent 'Sisimai::Lhost';
  42         80  
  42         237  
3 42     42   2692 use v5.26;
  42         115  
4 42     42   143 use strict;
  42         78  
  42         845  
5 42     42   157 use warnings;
  42         83  
  42         25889  
6              
7 1     1 1 3 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 928     928 1 2820 my $class = shift;
17 928   100     1749 my $mhead = shift // return undef;
18 927   100     1593 my $mbody = shift // return undef;
19 926         2035 my $tryto = [
20             'Mail could not be delivered',
21             'メッセージを配信できません。',
22             'メール配信に失敗しました',
23             ];
24 926 100 50     1099 my $match = 0; $match ||= 1 if index($mhead->{'from'}, '"InterScan MSS"') == 0;
  926         2764  
25 926 50 0     2259 $match ||= 1 if index($mhead->{'from'}, '"InterScan Notification"') == 0;
26 926 100 100     1326 $match ||= 1 if grep { $mhead->{'subject'} eq $_ } @$tryto;
  2778         4288  
27 926 100       2155 return undef unless $match;
28              
29 16         50 require Sisimai::SMTP::Command;
30 16         24 state $boundaries = ['Content-type: message/rfc822'];
31              
32 16         85 my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; my $v = undef;
  16         24  
33 16         64 my $emailparts = Sisimai::RFC5322->part($mbody, $boundaries);
34 16         21 my $recipients = 0; # (Integer) The number of 'Final-Recipient' header
35              
36 16         190 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       548 next unless length $e;
40              
41 408         320 $v = $dscontents->[-1];
42 408         394 my $p1 = index($e, ' <<< '); # Sent <<< ...
43 408         382 my $p2 = index($e, ' >>> '); # Received >>> ...
44 408 100 100     705 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         73 my $cr = substr($e, rindex($e, '<') + 1, rindex($e, '>') - rindex($e, '<') - 1);
51 22 50 66     60 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         36 $v->{'recipient'} = $cr;
57 22 100       42 $v->{'diagnosis'} = $e if index($e, 'Unable to deliver ') > -1;
58 22         39 $recipients = scalar @$dscontents;
59             }
60              
61 408 100 33     984 if( index($e, 'Sent <<< ') == 0 ) {
    100          
    50          
62             # Sent <<< RCPT TO:
63 6         61 $v->{'command'} = Sisimai::SMTP::Command->find($e);
64              
65             } elsif( index($e, 'Received >>> ') == 0 ) {
66             # Received >>> 550 5.1.1 ... user unknown
67 6         16 $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       67 return undef unless $recipients;
77              
78 16         20 for my $e ( @$dscontents ) {
79             # Set default values if each value is empty.
80 16 100       54 $e->{'reason'} = 'userunknown' if index($e->{'diagnosis'}, 'Unable to deliver') > -1;
81             }
82 16         96 return {"ds" => $dscontents, "rfc822" => $emailparts->[1]};
83             }
84              
85             1;
86             __END__