File Coverage

lib/Sisimai/Lhost/Verizon.pm
Criterion Covered Total %
statement 79 83 95.1
branch 41 50 82.0
condition 12 22 54.5
subroutine 6 6 100.0
pod 2 2 100.0
total 140 163 85.8


line stmt bran cond sub pod time code
1             package Sisimai::Lhost::Verizon;
2 38     38   4780 use parent 'Sisimai::Lhost';
  38         80  
  38         287  
3 38     38   3070 use v5.26;
  38         159  
4 38     38   227 use strict;
  38         69  
  38         1121  
5 38     38   197 use warnings;
  38         96  
  38         59734  
6              
7 1     1 1 5 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 899     899 1 5094 my $class = shift;
16 899   100     2681 my $mhead = shift // return undef;
17 898   100     4897 my $mbody = shift // return undef;
18              
19 897 100       2689 return undef unless grep { rindex($_, '.vtext.com (') > -1 } $mhead->{'received'}->@*;
  1741         4801  
20 11 100       24 my $match = -1; $match = 1 if $mhead->{'from'} eq 'post_master@vtext.com';
  11         57  
21 11 100       111 $match = 0 if Sisimai::String->aligned(\$mhead->{'from'}, ['sysadmin@', '.vzwpix.com']);
22 11 50       53 return undef if $match < 0;
23              
24 11         52 state $indicators = __PACKAGE__->INDICATORS;
25 11         28 my $boundaries = [];
26 11         71 my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; my $v = undef;
  11         29  
27 11         27 my $emailparts = [];
28 11         23 my $readcursor = 0; # (Integer) Points the current cursor position
29 11         50 my $recipients = 0; # (Integer) The number of 'Final-Recipient' header
30 11         26 my $senderaddr = ''; # (String) Sender address in the message body
31 11         30 my $subjecttxt = ''; # (String) Subject of the original message
32 11         23 my $messagesof = {}; # (Ref->Hash) Error message patterns
33              
34 11 100       55 if( $match == 1 ) {
35             # vtext.com
36 5         20 my $markingsof = {'message' => ['Error: ']};
37 5         24 $messagesof = {
38             # The attempted recipient address does not exist.
39             'userunknown' => ['550 - Requested action not taken: no such user here'],
40             };
41 5         35 $boundaries = [Sisimai::RFC2045->boundary($mhead->{'content-type'}, 1)];
42 5         30 $emailparts = Sisimai::RFC5322->part($mbody, $boundaries);
43              
44 5         39 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       124 unless( $readcursor ) {
48             # Beginning of the bounce message or delivery status part
49 5 50       33 $readcursor |= $indicators->{'deliverystatus'} if index($e, $markingsof->{'message'}->[0]) == 0;
50 5         13 next;
51             }
52 65 100 66     204 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         350 $v = $dscontents->[-1];
60              
61 55 100       171 if( index($e, ' RCPT TO: ') == 0 ) {
    100          
    100          
62 5 50       17 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         14 $v->{'recipient'} = substr($e, 11,);
68 5         9 $recipients++;
69 5         10 next;
70              
71             } elsif( index($e, ' MAIL FROM: ') == 0 ) {
72             # MAIL FROM: *******@hg.example.com
73 5   33     26 $senderaddr ||= substr($e, 13,);
74              
75             } elsif( index($e, ' Subject: ') == 0 ) {
76             # Subject:
77 5   33     33 $subjecttxt ||= substr($e, 11,);
78              
79             } else {
80             # 550 - Requested action not taken: no such user here
81 40 100       110 $v->{'diagnosis'} = $e if index($e, ' - ') > 2;
82             }
83             }
84             } else {
85             # vzwpix.com
86 6         36 my $startingof = {'message' => ['Message could not be delivered to mobile']};
87 6         29 $messagesof = {'userunknown' => ['No valid recipients for this MM']};
88 6         56 $boundaries = [Sisimai::RFC2045->boundary($mhead->{'content-type'})];
89 6         37 $emailparts = Sisimai::RFC5322->part($mbody, $boundaries);
90 6         58 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       135 unless( $readcursor ) {
94             # Beginning of the bounce message or delivery status part
95 6 50       52 $readcursor |= $indicators->{'deliverystatus'} if index($e, $startingof->{'message'}->[0]) == 0;
96 6         14 next;
97             }
98 48 100 66     224 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         64 $v = $dscontents->[-1];
106              
107 36 100       210 if( index($e, 'To: ') == 0 ) {
    100          
    100          
108 6 50       24 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         37 $v->{'recipient'} = Sisimai::Address->s3s4(substr($e, 4,));
114 6         17 $recipients++;
115 6         14 next;
116              
117             } elsif( index($e, 'From: ') == 0 ) {
118             # From: kijitora
119 6   33     70 $senderaddr ||= Sisimai::Address->s3s4(substr($e, 6,));
120              
121             } elsif( index($e, 'Subject: ') == 0 ) {
122             # Subject:
123 6   33     33 $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       95 $v->{'diagnosis'} = Sisimai::String->sweep(substr($e, 7,)) if index($e, 'Error: ') == 0;
129             }
130             }
131             }
132 11 50       67 return undef unless $recipients;
133              
134             # Set the value of "MAIL FROM:" and "From:"
135 11 50       94 $emailparts->[1] .= sprintf("From: %s\n", $senderaddr) if index($emailparts->[1], "\nFrom: ") < 0;
136 11 50       83 $emailparts->[1] .= sprintf("Subject: %s\n", $subjecttxt) if index($emailparts->[1], "\nSubject: ") < 0;
137              
138 11         46 for my $e ( @$dscontents ) {
139 11         81 $e->{'diagnosis'} = Sisimai::String->sweep($e->{'diagnosis'});
140              
141 11         42 SESSION: for my $r ( keys %$messagesof ) {
142             # Verify each regular expression of session errors
143 11 50       37 next unless grep { index($e->{'diagnosis'}, $_) > -1 } $messagesof->{ $r }->@*;
  11         58  
144 11         41 $e->{'reason'} = $r;
145 11         25 last;
146             }
147             }
148 11         110 return {"ds" => $dscontents, "rfc822" => $emailparts->[1]};
149             }
150              
151             1;
152             __END__