File Coverage

lib/Sisimai/Lhost/GMX.pm
Criterion Covered Total %
statement 52 52 100.0
branch 19 22 86.3
condition 11 13 84.6
subroutine 6 6 100.0
pod 2 2 100.0
total 90 95 94.7


line stmt bran cond sub pod time code
1             package Sisimai::Lhost::GMX;
2 39     39   4459 use parent 'Sisimai::Lhost';
  39         79  
  39         267  
3 39     39   3278 use v5.26;
  39         137  
4 39     39   211 use strict;
  39         71  
  39         1048  
5 39     39   195 use warnings;
  39         112  
  39         43548  
6              
7 1     1 1 4 sub description { 'GMX: https://gmx.net/' }
8             sub inquire {
9             # Detect an error from GMX and mail.com
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.4
15 915     915 1 4101 my $class = shift;
16 915 100 100     5501 my $mhead = shift // return undef; return undef unless defined $mhead->{'x-gmx-antispam'};
  914         3862  
17 21   50     86 my $mbody = shift // return undef;
18              
19             # Envelope-To:
20             # X-GMX-Antispam: 0 (Mail was not recognized as spam); Detail=V3;
21             # X-GMX-Antivirus: 0 (no virus found)
22             # X-UI-Out-Filterresults: unknown:0;
23 21         92 require Sisimai::SMTP::Command;
24 21         64 state $indicators = __PACKAGE__->INDICATORS;
25 21         35 state $boundaries = ['--- The header of the original message is following. ---'];
26 21         48 state $startingof = {'message' => ['This message was created automatically by mail delivery software']};
27 21         52 state $messagesof = {'expired' => ['delivery retry timeout exceeded']};
28              
29 21         115 my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; my $v = undef;
  21         64  
30 21         101 my $emailparts = Sisimai::RFC5322->part($mbody, $boundaries);
31 21         36 my $readcursor = 0; # (Integer) Points the current cursor position
32 21         52 my $recipients = 0; # (Integer) The number of 'Final-Recipient' header
33              
34 21         161 for my $e ( split("\n", $emailparts->[0]) ) {
35             # Read error messages and delivery status lines from the head of the email to the previous
36             # line of the beginning of the original message.
37 230 100       446 unless( $readcursor ) {
38             # Beginning of the bounce message or message/delivery-status part
39 21 50       124 $readcursor |= $indicators->{'deliverystatus'} if index($e, $startingof->{'message'}->[0]) == 0;
40 21         48 next;
41             }
42 209 100 66     740 next if ($readcursor & $indicators->{'deliverystatus'}) == 0 || $e eq "";
43              
44             # This message was created automatically by mail delivery software.
45             #
46             # A message that you sent could not be delivered to one or more of
47             # its recipients. This is a permanent error. The following address
48             # failed:
49             #
50             # "shironeko@example.jp":
51             # SMTP error from remote server after RCPT command:
52             # host: mx.example.jp
53             # 5.1.1 ... User Unknown
54 162         264 $v = $dscontents->[-1];
55              
56 162 100 100     717 if( index($e, '@') > 1 && (index($e, '"') == 0 || index($e, '<') == 0) ) {
    100 100        
    100          
57             # "shironeko@example.jp":
58             # ---- OR ----
59             #
60             #
61             # Reason:
62             # delivery retry timeout exceeded
63 26 100       68 if( $v->{'recipient'} ) {
64             # There are multiple recipient addresses in the message body.
65 5         24 push @$dscontents, __PACKAGE__->DELIVERYSTATUS;
66 5         15 $v = $dscontents->[-1];
67             }
68 26         164 $v->{'recipient'} = Sisimai::Address->s3s4($e);
69 26         58 $recipients++;
70              
71             } elsif( index($e, 'SMTP error ') == 0 ) {
72             # SMTP error from remote server after RCPT command:
73 21         171 $v->{'command'} = Sisimai::SMTP::Command->find($e);
74              
75             } elsif( index($e, 'host: ') == 0 ) {
76             # host: mx.example.jp
77 21         59 $v->{'rhost'} = substr($e, 6, );
78              
79             } else {
80             # Get error messages
81 94 50       205 next unless $e;
82 94         235 $v->{'diagnosis'} .= $e." ";
83             }
84             }
85 21 50       179 return undef unless $recipients;
86              
87 21         45 for my $e ( @$dscontents ) {
88 26         66 $e->{'diagnosis'} =~ y/\n/ /;
89 26         132 $e->{'diagnosis'} = Sisimai::String->sweep($e->{'diagnosis'});
90              
91 26         87 SESSION: for my $r ( keys %$messagesof ) {
92             # Verify each regular expression of session errors
93 26 100       73 next unless grep { index($e->{'diagnosis'}, $_) > -1 } $messagesof->{ $r }->@*;
  26         125  
94 5         34 $e->{'reason'} = $r;
95 5         13 last;
96             }
97             }
98 21         142 return {"ds" => $dscontents, "rfc822" => $emailparts->[1]};
99             }
100              
101             1;
102             __END__