File Coverage

lib/Sisimai/Lhost/Verizon.pm
Criterion Covered Total %
statement 78 82 95.1
branch 41 50 82.0
condition 12 22 54.5
subroutine 6 6 100.0
pod 2 2 100.0
total 139 162 85.8


line stmt bran cond sub pod time code
1             package Sisimai::Lhost::Verizon;
2 39     39   3434 use parent 'Sisimai::Lhost';
  39         59  
  39         213  
3 39     39   2514 use v5.26;
  39         102  
4 39     39   144 use strict;
  39         67  
  39         785  
5 39     39   137 use warnings;
  39         76  
  39         32107  
6              
7 1     1 1 3 sub description { 'Verizon: https://www.verizon.com/' }
8             sub inquire {
9             # Detect an error from Verizon
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.0.0
15 897     897 1 2660 my $class = shift;
16 897   100     1677 my $mhead = shift // return undef;
17 896   100     1705 my $mbody = shift // return undef;
18              
19 895 100       1500 return undef unless grep { rindex($_, '.vtext.com (') > -1 } $mhead->{'received'}->@*;
  1728         3241  
20 11 100       18 my $match = -1; $match = 1 if $mhead->{'from'} eq 'post_master@vtext.com';
  11         38  
21 11 100       65 $match = 0 if Sisimai::String->aligned(\$mhead->{'from'}, ['sysadmin@', '.vzwpix.com']);
22 11 50       30 return undef if $match < 0;
23              
24 11         52 state $indicators = __PACKAGE__->INDICATORS;
25 11         15 my $boundaries = [];
26 11         66 my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; my $v = undef;
  11         21  
27 11         14 my $emailparts = [];
28 11         12 my $readcursor = 0; # (Integer) Points the current cursor position
29 11         17 my $recipients = 0; # (Integer) The number of 'Final-Recipient' header
30 11         18 my $senderaddr = ''; # (String) Sender address in the message body
31 11         15 my $subjecttxt = ''; # (String) Subject of the original message
32 11         25 my $messagesof = {}; # (Ref->Hash) Error message patterns
33              
34 11 100       24 if( $match == 1 ) {
35             # vtext.com
36 5         17 my $markingsof = {'message' => ['Error: ']};
37 5         66 $messagesof = {
38             # The attempted recipient address does not exist.
39             'userunknown' => ['550 - Requested action not taken: no such user here'],
40             };
41 5         26 $boundaries = [Sisimai::RFC2045->boundary($mhead->{'content-type'}, 1)];
42 5         31 $emailparts = Sisimai::RFC5322->part($mbody, $boundaries);
43              
44 5         30 for my $e ( split("\n", $emailparts->[0]) ) {
45             # Read error messages and delivery status lines from the head of the email to the previous
46             # line of the beginning of the original message.
47 70 100       96 unless( $readcursor ) {
48             # Beginning of the bounce message or delivery status part
49 5 50       22 $readcursor |= $indicators->{'deliverystatus'} if index($e, $markingsof->{'message'}->[0]) == 0;
50 5         9 next;
51             }
52 65 100 66     192 next if ($readcursor & $indicators->{'deliverystatus'}) == 0 || $e eq "";
53              
54             # Message details:
55             # Subject: Test message
56             # Sent date: Wed Jun 12 02:21:53 GMT 2013
57             # MAIL FROM: *******@hg.example.com
58             # RCPT TO: *****@vtext.com
59 55         57 $v = $dscontents->[-1];
60              
61 55 100       131 if( index($e, ' RCPT TO: ') == 0 ) {
    100          
    100          
62 5 50       13 if( $v->{'recipient'} ) {
63             # There are multiple recipient addresses in the message body.
64 0         0 push @$dscontents, __PACKAGE__->DELIVERYSTATUS;
65 0         0 $v = $dscontents->[-1];
66             }
67 5         12 $v->{'recipient'} = substr($e, 11,);
68 5         6 $recipients++;
69 5         8 next;
70              
71             } elsif( index($e, ' MAIL FROM: ') == 0 ) {
72             # MAIL FROM: *******@hg.example.com
73 5   33     19 $senderaddr ||= substr($e, 13,);
74              
75             } elsif( index($e, ' Subject: ') == 0 ) {
76             # Subject:
77 5   33     38 $subjecttxt ||= substr($e, 11,);
78              
79             } else {
80             # 550 - Requested action not taken: no such user here
81 40 100       76 $v->{'diagnosis'} = $e if index($e, ' - ') > 2;
82             }
83             }
84             } else {
85             # vzwpix.com
86 6         19 my $startingof = {'message' => ['Message could not be delivered to mobile']};
87 6         18 $messagesof = {'userunknown' => ['No valid recipients for this MM']};
88 6         24 $boundaries = [Sisimai::RFC2045->boundary($mhead->{'content-type'})];
89 6         22 $emailparts = Sisimai::RFC5322->part($mbody, $boundaries);
90 6         31 for my $e ( split("\n", $emailparts->[0]) ) {
91             # Read error messages and delivery status lines from the head of the email to the previous
92             # line of the beginning of the original message.
93 54 100       75 unless( $readcursor ) {
94             # Beginning of the bounce message or delivery status part
95 6 50       39 $readcursor |= $indicators->{'deliverystatus'} if index($e, $startingof->{'message'}->[0]) == 0;
96 6         10 next;
97             }
98 48 100 66     135 next if ($readcursor & $indicators->{'deliverystatus'}) == 0 || $e eq "";
99              
100             # Original Message:
101             # From: kijitora
102             # To: 0000000000@vzwpix.com
103             # Subject: test for bounce
104             # Date: Wed, 20 Jun 2013 10:29:52 +0000
105 36         42 $v = $dscontents->[-1];
106              
107 36 100       101 if( index($e, 'To: ') == 0 ) {
    100          
    100          
108 6 50       17 if( $v->{'recipient'} ) {
109             # There are multiple recipient addresses in the message body.
110 0         0 push @$dscontents, __PACKAGE__->DELIVERYSTATUS;
111 0         0 $v = $dscontents->[-1];
112             }
113 6         26 $v->{'recipient'} = Sisimai::Address->s3s4(substr($e, 4,));
114 6         15 $recipients++;
115 6         10 next;
116              
117             } elsif( index($e, 'From: ') == 0 ) {
118             # From: kijitora
119 6   33     79 $senderaddr ||= Sisimai::Address->s3s4(substr($e, 6,));
120              
121             } elsif( index($e, 'Subject: ') == 0 ) {
122             # Subject:
123 6   33     27 $subjecttxt ||= substr($e, 9,);
124              
125             } else {
126             # Message could not be delivered to mobile.
127             # Error: No valid recipients for this MM
128 18 100       52 $v->{'diagnosis'} = substr($e, 7,) if index($e, 'Error: ') == 0;
129             }
130             }
131             }
132 11 50       48 return undef unless $recipients;
133              
134             # Set the value of "MAIL FROM:" and "From:"
135 11 50       43 $emailparts->[1] .= sprintf("From: %s\n", $senderaddr) if index($emailparts->[1], "\nFrom: ") < 0;
136 11 50       68 $emailparts->[1] .= sprintf("Subject: %s\n", $subjecttxt) if index($emailparts->[1], "\nSubject: ") < 0;
137              
138 11         20 for my $e ( @$dscontents ) {
139 11         31 SESSION: for my $r ( keys %$messagesof ) {
140             # Verify each regular expression of session errors
141 11 50       25 next unless grep { index($e->{'diagnosis'}, $_) > -1 } $messagesof->{ $r }->@*;
  11         45  
142 11         18 $e->{'reason'} = $r;
143 11         23 last;
144             }
145             }
146 11         65 return {"ds" => $dscontents, "rfc822" => $emailparts->[1]};
147             }
148              
149             1;
150             __END__