File Coverage

lib/Sisimai/SMTP/Command.pm
Criterion Covered Total %
statement 47 47 100.0
branch 22 24 91.6
condition 19 31 61.2
subroutine 7 7 100.0
pod 2 2 100.0
total 97 111 87.3


line stmt bran cond sub pod time code
1             package Sisimai::SMTP::Command;
2 90     90   115256 use v5.26;
  90         351  
3 90     90   504 use strict;
  90         188  
  90         2541  
4 90     90   459 use warnings;
  90         201  
  90         5811  
5 90     90   539 use constant ExceptDATA => ["CONN", "EHLO", "HELO", "MAIL", "RCPT"];
  90         194  
  90         8931  
6 90     90   603 use constant BeforeRCPT => ["CONN", "EHLO", "EHLO", "MAIL", "AUTH", "STARTTLS"];
  90         249  
  90         58799  
7             state $Availables = [
8             "HELO", "EHLO", "MAIL", "RCPT", "DATA", "QUIT", "RSET", "NOOP", "VRFY", "ETRN", "EXPN", "HELP",
9             "AUTH", "STARTTLS", "XFORWARD",
10             "CONN", # CONN is a pseudo SMTP command used only in Sisimai
11             ];
12             state $Detectable = [
13             "HELO", "EHLO", "STARTTLS", "AUTH PLAIN", "AUTH LOGIN", "AUTH CRAM-", "AUTH DIGEST-", "MAIL F",
14             "RCPT", "RCPT T", "DATA", "QUIT", "XFORWARD",
15             ];
16              
17             sub test {
18             # Check that an SMTP command in the argument is valid or not
19             # @param [String] argv0 An SMTP command
20             # @return [Boolean] 0: Is not a valid SMTP command, 1: Is a valid SMTP command
21             # @since v5.0.0
22 7128     7128 1 245751 my $class = shift;
23 7128 100 100     26556 my $argv0 = shift // return 0; return 0 unless length $argv0 > 3;
  7127         22291  
24 5180 100       11495 return 1 if grep { index($argv0, $_) > -1 } @$Availables;
  82880         157126  
25 1961         12221 return 0;
26             }
27              
28             sub find {
29             # Pick an SMTP command from the given string
30             # @param [String] argv0 A transcript text MTA returned
31             # @return [String] An SMTP command
32             # @since v5.0.0
33 3500     3500 1 17608 my $class = shift;
34 3500 100 100     10041 my $argv0 = shift // return ""; return "" unless __PACKAGE__->test($argv0);
  3499         10658  
35              
36 1518         4982 my $issuedcode = ' '.lc($argv0).' ';
37 1518         8276 my $commandmap = {'STAR' => 'STARTTLS', 'XFOR' => 'XFORWARD'};
38 1518         2729 my $commandset = [];
39              
40 1518         3797 for my $e ( @$Detectable ) {
41             # Find an SMTP command from the given string
42 19734 100       30024 my $p0 = index($argv0, $e); next if $p0 < 0;
  19734         37386  
43 2085 100       6715 if( index($e, " ") < 0 ) {
44             # For example, "RCPT T" does not appear in an email address or a domain name
45 1282         2135 my $cx = 1; while(1) {
  1282         2217  
46             # Exclude an SMTP command in the part of an email address, a domain name, such as
47             # DATABASE@EXAMPLE.JP, EMAIL.EXAMPLE.COM, and so on.
48 1282         21793 my $ca = ord(substr($issuedcode, $p0, 1));
49 1282         3197 my $cz = ord(substr($issuedcode, $p0 + length($e) + 1, 1));
50              
51 1282 50 66     9083 last if $ca > 47 && $ca < 58 || $cz > 47 && $cz < 58; # 0-9
      66        
      33        
52 1282 100 66     11701 last if $ca > 63 && $ca < 91 || $cz > 63 && $cz < 91; # @-Z
      100        
      66        
53 1281 50 33     7620 last if $ca > 96 && $ca < 123 || $cz > 96 && $cz < 123; # `-z
      33        
      33        
54 1281         2030 $cx = 0; last;
  1281         2133  
55             }
56 1282 100       3387 next if $cx == 1;
57             }
58              
59             # There is the same command in the "commanset" or nor
60 2084 100       4722 my $cv = substr($e, 0, 4); next if grep { index($cv, $_) == 0 } @$commandset;
  2084         5192  
  571         2015  
61 1529 100       5088 $cv = $commandmap->{ $cv } if exists $commandmap->{ $cv };
62 1529         5288 push @$commandset, $cv;
63             }
64 1518 100       4474 return "" unless scalar @$commandset;
65 1513         9619 return pop @$commandset;
66             }
67              
68             1;
69             __END__