File Coverage

blib/lib/Mail/POPRelay.pm
Criterion Covered Total %
statement 12 111 10.8
branch 0 64 0.0
condition n/a
subroutine 4 14 28.5
pod 5 7 71.4
total 21 196 10.7


line stmt bran cond sub pod time code
1             package Mail::POPRelay;
2              
3 1     1   41827 use strict;
  1         5  
  1         46  
4 1     1   494 use Mail::Object;
  1         3  
  1         30  
5 1     1   6 use vars qw[$VERSION @ISA ];
  1         2  
  1         49  
6              
7 1     1   5 use constant PRESERVE_MESSAGE => "# Above configuration will be preserved by POPRelay.\n";
  1         1  
  1         2933  
8              
9             $VERSION = '2.1.1';
10             @ISA = qw[Mail::Object ];
11              
12             $Mail::POPRelay::DEBUG = 0;
13              
14              
15             # check any given hash for existence of certain keys
16             # ---------
17             sub __initTest {
18 0     0     my $self = shift;
19 0           my %qaTest = %{; shift};
  0            
20              
21 0           foreach (keys %qaTest) {
22 0 0         die sprintf "%s was not specified.\n", $qaTest{$_} unless defined $self->{$_};
23             }
24 0           return $self;
25             }
26              
27              
28             # ---------
29             sub initWithConfigFile {
30 0     0 0   my $configFileName = splice(@_, 1, 1);
31              
32 0 0         die "Missing argument config-file." unless $configFileName;
33 0 0         die "$configFileName: No such file exists." unless -f $configFileName;
34              
35             # slurp config file
36 0           undef $/;
37 0 0         open CONFIG, $configFileName or die "Unable to open config-file $configFileName: $!";
38 0           my $configFile = ;
39 0           close CONFIG;
40 0           $/ = "\n"; # disable slurp mode
41            
42             # create a hash from the config file
43 0           my $options;
44 0           $configFile =~ s,(.*?=)([\s\t]*)(.*),$1>$2'$3'\,,g;
45 0           eval "\$options = { $configFile };";
46 0 0         die "Corrupted config-file $configFileName: $@" if $@;
47              
48             # store config file used
49 0 0         $_[0]->addAttributeWithValue('configFile', $configFileName)
50             unless $_[0]->respondsTo('configFile');
51            
52             # initialize a POPRelay subclass w/ config file hash
53 0           return Mail::POPRelay::init(@_, $options);
54             }
55              
56              
57             # ---------
58             sub init {
59             # call proper init if necessary
60 0 0   0 0   return Mail::POPRelay::initWithConfigFile(@_) unless ref $_[1];
61              
62 0           my $myDefaults = {
63             mailLogFile => '/var/log/maillog',
64             mailProgram => 'sendmail',
65             mailProgramRestart => 0,
66             mailProgramRestartCommand => '/etc/init.d/%m restart',
67             mailRelayIsDatabase => 0,
68             mailRelayDatabaseCommand => '/usr/sbin/makemap hash %r < %r',
69             mailRelayDirectory => '/var/spool/poprelay',
70             };
71 0           splice(@_, 2, 0, splice(@_, 1, 1, $myDefaults));
72 0           my $self = Mail::Object::init(@_);
73            
74 0           my %qualityAssurance = (
75             mailLogFile => 'Mail log file',
76             mailProgram => 'Mail program',
77             mailRelayDirectory => 'Mail relay directory',
78             mailRelayFile => 'Mail relay file',
79             mailRelayPeriod => 'Mail relay period',
80             mailRelayFileFormat => 'Mail relay file format',
81             );
82 0           $self->__initTest(\%qualityAssurance);
83              
84 0 0         $self->addAttribute('relayPreserve') unless
85             $self->respondsTo('relayPreserve');
86              
87             # parse special option variables
88 0           foreach ($self->{'mailRelayFileFormat'}, $self->{'mailProgramRestartCommand'}, $self->{'mailRelayDatabaseCommand'}) {
89 0           s,%m,$self->{'mailProgram'},gi;
90 0           s,%r,$self->{'mailRelayFile'},gi;
91             }
92              
93             $self->__createRelayDirectory()
94 0 0         unless (-d $self->{'mailRelayDirectory'});
95              
96 0           return $self;
97             }
98              
99              
100             # ---------
101             sub restartMailProgram {
102 0     0 1   my $self = shift;
103              
104 0           $self->{'mailProgramRestartCommand'} =~ s,%m,$self->{'mailProgram'},ig;
105              
106 0 0         print "o Restarting mail program: $self->{'mailProgramRestartCommand'}"
107             if $Mail::POPRelay::DEBUG;
108 0           return `$self->{'mailProgramRestartCommand'}`;
109             }
110              
111              
112             # purge all relay address files in spool
113             # ---------
114             sub wipeRelayDirectory {
115 0     0 1   my $self = shift;
116              
117 0 0         print "o Wiping relay directory\n" if $Mail::POPRelay::DEBUG;
118 0           my $mailRelayDirectory = $self->{'mailRelayDirectory'};
119 0           foreach (<$mailRelayDirectory/*>) {
120 0 0         unlink($_) or die "Unable to remove $_: $!";
121             }
122 0           return $self;
123             }
124              
125              
126             # purge only expired relay address files in spool
127             # ---------
128             sub cleanRelayDirectory {
129 0     0 1   my $self = shift;
130              
131 0 0         print "o Cleaning relay directory\n" if $Mail::POPRelay::DEBUG;
132 0           my($mailRelayDirectory, @purgeCount) = ($self->{'mailRelayDirectory'}, 0);
133 0           foreach (<$mailRelayDirectory/*>) {
134 0           chomp();
135 0 0         my $modifyTime = (stat("$_"))[8] or die "Unable to stat $_: $!";
136              
137 0 0         if (time > ($modifyTime + $self->{'mailRelayPeriod'})) {
138 0 0         printf "\t`- removing %s (%d - %d < %d)\n", $_, time, ($modifyTime + $self->{'mailRelayDirectory'}, $self->{'mailRelayPeriod'}) if $Mail::POPRelay::DEBUG;
139 0 0         unlink($_) or die "Unable to unlink $_: $!";
140 0           push @purgeCount, $_;
141             }
142             }
143 0 0         return wantarray ? @purgeCount : scalar @purgeCount;
144             }
145              
146              
147             # add relay address file to spool
148             # ---------
149             sub addRelayAddress {
150 0     0 1   my $self = shift;
151 0           my $userName = shift;
152 0           my $userIpAddress = shift;
153              
154 0 0         if (!-e "$self->{'mailRelayDirectory'}/$userIpAddress") {
155 0 0         open(OUT, ">$self->{'mailRelayDirectory'}/$userIpAddress") or die "Unable to open $self->{'mailRelayDirectory'}/$userIpAddress: $!";
156 0           print OUT $userName;
157 0           close(OUT);
158 0           return $self;
159             }
160              
161 0           return 0;
162             }
163              
164              
165             # ---------
166             sub __generatePreserveList {
167 0     0     my $self = shift;
168              
169 0           my @preserveList;
170 0           my $mailRelayFile = $self->{'mailRelayFile'};
171 0 0         open(PACCESS, "<$mailRelayFile") or die "Unable to open $mailRelayFile: $!";
172 0           while () {
173 0 0         last if $_ eq PRESERVE_MESSAGE;
174 0           push @preserveList, $_;
175             }
176 0           close(PACCESS);
177 0           return join('', @preserveList);
178             }
179              
180              
181             # ---------
182             sub __createRelayDirectory {
183 0     0     my $self = shift;
184              
185 0 0         die "Unable to create mail relay directory: $!" unless
186             mkdir($self->{'mailRelayDirectory'}, 0027);
187              
188 0           return $self;
189             }
190              
191              
192             # write out entire relaying file
193             # ---------
194             sub generateRelayFile {
195 0     0 1   my $self = shift;
196              
197 0           my @relayArray;
198 0           my $mailRelayDirectory = $self->{'mailRelayDirectory'};
199            
200 0 0         $self->__createRelayDirectory()
201             unless (-d $self->{'mailRelayDirectory'});
202              
203             # build relay list
204 0           my $entry;
205 0 0         print "o Building the relay file\n" if $Mail::POPRelay::DEBUG;
206 0           foreach (<$mailRelayDirectory/*>) {
207 0           s,.*/([\d\.]+)$,$1,;
208 0 0         print "\t`- adding $_\n" if $Mail::POPRelay::DEBUG;
209 0           $entry = $self->{'mailRelayFileFormat'};
210 0           $entry =~ s,%i,$_,g;
211 0           push @relayArray, $entry;
212             }
213              
214             # recreate preserve list incase of change
215 0           $self->{'relayPreserve'} = $self->__generatePreserveList();
216              
217 0           my $mailRelayFile = $self->{'mailRelayFile'};
218 0 0         open(RACCESS, ">$mailRelayFile") or die "Unable to open $mailRelayFile: $!";
219 0           print RACCESS $self->{'relayPreserve'}, PRESERVE_MESSAGE, join("\n", @relayArray);
220 0           close RACCESS;
221              
222             # generate relay database if needed
223 0 0         if ($self->{'mailRelayIsDatabase'}) {
224 0 0         print "o Generating relay database\n" if $Mail::POPRelay::DEBUG;
225 0 0         warn "Error generating relay database with command: $self->{'mailRelayDatabaseCommand'}\n" if
226             system($self->{'mailRelayDatabaseCommand'});
227             }
228              
229             # restart mail server if needed
230 0 0         if ($self->{'mailProgramRestart'}) {
231 0           sleep(3);
232 0 0         print "o Restarting mail daemon\n" if $Mail::POPRelay::DEBUG;
233 0           $self->restartMailProgram();
234             }
235 0           return $self;
236             }
237              
238              
239             1337;
240              
241              
242             __END__