File Coverage

lib/Sisimai/Lhost/Activehunter.pm
Criterion Covered Total %
statement 40 42 95.2
branch 15 18 83.3
condition 10 16 62.5
subroutine 6 6 100.0
pod 2 2 100.0
total 73 84 86.9


line stmt bran cond sub pod time code
1             package Sisimai::Lhost::Activehunter;
2 36     36   3670 use parent 'Sisimai::Lhost';
  36         51  
  36         183  
3 36     36   2365 use v5.26;
  36         201  
4 36     36   147 use strict;
  36         59  
  36         831  
5 36     36   116 use warnings;
  36         62  
  36         15778  
6              
7 1     1 1 3 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 876     876 1 2783 my $class = shift;
16 876 100 100     1747 my $mhead = shift // return undef; return undef unless defined $mhead->{'x-ahmailid'};
  875         2311  
17 11   50     30 my $mbody = shift // return undef;
18              
19 11         34 state $indicators = __PACKAGE__->INDICATORS;
20 11         19 state $boundaries = ['Content-Type: message/rfc822'];
21 11         22 state $startingof = {'message' => [' ----- The following addresses had permanent fatal errors -----']};
22              
23 11         52 my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; my $v = undef;
  11         22  
24 11         54 my $emailparts = Sisimai::RFC5322->part($mbody, $boundaries);
25 11         18 my $readcursor = 0; # (Integer) Points the current cursor position
26 11         16 my $recipients = 0; # (Integer) The number of 'Final-Recipient' header
27              
28 11         66 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       159 unless( $readcursor ) {
32             # Beginning of the bounce message or delivery status part
33 66 100       177 $readcursor |= $indicators->{'deliverystatus'} if index($e, $startingof->{'message'}->[0]) == 0;
34 66         75 next;
35             }
36 55 100 66     191 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         43 $v = $dscontents->[-1];
45              
46 33 100 66     97 if( index($e, '>>> ') == 0 && index($e, '@') > 1 ) {
47             # >>> kijitora@example.org
48 11 50       32 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         81 $v->{'recipient'} = Sisimai::Address->s3s4(substr($e, index($e, '<'),));
54 11         32 $recipients++;
55              
56             } else {
57             # ----- Transcript of session follows -----
58             # 550 sorry, no mailbox here by that name (#5.1.1 - chkusr)
59 22         31 my $p = ord(substr($e, 0, 1));
60 22 100 66     64 next if $p < 48 || $p > 122;
61 11 50       28 next if length $v->{'diagnosis'};
62 11   33     46 $v->{'diagnosis'} ||= $e;
63             }
64             }
65 11 50       34 return undef unless $recipients;
66 11         54 return {"ds" => $dscontents, "rfc822" => $emailparts->[1]};
67             }
68              
69             1;
70             __END__