| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Sisimai::Lhost::X6; | 
| 2 | 14 |  |  | 14 |  | 5374 | use parent 'Sisimai::Lhost'; | 
|  | 14 |  |  |  |  | 27 |  | 
|  | 14 |  |  |  |  | 66 |  | 
| 3 | 14 |  |  | 14 |  | 731 | use feature ':5.10'; | 
|  | 14 |  |  |  |  | 17 |  | 
|  | 14 |  |  |  |  | 869 |  | 
| 4 | 14 |  |  | 14 |  | 86 | use strict; | 
|  | 14 |  |  |  |  | 19 |  | 
|  | 14 |  |  |  |  | 240 |  | 
| 5 | 14 |  |  | 14 |  | 57 | use warnings; | 
|  | 14 |  |  |  |  | 32 |  | 
|  | 14 |  |  |  |  | 7523 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 | 2 |  |  | 2 | 1 | 939 | sub description { 'Unknown MTA #6' } | 
| 8 |  |  |  |  |  |  | sub make { | 
| 9 |  |  |  |  |  |  | # Detect an error from Unknown MTA #6 | 
| 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 parse or the arguments are missing | 
| 14 |  |  |  |  |  |  | # @since v4.25.6 | 
| 15 | 193 |  |  | 193 | 1 | 551 | my $class = shift; | 
| 16 | 193 |  | 100 |  |  | 444 | my $mhead = shift // return undef; | 
| 17 | 192 |  | 50 |  |  | 484 | my $mbody = shift // return undef; | 
| 18 | 192 | 100 |  |  |  | 652 | return undef unless index($mhead->{'subject'}, 'There was an error sending your mail') == 0; | 
| 19 |  |  |  |  |  |  |  | 
| 20 | 11 |  |  |  |  | 39 | state $indicators = __PACKAGE__->INDICATORS; | 
| 21 | 11 |  |  |  |  | 22 | state $rebackbone = qr/^The attachment contains the original mail headers.+$/m; | 
| 22 | 11 |  |  |  |  | 24 | state $markingsof = { 'message' => qr/\A\d+[ ]*error[(]s[)]:/ }; | 
| 23 |  |  |  |  |  |  |  | 
| 24 | 11 |  |  |  |  | 55 | my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; | 
| 25 | 11 |  |  |  |  | 66 | my $emailsteak = Sisimai::RFC5322->fillet($mbody, $rebackbone); | 
| 26 | 11 |  |  |  |  | 24 | my $readcursor = 0;     # (Integer) Points the current cursor position | 
| 27 | 11 |  |  |  |  | 19 | my $recipients = 0;     # (Integer) The number of 'Final-Recipient' header | 
| 28 | 11 |  |  |  |  | 18 | my $v = undef; | 
| 29 |  |  |  |  |  |  |  | 
| 30 | 11 |  |  |  |  | 58 | for my $e ( split("\n", $emailsteak->[0]) ) { | 
| 31 |  |  |  |  |  |  | # Read error messages and delivery status lines from the head of the email | 
| 32 |  |  |  |  |  |  | # to the previous line of the beginning of the original message. | 
| 33 | 110 | 100 |  |  |  | 133 | unless( $readcursor ) { | 
| 34 |  |  |  |  |  |  | # Beginning of the bounce message or message/delivery-status part | 
| 35 | 88 | 100 |  |  |  | 225 | $readcursor |= $indicators->{'deliverystatus'} if $e =~ $markingsof->{'message'}; | 
| 36 | 88 |  |  |  |  | 99 | next; | 
| 37 |  |  |  |  |  |  | } | 
| 38 | 22 | 50 |  |  |  | 44 | next unless $readcursor & $indicators->{'deliverystatus'}; | 
| 39 | 22 | 100 |  |  |  | 39 | next unless length $e; | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | # 1 error(s): | 
| 42 |  |  |  |  |  |  | # | 
| 43 |  |  |  |  |  |  | # SMTP Server  rejected recipient | 
| 44 |  |  |  |  |  |  | #   (Error following RCPT command). It responded as follows: [550 5.1.1 User unknown] | 
| 45 | 11 |  |  |  |  | 18 | $v = $dscontents->[-1]; | 
| 46 | 11 | 50 | 66 |  |  | 95 | if( $e =~ /<([^ @]+[@][^ @]+)>/ || $e =~ /errors:[ ]*([^ ]+[@][^ ]+)/ ) { | 
| 47 |  |  |  |  |  |  | # SMTP Server  rejected recipient | 
| 48 |  |  |  |  |  |  | # The following recipients returned permanent errors: neko@example.jp. | 
| 49 | 11 | 50 |  |  |  | 28 | if( $v->{'recipient'} ) { | 
| 50 |  |  |  |  |  |  | # There are multiple recipient addresses in the message body. | 
| 51 | 0 |  |  |  |  | 0 | push @$dscontents, __PACKAGE__->DELIVERYSTATUS; | 
| 52 | 0 |  |  |  |  | 0 | $v = $dscontents->[-1]; | 
| 53 |  |  |  |  |  |  | } | 
| 54 | 11 |  |  |  |  | 59 | $v->{'recipient'} = Sisimai::Address->s3s4($1); | 
| 55 | 11 |  |  |  |  | 21 | $v->{'diagnosis'} = $e; | 
| 56 | 11 |  |  |  |  | 22 | $recipients++; | 
| 57 |  |  |  |  |  |  | } | 
| 58 |  |  |  |  |  |  | } | 
| 59 | 11 | 50 |  |  |  | 36 | return undef unless $recipients; | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 11 |  |  |  |  | 21 | for my $e ( @$dscontents ) { | 
| 62 |  |  |  |  |  |  | # Get the last SMTP command from the error message | 
| 63 | 11 | 50 |  |  |  | 90 | if( $e->{'diagnosis'} =~ /\b(HELO|EHLO|MAIL|RCPT|DATA)\b/ ) { | 
| 64 |  |  |  |  |  |  | # ...(Error following RCPT command). | 
| 65 | 11 |  |  |  |  | 28 | $e->{'command'} = $1; | 
| 66 |  |  |  |  |  |  | } | 
| 67 | 11 |  |  |  |  | 68 | $e->{'diagnosis'} = Sisimai::String->sweep($e->{'diagnosis'}); | 
| 68 |  |  |  |  |  |  | } | 
| 69 | 11 |  |  |  |  | 46 | return { 'ds' => $dscontents, 'rfc822' => $emailsteak->[1] }; | 
| 70 |  |  |  |  |  |  | } | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | 1; | 
| 73 |  |  |  |  |  |  | __END__ |