File Coverage

lib/Haineko/SMTPD/Milter/Example.pm
Criterion Covered Total %
statement 61 63 96.8
branch 21 28 75.0
condition 21 29 72.4
subroutine 9 9 100.0
pod 6 6 100.0
total 118 135 87.4


line stmt bran cond sub pod time code
1             package Haineko::SMTPD::Milter::Example;
2 2     2   3010 use strict;
  2         6  
  2         97  
3 2     2   12 use warnings;
  2         6  
  2         69  
4 2     2   2197 use parent 'Haineko::SMTPD::Milter';
  2         661  
  2         11  
5              
6             sub conn {
7 4     4 1 1802 my $class = shift;
8 4   100     16 my $nekor = shift || return 1; # (Haineko::SMTPD::Response) Object
9 3         8 my $argvs = [ @_ ];
10              
11 3   50     11 my $remotehost = $argvs->[0] // q();
12 3   100     12 my $remoteaddr = $argvs->[1] // q();
13              
14 3 100       12 if( $remotehost eq 'localhost.localdomain' ) {
    100          
15             # Reject ``localhost.localdomain''
16 1         5 $nekor->error(1);
17 1         13 $nekor->message( [ 'Error message here' ] );
18              
19             } elsif( $remoteaddr eq '255.255.255.255' ) {
20             # Reject ``255.255.255.255''
21 1         4 $nekor->error(1);
22 1         9 $nekor->message( [ 'Broadcast address' ] );
23              
24             # Or Check REMOTE_ADDR with DNSBL...
25             }
26              
27 3 100       21 return $nekor->error ? 0 : 1;
28             }
29              
30             sub ehlo {
31 3     3 1 1492 my $class = shift;
32 3   100     13 my $nekor = shift || return 1; # (Haineko::SMTPD::Response) Object
33 2   50     6 my $argvs = shift // q(); # (String) Hostname or IP address
34              
35 2 100       9 if( $argvs =~ m/[.]local\z/ ) {
36             # Reject ``EHLO *.local''
37 1         4 $nekor->code(521);
38 1         8 $nekor->error(1);
39 1         8 $nekor->message( [ 'Invalid domain ".local"' ] );
40             }
41              
42 2 100       8 return $nekor->error ? 0 : 1;
43             }
44              
45             sub mail {
46 3     3 1 1802 my $class = shift;
47 3   100     13 my $nekor = shift || return 1; # (Haineko::SMTPD::Response) Object
48 2   50     6 my $argvs = shift // q(); # (String) Envelope sender address
49              
50 2         5 my $invalidtld = [ 'local', 'test', 'invalid' ];
51 2         4 my $spamsender = [ 'spammer@example.com', 'spammer@example.net' ];
52              
53 2 50       5 if( grep { $argvs =~ m/[.]$_\z/ } @$invalidtld ) {
  6 100       72  
  4         12  
54             # Reject by domain part of envelope sender address
55 0         0 $nekor->error(1);
56 0         0 $nekor->message( [ 'sender domain does not exist' ] );
57              
58             } elsif( grep { $argvs eq $_ } @$spamsender ) {
59             # Not allowed address
60 1         4 $nekor->error(1);
61 1         9 $nekor->message( [ 'spammer is not allowed to send'] );
62             }
63              
64 2 100       11 return $nekor->error ? 0 : 1;
65             }
66              
67             sub rcpt {
68 2     2 1 2081 my $class = shift;
69 2   100     12 my $nekor = shift || return 1; # (Haineko::SMTPD::Response) Object
70 1   50     5 my $argvs = shift // []; # (String) Envelope recipient addresses
71 1         2 my $bccto = 'always-bcc@example.jp';
72              
73 1 50       2 push @$argvs, $bccto unless grep { $bccto eq $_ } @$argvs;
  1         6  
74 1 50       5 return $nekor->error ? 0 : 1;
75             }
76              
77             sub head {
78 2     2 1 1447 my $class = shift;
79 2   100     10 my $nekor = shift || return 1; # (Haineko::SMTPD::Response) Object
80 1   50     8 my $argvs = shift // {}; # (Ref->Hash) Email header
81              
82 1 50 33     11 if( exists $argvs->{'subject'} && $argvs->{'subject'} =~ /spam/i ) {
83             # Reject if the subject contains text ``spam''
84 1         4 $nekor->error(1);
85 1         9 $nekor->dsn('5.7.1');
86 1         8 $nekor->message( [ 'DO NOT SEND spam' ] );
87             }
88              
89 1 50       7 return $nekor->error ? 0 : 1;
90             }
91              
92             sub body {
93 2     2 1 4149 my $class = shift;
94 2   100     10 my $nekor = shift || return 1; # (Haineko::SMTPD::Response) Object
95 1   50     4 my $argvs = shift // return 1; # (Ref->Scalar) Email body
96              
97 1 50       7 if( $$argvs =~ m{https?://} ) {
98             # Do not include any URL in email body
99 1         5 $nekor->error(1);
100 1         9 $nekor->message( [ 'Not allowed to send an email including URL' ] );
101             }
102              
103 1 50       7 return $nekor->error ? 0 : 1;
104             }
105              
106             1;
107             __END__