File Coverage

lib/Sisimai/Lhost/Activehunter.pm
Criterion Covered Total %
statement 41 43 95.3
branch 15 18 83.3
condition 10 16 62.5
subroutine 6 6 100.0
pod 2 2 100.0
total 74 85 87.0


line stmt bran cond sub pod time code
1             package Sisimai::Lhost::Activehunter;
2 35     35   4814 use parent 'Sisimai::Lhost';
  35         76  
  35         247  
3 35     35   2928 use v5.26;
  35         123  
4 35     35   209 use strict;
  35         306  
  35         1035  
5 35     35   320 use warnings;
  35         85  
  35         22316  
6              
7 1     1 1 6 sub description { 'TransWARE Active!hunter' };
8             sub inquire {
9             # Detect an error from QUALITIA Active!hunter
10             # @param [Hash] mhead Message headers of a bounce email
11             # @param [String] mbody Message body of a bounce email
12             # @return [Hash] Bounce data list and message/rfc822 part
13             # @return [undef] failed to decode or the arguments are missing
14             # @since v4.1.1
15 878     878 1 3143 my $class = shift;
16 878 100 100     2437 my $mhead = shift // return undef; return undef unless defined $mhead->{'x-ahmailid'};
  877         4998  
17 11   50     37 my $mbody = shift // return undef;
18              
19 11         37 state $indicators = __PACKAGE__->INDICATORS;
20 11         27 state $boundaries = ['Content-Type: message/rfc822'];
21 11         38 state $startingof = {'message' => [' ----- The following addresses had permanent fatal errors -----']};
22              
23 11         90 my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; my $v = undef;
  11         27  
24 11         57 my $emailparts = Sisimai::RFC5322->part($mbody, $boundaries);
25 11         19 my $readcursor = 0; # (Integer) Points the current cursor position
26 11         22 my $recipients = 0; # (Integer) The number of 'Final-Recipient' header
27              
28 11         113 for my $e ( split("\n", $emailparts->[0]) ) {
29             # Read error messages and delivery status lines from the head of the email to the previous
30             # line of the beginning of the original message.
31 121 100       202 unless( $readcursor ) {
32             # Beginning of the bounce message or delivery status part
33 66 100       166 $readcursor |= $indicators->{'deliverystatus'} if index($e, $startingof->{'message'}->[0]) == 0;
34 66         99 next;
35             }
36 55 100 66     227 next if ($readcursor & $indicators->{'deliverystatus'}) == 0 || $e eq "";
37              
38             # ----- The following addresses had permanent fatal errors -----
39             #
40             # >>> kijitora@example.org
41             #
42             # ----- Transcript of session follows -----
43             # 550 sorry, no mailbox here by that name (#5.1.1 - chkusr)
44 33         52 $v = $dscontents->[-1];
45              
46 33 100 66     151 if( index($e, '>>> ') == 0 && index($e, '@') > 1 ) {
47             # >>> kijitora@example.org
48 11 50       35 if( $v->{'recipient'} ) {
49             # There are multiple recipient addresses in the message body.
50 0         0 push @$dscontents, __PACKAGE__->DELIVERYSTATUS;
51 0         0 $v = $dscontents->[-1];
52             }
53 11         101 $v->{'recipient'} = Sisimai::Address->s3s4(substr($e, index($e, '<'),));
54 11         42 $recipients++;
55              
56             } else {
57             # ----- Transcript of session follows -----
58             # 550 sorry, no mailbox here by that name (#5.1.1 - chkusr)
59 22         40 my $p = ord(substr($e, 0, 1));
60 22 100 66     81 next if $p < 48 || $p > 122;
61 11 50       58 next if length $v->{'diagnosis'};
62 11   33     59 $v->{'diagnosis'} ||= $e;
63             }
64             }
65 11 50       57 return undef unless $recipients;
66              
67 11         75 $_->{'diagnosis'} = Sisimai::String->sweep($_->{'diagnosis'}) for @$dscontents;
68 11         67 return {"ds" => $dscontents, "rfc822" => $emailparts->[1]};
69             }
70              
71             1;
72             __END__