File Coverage

lib/Sisimai/SMTP/Error.pm
Criterion Covered Total %
statement 51 51 100.0
branch 23 24 95.8
condition 27 28 96.4
subroutine 7 7 100.0
pod 2 2 100.0
total 110 112 98.2


line stmt bran cond sub pod time code
1             package Sisimai::SMTP::Error;
2 79     79   69547 use feature ':5.10';
  79         191  
  79         5955  
3 79     79   533 use strict;
  79         200  
  79         1639  
4 79     79   368 use warnings;
  79         165  
  79         1956  
5 79     79   30149 use Sisimai::SMTP::Reply;
  79         196  
  79         2409  
6 79     79   41100 use Sisimai::SMTP::Status;
  79         204  
  79         39522  
7              
8             sub is_permanent {
9             # Permanent error or not
10             # @param [String] argv1 String including SMTP Status code
11             # @return [Integer] 1: Permanet error
12             # 0: Temporary error
13             # undef: is not an error
14             # @since v4.17.3
15 625     625 1 8182 my $class = shift;
16 625   100     1531 my $argv1 = shift || return undef;
17              
18 614   100     1501 my $statuscode = Sisimai::SMTP::Status->find($argv1) || Sisimai::SMTP::Reply->find($argv1) || '';
19 614         1218 my $parmanent1 = undef;
20              
21 614 100 100     2608 if( (my $classvalue = int(substr($statuscode, 0, 1) || 0)) > 0 ) {
22             # 2, 4, or 5
23 236 100       775 if( $classvalue == 5 ) {
    100          
    50          
24             # Permanent error
25 224         433 $parmanent1 = 1;
26              
27             } elsif( $classvalue == 4 ) {
28             # Temporary error
29 11         18 $parmanent1 = 0;
30              
31             } elsif( $classvalue == 2 ) {
32             # Succeeded
33 1         2 $parmanent1 = undef;
34             }
35             } else {
36             # Check with regular expression
37 378         1139 my $v = lc $argv1;
38 378 100 66     2600 if( rindex($v, 'temporar') > -1 || rindex($v, 'persistent') > -1 ) {
    100          
39             # Temporary failure
40 10         35 $parmanent1 = 0;
41              
42             } elsif( rindex($v, 'permanent') > -1 ) {
43             # Permanently failure
44 20         70 $parmanent1 = 1;
45              
46             } else {
47             # did not find information to decide that it is a soft bounce
48             # or a hard bounce.
49 348         576 $parmanent1 = undef;
50             }
51             }
52 614         1289 return $parmanent1;
53             }
54              
55             sub soft_or_hard {
56             # Check softbounce or not
57             # @param [String] argv1 Detected bounce reason
58             # @param [String] argv2 String including SMTP Status code
59             # @return [String] 'soft': Soft bounce
60             # 'hard': Hard bounce
61             # '': May not be bounce ?
62             # @since v4.17.3
63 2849     2849 1 33427 my $class = shift;
64 2849   100     5984 my $argv1 = shift || return undef;
65 2848   100     5662 my $argv2 = shift || '';
66 2848         3675 my $value = undef;
67              
68 2848         5163 state $softorhard = {
69             'soft' => [qw|
70             blocked contenterror exceedlimit expired filtered mailboxfull mailererror
71             mesgtoobig networkerror norelaying policyviolation rejected securityerror
72             spamdetected suspend syntaxerror systemerror systemfull toomanyconn virusdetected
73             |],
74             'hard' => [qw|hasmoved hostunknown userunknown|],
75             };
76              
77 2848 100 100     17475 if( $argv1 eq 'delivered' || $argv1 eq 'feedback' || $argv1 eq 'vacation' ) {
    100 100        
    100 100        
78             # These are not dealt as a bounce reason
79 3         5 $value = '';
80              
81             } elsif( $argv1 eq 'onhold' || $argv1 eq 'undefined' ) {
82             # It should be "soft" when a reason is "onhold" or "undefined"
83 45         165 $value = 'soft';
84              
85             } elsif( $argv1 eq 'notaccept' ) {
86             # NotAccept: 5xx => hard bounce, 4xx => soft bounce
87 38 100       155 if( $argv2 ) {
88             # Get D.S.N. or SMTP reply code from The 2nd argument string
89 37   100     181 my $statuscode = Sisimai::SMTP::Status->find($argv2) || Sisimai::SMTP::Reply->find($argv2) || '';
90 37   100     253 my $classvalue = int(substr($statuscode, 0, 1) || 0);
91 37 100       144 $value = $classvalue == 4 ? 'soft' : 'hard';
92              
93             } else {
94             # "notaccept" is a hard bounce
95 1         2 $value = 'hard';
96             }
97             } else {
98             # Check all the reasons defined at the above
99 2762         4593 SOFT_OR_HARD: for my $e ('hard', 'soft') {
100             # Soft or Hard?
101 4614         4759 for my $f ( @{ $softorhard->{ $e } } ) {
  4614         7916  
102             # Hard bounce?
103 22341 100       33529 next unless $argv1 eq $f;
104 2761         3804 $value = $e;
105 2761         5282 last(SOFT_OR_HARD);
106             }
107             }
108             }
109 2848   100     5351 $value //= '';
110 2848         5767 return $value;
111             }
112              
113             1;
114             __END__