File Coverage

lib/Sisimai/LDA.pm
Criterion Covered Total %
statement 28 28 100.0
branch 10 10 100.0
condition 7 7 100.0
subroutine 4 4 100.0
pod 0 1 0.0
total 49 50 98.0


line stmt bran cond sub pod time code
1             package Sisimai::LDA;
2 85     85   143070 use v5.26;
  85         292  
3 85     85   420 use strict;
  85         162  
  85         2164  
4 85     85   400 use warnings;
  85         136  
  85         49368  
5              
6             state $LocalAgent = {
7             # Each error message should be a lower-cased string
8             # dovecot/src/deliver/deliver.c
9             # 11: #define DEFAULT_MAIL_REJECTION_HUMAN_REASON \
10             # 12: "Your message to <%t> was automatically rejected:%n%r"
11             "dovecot" => ["Your message to <", "> was automatically rejected:"],
12             "mail.local" => ["mail.local: "],
13             "procmail" => ["procmail: ", "/procmail "],
14             "maildrop" => ["maildrop: "],
15             "vpopmail" => ["vdelivermail: "],
16             "vmailmgr" => ["vdeliver: "],
17             };
18              
19             state $MessagesOf = {
20             # Each error message should be a lower-cased string
21             "dovecot" => {
22             # dovecot/src/deliver/mail-send.c:94
23             "mailboxfull" => [
24             "not enough disk space",
25             "quota exceeded", # Dovecot 1.2 dovecot/src/plugins/quota/quota.c
26             "quota exceeded (mailbox for user is full)", # dovecot/src/plugins/quota/quota.c
27             ],
28             "userunknown" => ["mailbox doesn't exist: "],
29             },
30             "mail.local" => {
31             "mailboxfull" => ["disc quota exceeded", "mailbox full or quota exceeded"],
32             "systemerror" => ["temporary file write error"],
33             "userunknown" => [
34             ": invalid mailbox path",
35             ": unknown user:",
36             ": user missing home directory",
37             ": user unknown",
38             ],
39             },
40             "procmail" => {
41             "mailboxfull" => ["quota exceeded while writing", "user over quota"],
42             "systemerror" => ["service unavailable"],
43             "systemfull" => ["no space left to finish writing"],
44             },
45             "maildrop" => {
46             "mailboxfull" => ["maildir over quota."],
47             "userunknown" => ["invalid user specified.", "cannot find system user"],
48             },
49             "vpopmail" => {
50             "filtered" => ["user does not exist, but will deliver to "],
51             "mailboxfull" => ["domain is over quota", "user is over quota"],
52             "suspend" => ["account is locked email bounced"],
53             "userunknown" => ["sorry, no mailbox here by that name."],
54             },
55             "vmailmgr" => {
56             "mailboxfull" => ["delivery failed due to system quota violation"],
57             "userunknown" => [
58             "invalid or unknown base user or domain",
59             "invalid or unknown virtual user",
60             "user name does not refer to a virtual user"
61             ],
62             },
63             };
64              
65             sub find {
66             # Decode the message body and return a bounce reason detected by the error message of LDA
67             # @param [Sisimai::Fact] argvs Decoded email object
68             # @return [String] The value of bounce reason
69 3268     3268 0 11389 my $class = shift;
70 3268   100     8916 my $argvs = shift // return "";
71              
72 3267 100       10010 return "" unless length $argvs->{"diagnosticcode"};
73 3257 100 100     18788 return "" unless $argvs->{"command"} eq "" || $argvs->{"command"} eq "DATA";
74              
75 2267         3977 my $deliversby = ""; # [String] Local Delivery Agent name
76 2267         4047 my $reasontext = ""; # [String] Detected bounce reason
77 2267         7331 my $issuedcode = lc $argvs->{"diagnosticcode"};
78              
79 2267         11733 for my $e ( keys %$LocalAgent ) {
80             # Find a local delivery agent name from the lower-cased error message
81 13525 100       26156 next unless grep { index($issuedcode, $_) > -1 } $LocalAgent->{ $e }->@*;
  18025         45275  
82 37         73 $deliversby = $e; last;
  37         72  
83             }
84 2267 100       11633 return "" unless $deliversby;
85              
86 37         175 for my $e ( keys $MessagesOf->{ $deliversby }->%* ) {
87             # The key nane is a bounce reason name
88 71 100       176 next unless grep { index($issuedcode, $_) > -1 } $MessagesOf->{ $deliversby }->{ $e }->@*;
  120         299  
89 25         73 $reasontext = $e; last;
  25         39  
90             }
91              
92 37   100     163 $reasontext ||= "mailererror"; # procmail: Couldn't create "/var/mail/tmp.nekochan.22"
93 37         108 return $reasontext;
94             }
95              
96             1;
97             __END__