| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Sisimai::Lhost::ApacheJames; | 
| 2 | 18 |  |  | 18 |  | 6091 | use parent 'Sisimai::Lhost'; | 
|  | 18 |  |  |  |  | 35 |  | 
|  | 18 |  |  |  |  | 94 |  | 
| 3 | 18 |  |  | 18 |  | 1140 | use feature ':5.10'; | 
|  | 18 |  |  |  |  | 39 |  | 
|  | 18 |  |  |  |  | 1236 |  | 
| 4 | 18 |  |  | 18 |  | 113 | use strict; | 
|  | 18 |  |  |  |  | 35 |  | 
|  | 18 |  |  |  |  | 408 |  | 
| 5 | 18 |  |  | 18 |  | 92 | use warnings; | 
|  | 18 |  |  |  |  | 28 |  | 
|  | 18 |  |  |  |  | 14593 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 | 2 |  |  | 2 | 1 | 1245 | sub description { 'Java Apache Mail Enterprise Server' } | 
| 8 |  |  |  |  |  |  | sub make { | 
| 9 |  |  |  |  |  |  | # Detect an error from ApacheJames | 
| 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.1.26 | 
| 15 | 208 |  |  | 208 | 1 | 682 | my $class = shift; | 
| 16 | 208 |  | 100 |  |  | 661 | my $mhead = shift // return undef; | 
| 17 | 207 |  | 50 |  |  | 459 | my $mbody = shift // return undef; | 
| 18 | 207 |  |  |  |  | 328 | my $match = 0; | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | # 'subject'    => qr/\A\[BOUNCE\]\z/, | 
| 21 |  |  |  |  |  |  | # 'received'   => qr/JAMES SMTP Server/, | 
| 22 |  |  |  |  |  |  | # 'message-id' => qr/\d+[.]JavaMail[.].+[@]/, | 
| 23 | 207 | 50 | 0 |  |  | 589 | $match ||= 1 if $mhead->{'subject'} eq '[BOUNCE]'; | 
| 24 | 207 | 100 | 50 |  |  | 1128 | $match ||= 1 if defined $mhead->{'message-id'} && rindex($mhead->{'message-id'}, '.JavaMail.') > -1; | 
|  |  |  | 100 |  |  |  |  | 
| 25 | 207 | 50 | 0 |  |  | 328 | $match ||= 1 if grep { rindex($_, 'JAMES SMTP Server') > -1 } @{ $mhead->{'received'} }; | 
|  | 386 |  |  |  |  | 1028 |  | 
|  | 207 |  |  |  |  | 484 |  | 
| 26 | 207 | 100 |  |  |  | 641 | return undef unless $match; | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 6 |  |  |  |  | 32 | state $indicators = __PACKAGE__->INDICATORS; | 
| 29 | 6 |  |  |  |  | 21 | state $rebackbone = qr|^Content-Type:[ ]message/rfc822|m; | 
| 30 | 6 |  |  |  |  | 22 | state $startingof = { | 
| 31 |  |  |  |  |  |  | # apache-james-2.3.2/src/java/org/apache/james/transport/mailets/ | 
| 32 |  |  |  |  |  |  | #   AbstractNotify.java|124:  out.println("Error message below:"); | 
| 33 |  |  |  |  |  |  | #   AbstractNotify.java|128:  out.println("Message details:"); | 
| 34 |  |  |  |  |  |  | 'message' => [''], | 
| 35 |  |  |  |  |  |  | 'error'   => ['Error message below:'], | 
| 36 |  |  |  |  |  |  | }; | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 6 |  |  |  |  | 25 | my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; | 
| 39 | 6 |  |  |  |  | 37 | my $emailsteak = Sisimai::RFC5322->fillet($mbody, $rebackbone); | 
| 40 | 6 |  |  |  |  | 17 | my $readcursor = 0;     # (Integer) Points the current cursor position | 
| 41 | 6 |  |  |  |  | 17 | my $recipients = 0;     # (Integer) The number of 'Final-Recipient' header | 
| 42 | 6 |  |  |  |  | 15 | my $diagnostic = '';    # (String) Alternative diagnostic message | 
| 43 | 6 |  |  |  |  | 10 | my $subjecttxt = undef; # (String) Alternative Subject text | 
| 44 | 6 |  |  |  |  | 11 | my $gotmessage = 0;     # (Integer) Flag for error message | 
| 45 | 6 |  |  |  |  | 8 | my $v = undef; | 
| 46 |  |  |  |  |  |  |  | 
| 47 | 6 |  |  |  |  | 61 | for my $e ( split("\n", $emailsteak->[0]) ) { | 
| 48 |  |  |  |  |  |  | # Read error messages and delivery status lines from the head of the email | 
| 49 |  |  |  |  |  |  | # to the previous line of the beginning of the original message. | 
| 50 | 114 | 100 |  |  |  | 165 | unless( $readcursor ) { | 
| 51 |  |  |  |  |  |  | # Beginning of the bounce message or message/delivery-status part | 
| 52 | 6 | 50 |  |  |  | 29 | $readcursor |= $indicators->{'deliverystatus'} if index($e, $startingof->{'message'}->[0]) == 0; | 
| 53 | 6 |  |  |  |  | 12 | next; | 
| 54 |  |  |  |  |  |  | } | 
| 55 | 108 | 50 |  |  |  | 168 | next unless $readcursor & $indicators->{'deliverystatus'}; | 
| 56 | 108 | 100 |  |  |  | 156 | next unless length $e; | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | # Message details: | 
| 59 |  |  |  |  |  |  | #   Subject: Nyaaan | 
| 60 |  |  |  |  |  |  | #   Sent date: Thu Apr 29 01:20:50 JST 2015 | 
| 61 |  |  |  |  |  |  | #   MAIL FROM: shironeko@example.jp | 
| 62 |  |  |  |  |  |  | #   RCPT TO: kijitora@example.org | 
| 63 |  |  |  |  |  |  | #   From: Neko | 
| 64 |  |  |  |  |  |  | #   To: kijitora@example.org | 
| 65 |  |  |  |  |  |  | #   Size (in bytes): 1024 | 
| 66 |  |  |  |  |  |  | #   Number of lines: 64 | 
| 67 | 84 |  |  |  |  | 105 | $v = $dscontents->[-1]; | 
| 68 |  |  |  |  |  |  |  | 
| 69 | 84 | 100 |  |  |  | 272 | if( $e =~ /\A[ ][ ]RCPT[ ]TO:[ ]([^ ]+[@][^ ]+)\z/ ) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | #   RCPT TO: kijitora@example.org | 
| 71 | 6 | 50 |  |  |  | 25 | if( $v->{'recipient'} ) { | 
| 72 |  |  |  |  |  |  | # There are multiple recipient addresses in the message body. | 
| 73 | 0 |  |  |  |  | 0 | push @$dscontents, __PACKAGE__->DELIVERYSTATUS; | 
| 74 | 0 |  |  |  |  | 0 | $v = $dscontents->[-1]; | 
| 75 |  |  |  |  |  |  | } | 
| 76 | 6 |  |  |  |  | 18 | $v->{'recipient'} = $1; | 
| 77 | 6 |  |  |  |  | 10 | $recipients++; | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | } elsif( $e =~ /\A[ ][ ]Sent[ ]date:[ ](.+)\z/ ) { | 
| 80 |  |  |  |  |  |  | #   Sent date: Thu Apr 29 01:20:50 JST 2015 | 
| 81 | 6 |  |  |  |  | 18 | $v->{'date'} = $1; | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | } elsif( $e =~ /\A[ ][ ]Subject:[ ](.+)\z/ ) { | 
| 84 |  |  |  |  |  |  | #   Subject: Nyaaan | 
| 85 | 6 |  |  |  |  | 29 | $subjecttxt = $1; | 
| 86 |  |  |  |  |  |  |  | 
| 87 |  |  |  |  |  |  | } else { | 
| 88 | 66 | 100 |  |  |  | 102 | next if $gotmessage == 1; | 
| 89 |  |  |  |  |  |  |  | 
| 90 | 24 | 100 |  |  |  | 51 | if( $v->{'diagnosis'} ) { | 
| 91 |  |  |  |  |  |  | # Get an error message text | 
| 92 | 18 | 100 |  |  |  | 35 | if( $e eq 'Message details:' ) { | 
| 93 |  |  |  |  |  |  | # Message details: | 
| 94 |  |  |  |  |  |  | #   Subject: nyaan | 
| 95 |  |  |  |  |  |  | #   ... | 
| 96 | 6 |  |  |  |  | 16 | $gotmessage = 1; | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | } else { | 
| 99 |  |  |  |  |  |  | # Append error message text like the followng: | 
| 100 |  |  |  |  |  |  | #   Error message below: | 
| 101 |  |  |  |  |  |  | #   550 - Requested action not taken: no such user here | 
| 102 | 12 |  |  |  |  | 38 | $v->{'diagnosis'} .= ' '.$e; | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  | } else { | 
| 105 |  |  |  |  |  |  | # Error message below: | 
| 106 |  |  |  |  |  |  | # 550 - Requested action not taken: no such user here | 
| 107 | 6 | 50 |  |  |  | 18 | $v->{'diagnosis'} = $e if $e eq $startingof->{'error'}->[0]; | 
| 108 | 6 | 50 |  |  |  | 32 | $v->{'diagnosis'} .= ' '.$e unless $gotmessage; | 
| 109 |  |  |  |  |  |  | } | 
| 110 |  |  |  |  |  |  | } | 
| 111 |  |  |  |  |  |  | } | 
| 112 | 6 | 50 |  |  |  | 31 | return undef unless $recipients; | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | # Set the value of $subjecttxt as a Subject if there is no original message | 
| 115 |  |  |  |  |  |  | # in the bounce mail. | 
| 116 | 6 | 50 |  |  |  | 43 | $emailsteak->[1] .= sprintf("Subject: %s\n", $subjecttxt) unless $emailsteak->[1] =~ /^Subject:/m; | 
| 117 | 6 |  | 33 |  |  | 56 | $_->{'diagnosis'} = Sisimai::String->sweep($_->{'diagnosis'} || $diagnostic) for @$dscontents; | 
| 118 | 6 |  |  |  |  | 48 | return { 'ds' => $dscontents, 'rfc822' => $emailsteak->[1] }; | 
| 119 |  |  |  |  |  |  | } | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | 1; | 
| 122 |  |  |  |  |  |  | __END__ |