line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mail::Toaster::Logs; |
2
|
1
|
|
|
1
|
|
948
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
27
|
|
3
|
1
|
|
|
1
|
|
3
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
36
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
our $VERSION = 5.50; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# the output of warnings and diagnostics should not be enabled in production. |
8
|
|
|
|
|
|
|
# the SNMP daemon depends on the output of maillogs, so we need to return |
9
|
|
|
|
|
|
|
# nothing or valid counters. |
10
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
4
|
use Carp; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
51
|
|
12
|
1
|
|
|
1
|
|
5
|
use English '-no_match_vars'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
7
|
|
13
|
1
|
|
|
1
|
|
343
|
use File::Path; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
39
|
|
14
|
1
|
|
|
1
|
|
4
|
use Getopt::Std; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
32
|
|
15
|
1
|
|
|
1
|
|
4
|
use Params::Validate ':all'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
134
|
|
16
|
1
|
|
|
1
|
|
4
|
use Pod::Usage; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
63
|
|
17
|
|
|
|
|
|
|
|
18
|
1
|
|
|
1
|
|
3
|
use vars qw( $spam_ref $count_ref ); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
38
|
|
19
|
|
|
|
|
|
|
|
20
|
1
|
|
|
1
|
|
3
|
use lib 'lib'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
6
|
|
21
|
1
|
|
|
1
|
|
138
|
use parent 'Mail::Toaster::Base'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
6
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
sub report_yesterdays_activity { |
24
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
25
|
0
|
|
|
|
|
|
my %p = validate(@_, { $self->get_std_opts } ); |
26
|
|
|
|
|
|
|
|
27
|
0
|
0
|
|
|
|
|
return $p{test_ok} if defined $p{test_ok}; |
28
|
|
|
|
|
|
|
|
29
|
0
|
|
0
|
|
|
|
my $email = $self->conf->{toaster_admin_email} || "postmaster"; |
30
|
0
|
0
|
|
|
|
|
my $qma_dir = $self->find_qmailanalog or return; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# if ( ! -s $self->get_yesterdays_smtp_log ) { |
33
|
|
|
|
|
|
|
# carp "no smtp log file for yesterday found!\n"; |
34
|
|
|
|
|
|
|
# return; |
35
|
|
|
|
|
|
|
# }; |
36
|
|
|
|
|
|
|
|
37
|
0
|
|
|
|
|
|
my $send_log = $self->get_yesterdays_send_log; |
38
|
0
|
0
|
|
|
|
|
if ( ! -s $send_log ) { |
39
|
0
|
|
|
|
|
|
carp "no send log file for yesterday found!\n"; |
40
|
0
|
|
|
|
|
|
return; |
41
|
|
|
|
|
|
|
}; |
42
|
|
|
|
|
|
|
|
43
|
0
|
|
|
|
|
|
$self->audit( "processing log: $send_log" ); |
44
|
|
|
|
|
|
|
|
45
|
0
|
0
|
|
|
|
|
my $cat = $send_log =~ m/\.bz2$/ ? $self->util->find_bin( "bzcat" ) |
|
|
0
|
|
|
|
|
|
46
|
|
|
|
|
|
|
: $send_log =~ m/\.gz$/ ? $self->util->find_bin( "gzcat" ) |
47
|
|
|
|
|
|
|
: $self->util->find_bin( "cat" ); |
48
|
|
|
|
|
|
|
|
49
|
0
|
|
|
|
|
|
my %cmds = ( |
50
|
|
|
|
|
|
|
overall => { cmd => "$qma_dir/zoverall" }, |
51
|
|
|
|
|
|
|
failure => { cmd => "$qma_dir/zfailures" }, |
52
|
|
|
|
|
|
|
deferral => { cmd => "$qma_dir/zdeferrals" }, |
53
|
|
|
|
|
|
|
); |
54
|
|
|
|
|
|
|
|
55
|
0
|
|
|
|
|
|
foreach ( keys %cmds ) { |
56
|
0
|
|
|
|
|
|
my $cmd = "$cat $send_log | $qma_dir/matchup 5>/dev/null | " . $cmds{$_}{cmd}; |
57
|
0
|
|
|
|
|
|
$self->audit( "calculating $_ stats with: $cmd"); |
58
|
0
|
|
|
|
|
|
$cmds{$_}{out} = `$cmd`; |
59
|
|
|
|
|
|
|
}; |
60
|
|
|
|
|
|
|
|
61
|
0
|
|
|
|
|
|
my ( $dd, $mm, $yy ) = $self->util->get_the_date(bump=>0); |
62
|
0
|
|
|
|
|
|
my $date = "$yy.$mm.$dd"; |
63
|
0
|
|
|
|
|
|
$self->audit( "date: $yy.$mm.$dd" ); |
64
|
|
|
|
|
|
|
|
65
|
0
|
|
|
|
|
|
open my $EMAIL, "| /var/qmail/bin/qmail-inject"; ## no critic (Open) |
66
|
0
|
|
|
|
|
|
print $EMAIL <<"EO_EMAIL"; |
67
|
|
|
|
|
|
|
To: $email |
68
|
|
|
|
|
|
|
From: postmaster |
69
|
|
|
|
|
|
|
Subject: Daily Mail Toaster Report for $date |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
==================================================================== |
72
|
|
|
|
|
|
|
OVERALL MESSAGE DELIVERY STATISTICS |
73
|
|
|
|
|
|
|
____________________________________________________________________ |
74
|
|
|
|
|
|
|
\n$cmds{overall}{out}\n\n |
75
|
|
|
|
|
|
|
==================================================================== |
76
|
|
|
|
|
|
|
MESSAGE FAILURE REPORT |
77
|
|
|
|
|
|
|
____________________________________________________________________ |
78
|
|
|
|
|
|
|
$cmds{failure}{out}\n\n |
79
|
|
|
|
|
|
|
==================================================================== |
80
|
|
|
|
|
|
|
MESSAGE DEFERRAL REPORT |
81
|
|
|
|
|
|
|
____________________________________________________________________ |
82
|
|
|
|
|
|
|
$cmds{deferral}{out} |
83
|
|
|
|
|
|
|
EO_EMAIL |
84
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
close $EMAIL; |
86
|
|
|
|
|
|
|
|
87
|
0
|
|
|
|
|
|
return 0; # because periodic expects 0 for non-error exit code |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub find_qmailanalog { |
91
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
92
|
|
|
|
|
|
|
|
93
|
0
|
|
0
|
|
|
|
my $qmailanalog_dir = $self->conf->{qmailanalog_bin} || "/var/qmail/qmailanalog/bin"; |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# the port location changed, if toaster.conf hasn't been updated, this |
96
|
|
|
|
|
|
|
# will catch it. |
97
|
0
|
0
|
|
|
|
|
if ( ! -d $qmailanalog_dir ) { |
98
|
0
|
|
|
|
|
|
carp <<"EO_QMADIR_MISSING"; |
99
|
|
|
|
|
|
|
ERROR: the location of qmailanalog programs is missing! Make sure you have |
100
|
|
|
|
|
|
|
qmailanalog installed and the path to the binaries is set correctly in |
101
|
|
|
|
|
|
|
toaster.conf. The current setting is $qmailanalog_dir |
102
|
|
|
|
|
|
|
EO_QMADIR_MISSING |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
|
105
|
0
|
0
|
|
|
|
|
if ( -d "/usr/local/qmailanalog/bin" ) { |
106
|
0
|
|
|
|
|
|
$qmailanalog_dir = "/usr/local/qmailanalog/bin"; |
107
|
|
|
|
|
|
|
|
108
|
0
|
|
|
|
|
|
carp <<"EO_QMADIR_FOUND"; |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
YAY! I found your qmailanalog programs in /usr/local/qmailanalog/bin. You |
111
|
|
|
|
|
|
|
should update toaster.conf so you stop getting this error message. |
112
|
|
|
|
|
|
|
EO_QMADIR_FOUND |
113
|
|
|
|
|
|
|
}; |
114
|
|
|
|
|
|
|
}; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# make sure that the matchup program is in there |
117
|
0
|
0
|
|
|
|
|
unless ( -x "$qmailanalog_dir/matchup" ) { |
118
|
0
|
|
|
|
|
|
carp <<"EO_NO_MATCHUP"; |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
report_yesterdays_activity: ERROR! The 'maillogs yesterday' feature only |
121
|
|
|
|
|
|
|
works if qmailanalog is installed. I am unable to find the binaries for |
122
|
|
|
|
|
|
|
it. Please make sure it is installed and the qmailanalog_bin setting in |
123
|
|
|
|
|
|
|
toaster.conf is configured correctly. |
124
|
|
|
|
|
|
|
EO_NO_MATCHUP |
125
|
|
|
|
|
|
|
|
126
|
0
|
|
|
|
|
|
return; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
0
|
|
|
|
|
|
return $qmailanalog_dir; |
130
|
|
|
|
|
|
|
}; |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub get_yesterdays_send_log { |
133
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
134
|
|
|
|
|
|
|
|
135
|
0
|
0
|
0
|
|
|
|
if ( $self->conf->{send_log_method} && $self->conf->{send_log_method} eq "syslog" ) { |
136
|
0
|
|
|
|
|
|
return $self->get_yesterdays_send_log_syslog; |
137
|
|
|
|
|
|
|
}; |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# some form of multilog logging |
140
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
141
|
|
|
|
|
|
|
|
142
|
0
|
|
|
|
|
|
my ( $dd, $mm, $yy ) = $self->util->get_the_date(bump=>0); |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# where todays logs are archived |
145
|
0
|
|
|
|
|
|
my $today = "$logbase/$yy/$mm/$dd/sendlog"; |
146
|
0
|
|
|
|
|
|
$self->audit( "updating todays symlink for sendlogs to $today"); |
147
|
0
|
0
|
|
|
|
|
unlink "$logbase/sendlog" if -l "$logbase/sendlog"; |
148
|
0
|
|
|
|
|
|
symlink( $today, "$logbase/sendlog" ); |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
# where yesterdays logs are archived |
151
|
0
|
|
|
|
|
|
( $dd, $mm, $yy ) = $self->util->get_the_date(bump=>1); |
152
|
0
|
|
|
|
|
|
my $yester = "$logbase/$yy/$mm/$dd/sendlog.gz"; |
153
|
0
|
|
|
|
|
|
$self->audit( "updating yesterdays symlink for sendlogs to $yester" ); |
154
|
0
|
0
|
|
|
|
|
unlink "$logbase/sendlog.gz" if -l "$logbase/sendlog.gz"; |
155
|
0
|
|
|
|
|
|
symlink( $yester, "$logbase/sendlog.gz" ); |
156
|
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
|
return $yester; |
158
|
|
|
|
|
|
|
}; |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub get_yesterdays_send_log_syslog { |
161
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# freebsd's maillog is rotated daily |
164
|
0
|
0
|
|
|
|
|
if ( $OSNAME eq "freebsd" ) { |
165
|
0
|
|
|
|
|
|
my $file = "/var/log/maillog.0"; |
166
|
|
|
|
|
|
|
|
167
|
0
|
0
|
|
|
|
|
return -e "$file.bz2" ? "$file.bz2" |
|
|
0
|
|
|
|
|
|
168
|
|
|
|
|
|
|
: -e "$file.gz" ? "$file.gz" |
169
|
|
|
|
|
|
|
: croak "could not find yesterdays qmail-send logs! "; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
0
|
0
|
|
|
|
|
if ( $OSNAME eq "darwin" ) { |
173
|
0
|
|
|
|
|
|
return "/var/log/mail.log"; # logs are rotated weekly. |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
0
|
|
|
|
|
|
my $file = "/var/log/mail.log.0"; |
177
|
|
|
|
|
|
|
|
178
|
0
|
0
|
|
|
|
|
return -e "$file.gz" ? "$file.gz" |
|
|
0
|
|
|
|
|
|
179
|
|
|
|
|
|
|
: -e "$file.bz2" ? "$file.bz2" |
180
|
|
|
|
|
|
|
: croak "could not find your mail logs from yesterday!\n"; |
181
|
|
|
|
|
|
|
}; |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
sub get_yesterdays_smtp_log { |
184
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
185
|
|
|
|
|
|
|
|
186
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# set up our date variables for today |
189
|
0
|
|
|
|
|
|
my ( $dd, $mm, $yy ) = $self->util->get_the_date(bump=>0); |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# where todays logs are being archived |
192
|
0
|
|
|
|
|
|
my $today = "$logbase/$yy/$mm/$dd/smtplog"; |
193
|
0
|
|
|
|
|
|
$self->audit( "updating todays symlink for smtplogs to $today" ); |
194
|
0
|
0
|
|
|
|
|
unlink("$logbase/smtplog") if -l "$logbase/smtplog"; |
195
|
0
|
|
|
|
|
|
symlink( $today, "$logbase/smtplog" ); |
196
|
|
|
|
|
|
|
|
197
|
0
|
|
|
|
|
|
( $dd, $mm, $yy ) = $self->util->get_the_date(bump=>1); |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# where yesterdays logs are being archived |
200
|
0
|
|
|
|
|
|
my $yester = "$logbase/$yy/$mm/$dd/smtplog.gz"; |
201
|
0
|
|
|
|
|
|
$self->audit( "updating yesterdays symlink for smtplogs" ); |
202
|
0
|
0
|
|
|
|
|
unlink("$logbase/smtplog.gz") if -l "$logbase/smtplog.gz"; |
203
|
0
|
|
|
|
|
|
symlink( $yester, "$logbase/smtplog.gz" ); |
204
|
|
|
|
|
|
|
|
205
|
0
|
|
|
|
|
|
return $yester; |
206
|
|
|
|
|
|
|
}; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub verify_settings { |
209
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
210
|
0
|
|
|
|
|
|
my %p = validate(@_, { $self->get_std_opts } ); |
211
|
0
|
0
|
|
|
|
|
return $p{test_ok} if defined $p{test_ok}; |
212
|
|
|
|
|
|
|
|
213
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
214
|
0
|
|
0
|
|
|
|
my $counters = $self->conf->{logs_counters} || "counters"; |
215
|
|
|
|
|
|
|
|
216
|
0
|
|
0
|
|
|
|
my $user = $self->conf->{logs_user} || 'qmaill'; |
217
|
0
|
|
0
|
|
|
|
my $group = $self->conf->{logs_group} || 'qnofiles'; |
218
|
|
|
|
|
|
|
|
219
|
0
|
0
|
|
|
|
|
if ( !-e $logbase ) { |
220
|
0
|
0
|
|
|
|
|
mkpath( $logbase, 0, oct('0755') ) |
221
|
|
|
|
|
|
|
or return $self->error( "Couldn't create $logbase: $!", %p ); |
222
|
0
|
0
|
|
|
|
|
$self->util->chown($logbase, uid=>$user, gid=>$group) or return; |
223
|
|
|
|
|
|
|
}; |
224
|
|
|
|
|
|
|
|
225
|
0
|
0
|
|
|
|
|
if ( -w $logbase ) { |
226
|
0
|
0
|
|
|
|
|
$self->util->chown($logbase, uid=>$user, gid=>$group) or return; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
0
|
|
|
|
|
|
my $dir = "$logbase/$counters"; |
230
|
|
|
|
|
|
|
|
231
|
0
|
0
|
|
|
|
|
if ( ! -e $dir ) { |
232
|
0
|
|
|
|
|
|
eval { mkpath( $dir, 0, oct('0755') ); }; |
|
0
|
|
|
|
|
|
|
233
|
0
|
0
|
|
|
|
|
return $self->error( "Couldn't create $dir: $!",fatal=>0) if $EVAL_ERROR; |
234
|
0
|
0
|
|
|
|
|
$self->util->chown($dir, uid=>$user, gid=>$group) or return; |
235
|
|
|
|
|
|
|
} |
236
|
0
|
0
|
|
|
|
|
$self->error( "$dir is not a directory!",fatal=>0) if ! -d $dir; |
237
|
|
|
|
|
|
|
|
238
|
0
|
|
|
|
|
|
my $script = "/usr/local/bin/maillogs"; |
239
|
0
|
0
|
|
|
|
|
$script = '/usr/local/sbin/maillogs' if ! -x $script; |
240
|
|
|
|
|
|
|
|
241
|
0
|
0
|
|
|
|
|
return $self->error( "$script must be installed!",fatal=>0) if ! -e $script; |
242
|
0
|
0
|
|
|
|
|
return $self->error( "$script must be executable!",fatal=>0) if ! -x $script; |
243
|
0
|
|
|
|
|
|
return 1; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub parse_cmdline_flags { |
247
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
248
|
|
|
|
|
|
|
|
249
|
0
|
|
|
|
|
|
my %p = validate(@_, { |
250
|
|
|
|
|
|
|
'prot' => { type=>SCALAR|UNDEF, optional=>1, }, |
251
|
|
|
|
|
|
|
$self->get_std_opts, |
252
|
|
|
|
|
|
|
} ); |
253
|
|
|
|
|
|
|
|
254
|
0
|
0
|
|
|
|
|
my $prot = $p{prot} or pod2usage; |
255
|
|
|
|
|
|
|
|
256
|
0
|
|
|
|
|
|
my @prots = qw/ smtp send imap pop3 rbl yesterday qmailscanner |
257
|
|
|
|
|
|
|
spamassassin webmail test /; |
258
|
0
|
|
|
|
|
|
my %valid_prots = map { $_ => 1 } @prots; |
|
0
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
|
260
|
0
|
0
|
|
|
|
|
pod2usage if !$valid_prots{$prot}; |
261
|
|
|
|
|
|
|
|
262
|
0
|
0
|
|
|
|
|
return 1 if $prot eq "test"; |
263
|
|
|
|
|
|
|
|
264
|
0
|
|
|
|
|
|
$self->audit( "parse_cmdline_flags: prot is $prot" ); |
265
|
|
|
|
|
|
|
|
266
|
0
|
0
|
|
|
|
|
return $self->smtp_auth_count if $prot eq "smtp"; |
267
|
0
|
0
|
|
|
|
|
return $self->rbl_count if $prot eq "rbl"; |
268
|
0
|
0
|
|
|
|
|
return $self->send_count if $prot eq "send"; |
269
|
0
|
0
|
|
|
|
|
return $self->pop3_count if $prot eq "pop3"; |
270
|
0
|
0
|
|
|
|
|
return $self->imap_count if $prot eq "imap"; |
271
|
0
|
0
|
|
|
|
|
return $self->spama_count if $prot eq "spamassassin"; |
272
|
0
|
0
|
|
|
|
|
return $self->qms_count if $prot eq "qmailscanner"; |
273
|
0
|
0
|
|
|
|
|
return $self->webmail_count if $prot eq "webmail"; |
274
|
0
|
0
|
|
|
|
|
return $self->report_yesterdays_activity if $prot eq "yesterday"; |
275
|
0
|
|
|
|
|
|
pod2usage; |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub what_am_i { |
279
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
280
|
0
|
|
|
|
|
|
$self->audit( "what_am_i: $0"); |
281
|
0
|
|
|
|
|
|
$0 =~ /([a-zA-Z0-9\.]*)$/; |
282
|
0
|
|
|
|
|
|
$self->audit( " returning $1" ); |
283
|
0
|
|
|
|
|
|
return $1; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
sub rbl_count { |
287
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
288
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
289
|
|
|
|
|
|
|
|
290
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>"rbl"); |
291
|
0
|
|
|
|
|
|
$spam_ref = $self->counter_read( file=>$countfile ); |
292
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
293
|
|
|
|
|
|
|
|
294
|
0
|
|
|
|
|
|
$self->process_rbl_logs( |
295
|
|
|
|
|
|
|
files => $self->check_log_files( "$logbase/smtp/current" ), |
296
|
|
|
|
|
|
|
); |
297
|
|
|
|
|
|
|
|
298
|
0
|
0
|
|
|
|
|
print " Spam Counts\n\n" if $verbose; |
299
|
|
|
|
|
|
|
|
300
|
0
|
|
|
|
|
|
my $i = 0; |
301
|
0
|
|
|
|
|
|
while ( my ($description,$count) = each %$spam_ref ) { |
302
|
0
|
0
|
|
|
|
|
print ":" if $i > 0; |
303
|
0
|
|
|
|
|
|
print "$description:$count"; |
304
|
0
|
|
|
|
|
|
$i++; |
305
|
|
|
|
|
|
|
} |
306
|
0
|
0
|
|
|
|
|
print "\n" if $i > 0; |
307
|
0
|
|
|
|
|
|
return 1; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub smtp_auth_count { |
311
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
312
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
313
|
|
|
|
|
|
|
|
314
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>"smtp"); |
315
|
0
|
|
|
|
|
|
my $count_ref = $self->counter_read( file=>$countfile ); |
316
|
|
|
|
|
|
|
|
317
|
0
|
0
|
|
|
|
|
print " SMTP Counts\n\n" if $verbose; |
318
|
|
|
|
|
|
|
|
319
|
0
|
|
|
|
|
|
my $logfiles = $self->check_log_files( $self->syslog_locate ); |
320
|
0
|
0
|
|
|
|
|
if ( $logfiles->[0] eq "" ) { |
321
|
0
|
|
|
|
|
|
carp "\nsmtp_auth_count: Ack, no logfiles! You may want to see why?"; |
322
|
0
|
|
|
|
|
|
return 1; |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
0
|
|
|
|
|
|
my ($lines, %new_entries); |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# we could have one log file, or dozens (multilog) |
328
|
|
|
|
|
|
|
# go through each, adding their entries to the new_entries hash. |
329
|
0
|
|
|
|
|
|
foreach (@$logfiles) { |
330
|
0
|
|
|
|
|
|
open my $LOGF, "<", $_; |
331
|
|
|
|
|
|
|
|
332
|
0
|
|
|
|
|
|
while ( my $log_line = <$LOGF> ) { |
333
|
0
|
0
|
|
|
|
|
next unless ( $log_line =~ /vchkpw-(smtp|submission)/ ); |
334
|
|
|
|
|
|
|
|
335
|
0
|
|
|
|
|
|
$lines++; |
336
|
0
|
|
|
|
|
|
$new_entries{connect}++; |
337
|
0
|
0
|
|
|
|
|
$new_entries{success}++ if ( $log_line =~ /success/i ); |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
0
|
0
|
|
|
|
|
if ( $new_entries{success} ) { |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# because rrdtool expects ever increasing counters (ie, not starting new |
344
|
|
|
|
|
|
|
# each day), we keep track of when the counts suddenly reset (ie, after a |
345
|
|
|
|
|
|
|
# syslog gets rotated). To reliably know when this happens, we save the |
346
|
|
|
|
|
|
|
# last counter in a _last count. If the new count is greater the last |
347
|
|
|
|
|
|
|
# count, add the difference, which is how many authentications |
348
|
|
|
|
|
|
|
# happened since we last checked. |
349
|
|
|
|
|
|
|
|
350
|
0
|
0
|
|
|
|
|
if ( $new_entries{success} >= $count_ref->{success_last} ) { |
351
|
|
|
|
|
|
|
$count_ref->{success} += |
352
|
0
|
|
|
|
|
|
( $new_entries{success} - $count_ref->{success_last} ); |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
else { |
355
|
|
|
|
|
|
|
# If the counters are lower, then the logs were just rolled and we |
356
|
|
|
|
|
|
|
# need only to add them to the new count. |
357
|
0
|
|
|
|
|
|
$count_ref->{success} += $new_entries{success}; |
358
|
|
|
|
|
|
|
}; |
359
|
|
|
|
|
|
|
|
360
|
0
|
|
|
|
|
|
$count_ref->{success_last} = $new_entries{success}; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
0
|
0
|
|
|
|
|
if ( $new_entries{connect} ) { |
364
|
0
|
0
|
|
|
|
|
if ( $new_entries{connect} >= $count_ref->{connect_last} ) { |
365
|
|
|
|
|
|
|
$count_ref->{connect} += |
366
|
0
|
|
|
|
|
|
( $new_entries{connect} - $count_ref->{connect_last} ); |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
else { |
369
|
|
|
|
|
|
|
$count_ref->{connect} += $new_entries{connect} |
370
|
0
|
|
|
|
|
|
}; |
371
|
|
|
|
|
|
|
|
372
|
0
|
|
|
|
|
|
$count_ref->{connect_last} = $new_entries{connect}; |
373
|
|
|
|
|
|
|
}; |
374
|
|
|
|
|
|
|
|
375
|
0
|
|
|
|
|
|
foreach ( qw/ connect success / ) { |
376
|
0
|
0
|
|
|
|
|
$count_ref->{$_} = 0 if ! defined $count_ref->{$_}; |
377
|
|
|
|
|
|
|
}; |
378
|
|
|
|
|
|
|
|
379
|
0
|
|
|
|
|
|
print "smtp_auth_connect:$count_ref->{connect}:" |
380
|
|
|
|
|
|
|
."smtp_auth_success:$count_ref->{success}\n"; |
381
|
|
|
|
|
|
|
|
382
|
0
|
|
|
|
|
|
return $self->counter_write( log=>$countfile, values=>$count_ref, fatal=>0, verbose=>$verbose ); |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
sub send_count { |
386
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
387
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
388
|
|
|
|
|
|
|
|
389
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
390
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>"send"); |
391
|
0
|
|
|
|
|
|
$count_ref = $self->counter_read( file=>$countfile ); |
392
|
|
|
|
|
|
|
|
393
|
0
|
0
|
|
|
|
|
print "processing send logs\n" if $verbose; |
394
|
|
|
|
|
|
|
|
395
|
0
|
|
|
|
|
|
$self->process_send_logs( |
396
|
|
|
|
|
|
|
roll => 0, |
397
|
|
|
|
|
|
|
files => $self->check_log_files( "$logbase/send/current" ), |
398
|
|
|
|
|
|
|
); |
399
|
|
|
|
|
|
|
|
400
|
0
|
0
|
0
|
|
|
|
if ( $count_ref->{status_remotep} && $count_ref->{status} ) { |
401
|
|
|
|
|
|
|
$count_ref->{concurrencyremote} = |
402
|
0
|
|
|
|
|
|
( $count_ref->{status_remotep} / $count_ref->{status} ) * 100; |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
|
405
|
0
|
0
|
|
|
|
|
print " Counts\n\n" if $verbose; |
406
|
|
|
|
|
|
|
|
407
|
0
|
|
|
|
|
|
my $i = 0; |
408
|
0
|
|
|
|
|
|
while ( my ($description, $count) = each %$count_ref ) { |
409
|
0
|
0
|
|
|
|
|
print ":" if ( $i > 0 ); |
410
|
0
|
|
|
|
|
|
print "$description:$count"; |
411
|
0
|
|
|
|
|
|
$i++; |
412
|
|
|
|
|
|
|
} |
413
|
0
|
|
|
|
|
|
print "\n"; |
414
|
0
|
|
|
|
|
|
return 1; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
sub imap_count { |
418
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
419
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
420
|
|
|
|
|
|
|
|
421
|
0
|
|
|
|
|
|
my ( $imap_success, $imap_connect, $imap_ssl_success, $imap_ssl_connect ); |
422
|
|
|
|
|
|
|
|
423
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>"imap"); |
424
|
0
|
|
|
|
|
|
$count_ref = $self->counter_read( file=>$countfile ); |
425
|
|
|
|
|
|
|
|
426
|
0
|
|
|
|
|
|
my $logfiles = $self->check_log_files( $self->syslog_locate ); |
427
|
0
|
0
|
|
|
|
|
if ( @$logfiles[0] eq "" ) { |
428
|
0
|
|
|
|
|
|
carp "\n imap_count ERROR: no logfiles!"; |
429
|
0
|
|
|
|
|
|
return; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
0
|
|
|
|
|
|
my $lines; |
433
|
0
|
|
|
|
|
|
foreach (@$logfiles) { |
434
|
0
|
|
|
|
|
|
open my $LOGF, "<", $_; |
435
|
|
|
|
|
|
|
|
436
|
0
|
|
|
|
|
|
while ( my $line = <$LOGF> ) { |
437
|
0
|
0
|
|
|
|
|
next if $line !~ /imap/; |
438
|
|
|
|
|
|
|
|
439
|
0
|
|
|
|
|
|
$lines++; |
440
|
|
|
|
|
|
|
|
441
|
0
|
0
|
|
|
|
|
if ( $line =~ /imap-login/ ) { # dovecot |
442
|
0
|
0
|
|
|
|
|
if ( $line =~ /secured/ ) { $imap_ssl_success++; } |
|
0
|
|
|
|
|
|
|
443
|
0
|
|
|
|
|
|
else { $imap_success++; }; |
444
|
0
|
|
|
|
|
|
next; |
445
|
|
|
|
|
|
|
}; |
446
|
|
|
|
|
|
|
|
447
|
0
|
0
|
|
|
|
|
if ( $line =~ /ssl: LOGIN/ ) { # courier |
448
|
0
|
|
|
|
|
|
$imap_ssl_success++; |
449
|
0
|
|
|
|
|
|
next; |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
0
|
0
|
|
|
|
|
if ( $line =~ /LOGIN/ ) { # courier |
453
|
0
|
|
|
|
|
|
$imap_success++; |
454
|
0
|
|
|
|
|
|
next; |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
# elsif ( $line =~ /ssl: Connection/ ) { $imap_ssl_connect++; } |
458
|
|
|
|
|
|
|
# elsif ( $line =~ /Connection/ ) { $imap_connect++; } |
459
|
|
|
|
|
|
|
} |
460
|
0
|
|
|
|
|
|
close $LOGF; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
0
|
0
|
|
|
|
|
unless ( $lines ) { |
464
|
0
|
|
0
|
|
|
|
$count_ref->{imap_success} ||= 0; # hush those "uninitialized value" errors |
465
|
0
|
|
0
|
|
|
|
$count_ref->{imap_ssl_success} ||= 0; |
466
|
|
|
|
|
|
|
|
467
|
0
|
|
|
|
|
|
print "imap_success:$count_ref->{imap_success}" |
468
|
|
|
|
|
|
|
. ":imap_ssl_success:$count_ref->{imap_ssl_success}\n"; |
469
|
0
|
0
|
|
|
|
|
carp "imap_count: no log entries to process. I'm done!" if $verbose; |
470
|
0
|
|
|
|
|
|
return 1; |
471
|
|
|
|
|
|
|
}; |
472
|
|
|
|
|
|
|
|
473
|
0
|
0
|
|
|
|
|
if ( $imap_success ) { |
474
|
0
|
0
|
|
|
|
|
if ( $imap_success >= $count_ref->{imap_success_last} ) { |
475
|
|
|
|
|
|
|
$count_ref->{imap_success} |
476
|
0
|
|
|
|
|
|
+= ( $imap_success - $count_ref->{imap_success_last} ); |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
else { |
479
|
0
|
|
|
|
|
|
$count_ref->{imap_success} += $imap_success; |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
0
|
|
|
|
|
|
$count_ref->{imap_success_last} = $imap_success; |
483
|
|
|
|
|
|
|
}; |
484
|
|
|
|
|
|
|
|
485
|
0
|
0
|
|
|
|
|
if ( $imap_ssl_success ) { |
486
|
0
|
0
|
|
|
|
|
if ( $imap_ssl_success >= $count_ref->{imap_ssl_success_last} ) { |
487
|
|
|
|
|
|
|
$count_ref->{imap_ssl_success} += |
488
|
0
|
|
|
|
|
|
( $imap_ssl_success - $count_ref->{imap_ssl_success_last} ); |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
else { |
491
|
0
|
|
|
|
|
|
$count_ref->{imap_ssl_success} += $imap_ssl_success; |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
0
|
|
|
|
|
|
$count_ref->{imap_ssl_success_last} = $imap_ssl_success; |
495
|
|
|
|
|
|
|
}; |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
print "imap_success:".$count_ref->{imap_success} |
498
|
0
|
|
|
|
|
|
. ":imap_ssl_success:".$count_ref->{imap_ssl_success}."\n"; |
499
|
|
|
|
|
|
|
|
500
|
0
|
|
|
|
|
|
return $self->counter_write( log=>$countfile, values=>$count_ref, fatal=>0 ); |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
sub pop3_count { |
504
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
505
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
# read our counters from disk |
508
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>"pop3"); |
509
|
|
|
|
|
|
|
|
510
|
0
|
0
|
|
|
|
|
print "pop3_count: reading counters from $countfile.\n" if $verbose; |
511
|
0
|
|
|
|
|
|
$count_ref = $self->counter_read( file=>$countfile ); |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
# get the location of log files to process |
514
|
0
|
0
|
|
|
|
|
print "finding the log files to process.\n" if $verbose; |
515
|
0
|
|
|
|
|
|
my $logfiles = $self->check_log_files( $self->syslog_locate ); |
516
|
0
|
0
|
|
|
|
|
if ( $logfiles->[0] eq "" ) { |
517
|
0
|
|
|
|
|
|
carp " pop3_count: ERROR: no logfiles to process!"; |
518
|
0
|
|
|
|
|
|
return; |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
0
|
0
|
|
|
|
|
print "pop3_count: processing files @$logfiles.\n" if $verbose; |
522
|
|
|
|
|
|
|
|
523
|
0
|
|
|
|
|
|
my $lines; |
524
|
0
|
|
|
|
|
|
my %new_entries = ( |
525
|
|
|
|
|
|
|
'connect' => 0, |
526
|
|
|
|
|
|
|
'success' => 0, |
527
|
|
|
|
|
|
|
'ssl_connect' => 0, |
528
|
|
|
|
|
|
|
'ssl_success' => 0, |
529
|
|
|
|
|
|
|
); |
530
|
|
|
|
|
|
|
|
531
|
0
|
|
|
|
|
|
my %valid_counters = ( |
532
|
|
|
|
|
|
|
'pop3_success' => 1, # successful authentication |
533
|
|
|
|
|
|
|
'pop3_success_last' => 1, # last success count |
534
|
|
|
|
|
|
|
'pop3_connect' => 1, # total connections |
535
|
|
|
|
|
|
|
'pop3_connect_last' => 1, # last total connections |
536
|
|
|
|
|
|
|
'pop3_ssl_success' => 1, # ssl successful auth |
537
|
|
|
|
|
|
|
'pop3_ssl_success_last' => 1, # last ssl success auths |
538
|
|
|
|
|
|
|
'pop3_ssl_connect' => 1, # ssl connections |
539
|
|
|
|
|
|
|
'pop3_ssl_connect_last' => 1, # last ssl connects |
540
|
|
|
|
|
|
|
); |
541
|
|
|
|
|
|
|
|
542
|
0
|
|
|
|
|
|
foreach my $key ( keys %valid_counters ) { |
543
|
0
|
0
|
|
|
|
|
if ( ! defined $count_ref->{$key} ) { |
544
|
0
|
0
|
|
|
|
|
carp "pop3_count: missing key $key in count_ref!" if $verbose; |
545
|
0
|
|
|
|
|
|
$count_ref->{$key} = 0; |
546
|
|
|
|
|
|
|
}; |
547
|
|
|
|
|
|
|
}; |
548
|
|
|
|
|
|
|
|
549
|
0
|
0
|
|
|
|
|
print "processing...\n" if $verbose; |
550
|
0
|
|
|
|
|
|
foreach (@$logfiles) { |
551
|
0
|
|
|
|
|
|
open my $LOGF, "<", $_; |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
LINE: |
554
|
0
|
|
|
|
|
|
while ( my $line = <$LOGF> ) { |
555
|
0
|
0
|
|
|
|
|
next unless ( $line =~ /pop3/ ); # discard everything not pop3 |
556
|
0
|
|
|
|
|
|
$lines++; |
557
|
|
|
|
|
|
|
|
558
|
0
|
0
|
|
|
|
|
if ( $line =~ /vchkpw-pop3:/ ) { # qmail-pop3d |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
559
|
0
|
|
|
|
|
|
$new_entries{connect}++; |
560
|
0
|
0
|
|
|
|
|
$new_entries{success}++ if ( $line =~ /success/ ); |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
elsif ( $line =~ /pop3d: / ) { # courier pop3d |
563
|
0
|
0
|
|
|
|
|
$new_entries{connect}++ if ( $line =~ /Connection/ ); |
564
|
0
|
0
|
|
|
|
|
$new_entries{success}++ if ( $line =~ /LOGIN/ ); |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
elsif ( $line =~ /pop3d-ssl: / ) { # courier pop3d-ssl |
567
|
0
|
0
|
|
|
|
|
if ( $line =~ /LOGIN/ ) { |
568
|
0
|
|
|
|
|
|
$new_entries{ssl_success}++; |
569
|
0
|
|
|
|
|
|
next LINE; |
570
|
|
|
|
|
|
|
}; |
571
|
0
|
0
|
|
|
|
|
$new_entries{ssl_connect}++ if ( $line =~ /Connection/ ); |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
elsif ( $line =~ /pop3-login: / ) { # dovecot pop3 |
574
|
0
|
0
|
|
|
|
|
if ( $line =~ /secured/ ) { |
575
|
0
|
|
|
|
|
|
$new_entries{ssl_success}++; |
576
|
|
|
|
|
|
|
} else { |
577
|
0
|
|
|
|
|
|
$new_entries{success}++; |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
} |
580
|
|
|
|
|
|
|
} |
581
|
0
|
|
|
|
|
|
close $LOGF; |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
|
584
|
0
|
0
|
|
|
|
|
if ( ! $lines ) { |
585
|
0
|
|
|
|
|
|
pop3_report(); |
586
|
0
|
0
|
|
|
|
|
carp "pop3_count: no log entries, I'm done!" if $verbose; |
587
|
0
|
|
|
|
|
|
return 1; |
588
|
|
|
|
|
|
|
}; |
589
|
|
|
|
|
|
|
|
590
|
0
|
0
|
|
|
|
|
if ( $new_entries{success} ) { |
591
|
0
|
0
|
|
|
|
|
if ( $new_entries{success} >= $count_ref->{pop3_success_last} ) { |
592
|
|
|
|
|
|
|
$count_ref->{pop3_success} += |
593
|
0
|
|
|
|
|
|
( $new_entries{success} - $count_ref->{pop3_success_last} ); |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
else { |
596
|
0
|
|
|
|
|
|
$count_ref->{pop3_success} += $new_entries{success}; |
597
|
|
|
|
|
|
|
} |
598
|
|
|
|
|
|
|
|
599
|
0
|
|
|
|
|
|
$count_ref->{pop3_success_last} = $new_entries{success}; |
600
|
|
|
|
|
|
|
}; |
601
|
|
|
|
|
|
|
|
602
|
0
|
0
|
|
|
|
|
if ( $new_entries{connect} ) { |
603
|
0
|
0
|
|
|
|
|
if ( $new_entries{connect} >= $count_ref->{pop3_connect_last} ) { |
604
|
|
|
|
|
|
|
$count_ref->{pop3_connect} += |
605
|
0
|
|
|
|
|
|
( $new_entries{connect} - $count_ref->{pop3_connect_last} ); |
606
|
|
|
|
|
|
|
} |
607
|
0
|
|
|
|
|
|
else { $count_ref->{pop3_connect} += $new_entries{connect} } |
608
|
|
|
|
|
|
|
|
609
|
0
|
|
|
|
|
|
$count_ref->{pop3_connect_last} = $new_entries{connect}; |
610
|
|
|
|
|
|
|
}; |
611
|
|
|
|
|
|
|
|
612
|
0
|
0
|
|
|
|
|
if ( $new_entries{ssl_success} ) { |
613
|
0
|
0
|
|
|
|
|
if ( $new_entries{ssl_success} >= $count_ref->{pop3_ssl_success_last} ) { |
614
|
|
|
|
|
|
|
$count_ref->{pop3_ssl_success} += |
615
|
0
|
|
|
|
|
|
( $new_entries{ssl_success} - $count_ref->{pop3_ssl_success_last} ); |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
else { |
618
|
0
|
|
|
|
|
|
$count_ref->{pop3_ssl_success} += $new_entries{ssl_success}; |
619
|
|
|
|
|
|
|
} |
620
|
|
|
|
|
|
|
|
621
|
0
|
|
|
|
|
|
$count_ref->{pop3_ssl_success_last} = $new_entries{ssl_success}; |
622
|
|
|
|
|
|
|
}; |
623
|
|
|
|
|
|
|
|
624
|
0
|
0
|
|
|
|
|
if ( $new_entries{ssl_connect} ) { |
625
|
0
|
0
|
|
|
|
|
if ( $new_entries{ssl_connect} >= $count_ref->{pop3_ssl_connect_last} ) { |
626
|
|
|
|
|
|
|
$count_ref->{pop3_ssl_connect} |
627
|
0
|
|
|
|
|
|
+= ( $new_entries{ssl_connect} - $count_ref->{pop3_ssl_connect_last} ); |
628
|
|
|
|
|
|
|
} |
629
|
|
|
|
|
|
|
else { |
630
|
0
|
|
|
|
|
|
$count_ref->{pop3_ssl_connect} += $new_entries{ssl_connect}; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
0
|
|
|
|
|
|
$count_ref->{pop3_ssl_connect_last} = $new_entries{ssl_connect}; |
634
|
|
|
|
|
|
|
}; |
635
|
|
|
|
|
|
|
|
636
|
0
|
|
|
|
|
|
pop3_report(); |
637
|
|
|
|
|
|
|
|
638
|
0
|
|
|
|
|
|
return $self->counter_write( log=>$countfile, values=>$count_ref, fatal=>0 ); |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
sub pop3_report { |
642
|
|
|
|
|
|
|
|
643
|
0
|
0
|
|
0
|
0
|
|
$count_ref->{pop3_connect} || 0; |
644
|
0
|
0
|
|
|
|
|
$count_ref->{pop3_ssl_connect} || 0; |
645
|
0
|
0
|
|
|
|
|
$count_ref->{pop3_success} || 0; |
646
|
0
|
0
|
|
|
|
|
$count_ref->{pop3_ssl_success} || 0; |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
print "pop3_connect:" . $count_ref->{pop3_connect} |
649
|
|
|
|
|
|
|
. ":pop3_ssl_connect:" . $count_ref->{pop3_ssl_connect} |
650
|
|
|
|
|
|
|
. ":pop3_success:" . $count_ref->{pop3_success} |
651
|
|
|
|
|
|
|
. ":pop3_ssl_success:" . $count_ref->{pop3_ssl_success} |
652
|
0
|
|
|
|
|
|
. "\n"; |
653
|
|
|
|
|
|
|
}; |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
sub webmail_count { |
656
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
657
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
658
|
|
|
|
|
|
|
|
659
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>"web"); |
660
|
0
|
|
|
|
|
|
$count_ref = $self->counter_read( file=>$countfile ); |
661
|
|
|
|
|
|
|
|
662
|
0
|
|
|
|
|
|
my $logfiles = $self->check_log_files( $self->syslog_locate ); |
663
|
0
|
0
|
|
|
|
|
if ( @$logfiles[0] eq "" ) { |
664
|
0
|
|
|
|
|
|
carp "\n ERROR: no logfiles!"; |
665
|
0
|
|
|
|
|
|
return 0; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
# sample log entries |
669
|
|
|
|
|
|
|
# Feb 21 10:24:41 cadillac sqwebmaild: LOGIN, user=matt@cadillac.net, ip=[66.227.213.209] |
670
|
|
|
|
|
|
|
# Feb 21 10:27:00 cadillac sqwebmaild: LOGIN FAILED, user=matt@cadillac.net, ip=[66.227.213.209] |
671
|
|
|
|
|
|
|
|
672
|
0
|
|
|
|
|
|
my %temp; |
673
|
|
|
|
|
|
|
|
674
|
0
|
|
|
|
|
|
foreach (@$logfiles) { |
675
|
0
|
|
|
|
|
|
open my $LOGF, "<", $_; |
676
|
|
|
|
|
|
|
|
677
|
0
|
|
|
|
|
|
while ( my $line = <$LOGF> ) { |
678
|
0
|
0
|
|
|
|
|
next if $line =~ /spamd/; # typically half the syslog file |
679
|
0
|
0
|
|
|
|
|
next if $line =~ /pop3/; # another 1/3 to 1/2 |
680
|
|
|
|
|
|
|
|
681
|
0
|
0
|
0
|
|
|
|
if ( $line =~ /Successful webmail login/ ) { # squirrelmail w/plugin |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
682
|
0
|
|
|
|
|
|
$temp{success}++; |
683
|
0
|
|
|
|
|
|
$temp{connect}++; |
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
elsif ( $line =~ /sqwebmaild/ ) { # sqwebmail |
686
|
0
|
|
|
|
|
|
$temp{connect}++; |
687
|
0
|
0
|
|
|
|
|
$temp{success}++ if ( $line !~ /FAILED/ ); |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
elsif ( $line =~ /imapd: LOGIN/ && $line =~ /127\.0\.0\./ ) |
690
|
|
|
|
|
|
|
{ # IMAP connections on loopback interface are webmail |
691
|
0
|
|
|
|
|
|
$temp{success}++; |
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
} |
694
|
0
|
|
|
|
|
|
close $LOGF; |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
|
697
|
0
|
0
|
|
|
|
|
if ( !$temp{connect} ) { |
698
|
0
|
0
|
|
|
|
|
carp "webmail_count: No webmail logins! I'm all done." if $verbose; |
699
|
0
|
|
|
|
|
|
return 1; |
700
|
|
|
|
|
|
|
}; |
701
|
|
|
|
|
|
|
|
702
|
0
|
0
|
|
|
|
|
if ( $temp{success} ) { |
703
|
0
|
0
|
|
|
|
|
if ( $temp{success} >= $count_ref->{success_last} ) { |
704
|
|
|
|
|
|
|
$count_ref->{success} = |
705
|
0
|
|
|
|
|
|
$count_ref->{success} + ( $temp{success} - $count_ref->{success_last} ); |
706
|
|
|
|
|
|
|
} |
707
|
0
|
|
|
|
|
|
else { $count_ref->{success} = $count_ref->{success} + $temp{success} } |
708
|
|
|
|
|
|
|
|
709
|
0
|
|
|
|
|
|
$count_ref->{success_last} = $temp{success}; |
710
|
|
|
|
|
|
|
}; |
711
|
|
|
|
|
|
|
|
712
|
0
|
0
|
|
|
|
|
if ( $temp{connect} ) { |
713
|
0
|
0
|
|
|
|
|
if ( $temp{connect} >= $count_ref->{connect_last} ) { |
714
|
|
|
|
|
|
|
$count_ref->{connect} = |
715
|
0
|
|
|
|
|
|
$count_ref->{connect} + ( $temp{connect} - $count_ref->{connect_last} ); |
716
|
|
|
|
|
|
|
} |
717
|
0
|
|
|
|
|
|
else { $count_ref->{connect} = $count_ref->{connect} + $temp{connect} } |
718
|
|
|
|
|
|
|
|
719
|
0
|
|
|
|
|
|
$count_ref->{connect_last} = $temp{connect}; |
720
|
|
|
|
|
|
|
}; |
721
|
|
|
|
|
|
|
|
722
|
0
|
0
|
|
|
|
|
if ( ! $count_ref->{connect} ) { |
723
|
0
|
|
|
|
|
|
$count_ref->{connect} = 0; |
724
|
|
|
|
|
|
|
}; |
725
|
|
|
|
|
|
|
|
726
|
0
|
0
|
|
|
|
|
if ( ! $count_ref->{success} ) { |
727
|
0
|
|
|
|
|
|
$count_ref->{success} = 0; |
728
|
|
|
|
|
|
|
}; |
729
|
|
|
|
|
|
|
|
730
|
0
|
|
|
|
|
|
print "webmail_connect:$count_ref->{connect}" |
731
|
|
|
|
|
|
|
. ":webmail_success:$count_ref->{success}" |
732
|
|
|
|
|
|
|
. "\n"; |
733
|
|
|
|
|
|
|
|
734
|
0
|
|
|
|
|
|
return $self->counter_write( |
735
|
|
|
|
|
|
|
log => $countfile, |
736
|
|
|
|
|
|
|
values => $count_ref, |
737
|
|
|
|
|
|
|
fatal => 0, |
738
|
|
|
|
|
|
|
); |
739
|
|
|
|
|
|
|
} |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
sub spama_count { |
742
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
743
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
744
|
|
|
|
|
|
|
|
745
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>"spam"); |
746
|
0
|
|
|
|
|
|
$count_ref = $self->counter_read( file=>$countfile ); |
747
|
|
|
|
|
|
|
|
748
|
0
|
|
|
|
|
|
my $logfiles = $self->check_log_files( $self->syslog_locate ); |
749
|
0
|
0
|
|
|
|
|
if ( @$logfiles[0] eq "" ) { |
750
|
0
|
|
|
|
|
|
carp "\n spamassassin_count ERROR: no logfiles!"; |
751
|
0
|
|
|
|
|
|
return; |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
|
754
|
0
|
|
|
|
|
|
my %temp = ( spam => 1, ham => 1 ); |
755
|
|
|
|
|
|
|
|
756
|
0
|
|
|
|
|
|
foreach (@$logfiles) { |
757
|
0
|
0
|
|
|
|
|
open my $LOGF, "<", $_ or do { |
758
|
0
|
|
|
|
|
|
carp "unable to open $_: $!"; |
759
|
0
|
|
|
|
|
|
next; |
760
|
|
|
|
|
|
|
}; |
761
|
|
|
|
|
|
|
|
762
|
0
|
|
|
|
|
|
while ( my $line = <$LOGF> ) { |
763
|
0
|
0
|
|
|
|
|
next unless $line =~ /spamd/; |
764
|
0
|
|
|
|
|
|
$temp{spamd_lines}++; |
765
|
|
|
|
|
|
|
|
766
|
0
|
0
|
|
|
|
|
if ( $line =~ |
|
|
0
|
|
|
|
|
|
767
|
|
|
|
|
|
|
/clean message \(([0-9-\.]+)\/([0-9\.]+)\) for .* in ([0-9\.]+) seconds, ([0-9]+) bytes/ |
768
|
|
|
|
|
|
|
) |
769
|
|
|
|
|
|
|
{ |
770
|
0
|
|
|
|
|
|
$temp{ham}++; |
771
|
0
|
|
|
|
|
|
$temp{ham_scores} += $1; |
772
|
0
|
|
|
|
|
|
$temp{threshhold} += $2; |
773
|
0
|
|
|
|
|
|
$temp{ham_seconds} += $3; |
774
|
0
|
|
|
|
|
|
$temp{ham_bytes} += $4; |
775
|
|
|
|
|
|
|
} |
776
|
|
|
|
|
|
|
elsif ( $line =~ |
777
|
|
|
|
|
|
|
/identified spam \(([0-9-\.]+)\/([0-9\.]+)\) for .* in ([0-9\.]+) seconds, ([0-9]+) bytes/ |
778
|
|
|
|
|
|
|
) |
779
|
|
|
|
|
|
|
{ |
780
|
0
|
|
|
|
|
|
$temp{spam}++; |
781
|
0
|
|
|
|
|
|
$temp{spam_scores} += $1; |
782
|
0
|
|
|
|
|
|
$temp{threshhold} += $2; |
783
|
0
|
|
|
|
|
|
$temp{spam_seconds} += $3; |
784
|
0
|
|
|
|
|
|
$temp{spam_bytes} += $4; |
785
|
|
|
|
|
|
|
} |
786
|
|
|
|
|
|
|
else { |
787
|
0
|
|
|
|
|
|
$temp{other}++; |
788
|
|
|
|
|
|
|
} |
789
|
|
|
|
|
|
|
} |
790
|
|
|
|
|
|
|
|
791
|
0
|
|
|
|
|
|
close $LOGF; |
792
|
|
|
|
|
|
|
} |
793
|
|
|
|
|
|
|
|
794
|
0
|
0
|
|
|
|
|
unless ( $temp{spamd_lines} ) { |
795
|
0
|
0
|
|
|
|
|
carp "spamassassin_count: no log file entries for spamd!" if $verbose; |
796
|
0
|
|
|
|
|
|
return 1; |
797
|
|
|
|
|
|
|
}; |
798
|
|
|
|
|
|
|
|
799
|
0
|
|
0
|
|
|
|
my $ham_count = $temp{ham} || 0; |
800
|
0
|
|
0
|
|
|
|
my $spam_count = $temp{spam} || 0; |
801
|
|
|
|
|
|
|
|
802
|
0
|
0
|
|
|
|
|
if ( $ham_count ) { |
803
|
0
|
0
|
|
|
|
|
if ( $ham_count >= $count_ref->{sa_ham_last} ) { |
804
|
|
|
|
|
|
|
$count_ref->{sa_ham} = |
805
|
0
|
|
|
|
|
|
$count_ref->{sa_ham} + ( $ham_count - $count_ref->{sa_ham_last} ); |
806
|
|
|
|
|
|
|
} |
807
|
|
|
|
|
|
|
else { |
808
|
0
|
|
|
|
|
|
$count_ref->{sa_ham} = $count_ref->{sa_ham} + $ham_count; |
809
|
|
|
|
|
|
|
} |
810
|
|
|
|
|
|
|
}; |
811
|
|
|
|
|
|
|
|
812
|
0
|
0
|
|
|
|
|
if ( $spam_count ) { |
813
|
0
|
0
|
|
|
|
|
if ( $spam_count >= $count_ref->{sa_spam_last} ) { |
814
|
|
|
|
|
|
|
$count_ref->{sa_spam} = |
815
|
0
|
|
|
|
|
|
$count_ref->{sa_spam} + ( $spam_count - $count_ref->{sa_spam_last} ); |
816
|
|
|
|
|
|
|
} |
817
|
|
|
|
|
|
|
else { |
818
|
0
|
|
|
|
|
|
$count_ref->{sa_spam} = $count_ref->{sa_spam} + $spam_count; |
819
|
|
|
|
|
|
|
} |
820
|
|
|
|
|
|
|
}; |
821
|
|
|
|
|
|
|
|
822
|
0
|
|
|
|
|
|
require POSIX; # needed for floor |
823
|
|
|
|
|
|
|
$count_ref->{avg_spam_score} = (defined $temp{spam_scores} && $spam_count ) |
824
|
0
|
0
|
0
|
|
|
|
? POSIX::floor( $temp{spam_scores} / $spam_count * 100 ) : 0; |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
$count_ref->{avg_ham_score} = (defined $temp{ham_scores} && $ham_count ) |
827
|
0
|
0
|
0
|
|
|
|
? POSIX::floor( $temp{ham_scores} / $ham_count * 100 ) : 0; |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
$count_ref->{threshhold} = ( $temp{threshhold} && ($ham_count || $spam_count) ) |
830
|
0
|
0
|
0
|
|
|
|
? POSIX::floor( $temp{threshhold} / ( $ham_count + $spam_count ) * 100 ) : 0; |
831
|
|
|
|
|
|
|
|
832
|
0
|
|
|
|
|
|
$count_ref->{sa_ham_last} = $ham_count; |
833
|
0
|
|
|
|
|
|
$count_ref->{sa_spam_last} = $spam_count; |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
$count_ref->{sa_ham_seconds} = (defined $temp{ham_seconds} && $ham_count ) |
836
|
0
|
0
|
0
|
|
|
|
? POSIX::floor( $temp{ham_seconds} / $ham_count * 100 ) : 0; |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
$count_ref->{sa_spam_seconds} = (defined $temp{spam_seconds} && $spam_count) |
839
|
0
|
0
|
0
|
|
|
|
? POSIX::floor( $temp{spam_seconds} / $spam_count * 100 ) : 0; |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
$count_ref->{sa_ham_bytes} = (defined $temp{ham_bytes} && $ham_count ) |
842
|
0
|
0
|
0
|
|
|
|
? POSIX::floor( $temp{ham_bytes} / $ham_count * 100 ) : 0; |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
$count_ref->{sa_spam_bytes} = (defined $temp{spam_bytes} && $spam_count ) |
845
|
0
|
0
|
0
|
|
|
|
? POSIX::floor( $temp{spam_bytes} / $spam_count * 100 ) : 0; |
846
|
|
|
|
|
|
|
|
847
|
0
|
|
|
|
|
|
print "sa_spam:$count_ref->{sa_spam}" |
848
|
|
|
|
|
|
|
. ":sa_ham:$count_ref->{sa_ham}" |
849
|
|
|
|
|
|
|
. ":spam_score:$count_ref->{avg_spam_score}" |
850
|
|
|
|
|
|
|
. ":ham_score:$count_ref->{avg_ham_score}" |
851
|
|
|
|
|
|
|
. ":threshhold:$count_ref->{threshhold}" |
852
|
|
|
|
|
|
|
. ":ham_seconds:$count_ref->{sa_ham_seconds}" |
853
|
|
|
|
|
|
|
. ":spam_seconds:$count_ref->{sa_spam_seconds}" |
854
|
|
|
|
|
|
|
. ":ham_bytes:$count_ref->{sa_ham_bytes}" |
855
|
|
|
|
|
|
|
. ":spam_bytes:$count_ref->{sa_spam_bytes}" |
856
|
|
|
|
|
|
|
. "\n"; |
857
|
|
|
|
|
|
|
|
858
|
0
|
|
|
|
|
|
return $self->counter_write( log=>$countfile, values=>$count_ref, fatal=>0 ); |
859
|
|
|
|
|
|
|
} |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
sub qms_count { |
862
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
863
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
864
|
|
|
|
|
|
|
|
865
|
0
|
|
|
|
|
|
my ( $qs_clean, $qs_virus, $qs_all ); |
866
|
|
|
|
|
|
|
|
867
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>"virus"); |
868
|
0
|
|
|
|
|
|
my $count_ref = $self->counter_read( file=>$countfile ); |
869
|
|
|
|
|
|
|
|
870
|
0
|
|
|
|
|
|
my $logfiles = $self->check_log_files( $self->syslog_locate ); |
871
|
0
|
0
|
0
|
|
|
|
if ( ! defined @$logfiles[0] || @$logfiles[0] eq "" ) { |
872
|
0
|
|
|
|
|
|
carp " qms_count: ERROR: no logfiles!"; |
873
|
0
|
|
|
|
|
|
return 1; |
874
|
|
|
|
|
|
|
} |
875
|
|
|
|
|
|
|
|
876
|
0
|
|
|
|
|
|
my $grep = $self->util->find_bin("grep", verbose=>0); |
877
|
0
|
|
|
|
|
|
my $wc = $self->util->find_bin("wc", verbose=>0); |
878
|
|
|
|
|
|
|
|
879
|
0
|
|
|
|
|
|
$qs_clean = `$grep " qmail-scanner" @$logfiles | $grep "Clear:" | $wc -l`; |
880
|
0
|
|
|
|
|
|
$qs_clean = $qs_clean * 1; |
881
|
0
|
|
|
|
|
|
$qs_all = `$grep " qmail-scanner" @$logfiles | $wc -l`; |
882
|
0
|
|
|
|
|
|
$qs_all = $qs_all * 1; |
883
|
0
|
|
|
|
|
|
$qs_virus = $qs_all - $qs_clean; |
884
|
|
|
|
|
|
|
|
885
|
0
|
0
|
|
|
|
|
if ( $qs_all == 0 ) { |
886
|
0
|
0
|
|
|
|
|
carp "qms_count: no log files for qmail-scanner found!" if $verbose; |
887
|
0
|
|
|
|
|
|
return 1; |
888
|
|
|
|
|
|
|
}; |
889
|
|
|
|
|
|
|
|
890
|
0
|
0
|
|
|
|
|
if ( $qs_clean ) { |
891
|
0
|
0
|
|
|
|
|
if ( $qs_clean >= $count_ref->{qs_clean_last} ) { |
892
|
|
|
|
|
|
|
$count_ref->{qs_clean} = |
893
|
0
|
|
|
|
|
|
$count_ref->{qs_clean} + ( $qs_clean - $count_ref->{qs_clean_last} ); |
894
|
|
|
|
|
|
|
} |
895
|
0
|
|
|
|
|
|
else { $count_ref->{qs_clean} = $count_ref->{qs_clean} + $qs_clean } |
896
|
|
|
|
|
|
|
|
897
|
0
|
|
|
|
|
|
$count_ref->{qs_clean_last} = $qs_clean; |
898
|
|
|
|
|
|
|
}; |
899
|
|
|
|
|
|
|
|
900
|
0
|
0
|
|
|
|
|
if ( $qs_virus ) { |
901
|
0
|
0
|
|
|
|
|
if ( $qs_virus >= $count_ref->{qs_virus_last} ) { |
902
|
|
|
|
|
|
|
$count_ref->{qs_virus} = |
903
|
0
|
|
|
|
|
|
$count_ref->{qs_virus} + ( $qs_virus - $count_ref->{qs_virus_last} ); |
904
|
|
|
|
|
|
|
} |
905
|
0
|
|
|
|
|
|
else { $count_ref->{qs_virus} = $count_ref->{qs_virus} + $qs_virus } |
906
|
|
|
|
|
|
|
|
907
|
0
|
|
|
|
|
|
$count_ref->{qs_virus_last} = $qs_virus; |
908
|
|
|
|
|
|
|
}; |
909
|
|
|
|
|
|
|
|
910
|
0
|
|
|
|
|
|
print "qs_clean:$qs_clean:qs_virii:$qs_virus\n"; |
911
|
|
|
|
|
|
|
|
912
|
0
|
0
|
|
|
|
|
if ( !$count_ref ) { |
913
|
0
|
|
|
|
|
|
$count_ref = { qs_clean=>0, qs_virii=>0 }; |
914
|
|
|
|
|
|
|
}; |
915
|
|
|
|
|
|
|
|
916
|
0
|
|
|
|
|
|
return $self->counter_write( log=>$countfile, values=>$count_ref, fatal=>0 ); |
917
|
|
|
|
|
|
|
} |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
sub roll_send_logs { |
920
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
921
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
922
|
|
|
|
|
|
|
|
923
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
924
|
0
|
0
|
|
|
|
|
print "roll_send_logs: logging base is $logbase.\n" if $verbose; |
925
|
|
|
|
|
|
|
|
926
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>"send"); |
927
|
0
|
|
|
|
|
|
$count_ref = $self->counter_read( file=>$countfile ); |
928
|
|
|
|
|
|
|
|
929
|
0
|
|
|
|
|
|
$self->process_send_logs( |
930
|
|
|
|
|
|
|
roll => 1, |
931
|
|
|
|
|
|
|
files => $self->check_log_files( "$logbase/send/current" ), |
932
|
|
|
|
|
|
|
); |
933
|
|
|
|
|
|
|
|
934
|
0
|
|
|
|
|
|
$self->counter_write( log=>$countfile, values=>$count_ref, fatal=>0 ); |
935
|
|
|
|
|
|
|
} |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
sub roll_rbl_logs { |
938
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
939
|
|
|
|
|
|
|
|
940
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
941
|
0
|
|
|
|
|
|
my $countfile = $self->set_countfile(prot=>'rbl'); |
942
|
|
|
|
|
|
|
|
943
|
0
|
0
|
|
|
|
|
if ( -r $countfile ) { |
944
|
0
|
|
|
|
|
|
$spam_ref = $self->counter_read( file=>$countfile ); |
945
|
|
|
|
|
|
|
} |
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
$self->process_rbl_logs( |
948
|
0
|
|
|
|
|
|
roll => 1, |
949
|
|
|
|
|
|
|
files => $self->check_log_files( "$logbase/smtp/current" ), |
950
|
|
|
|
|
|
|
); |
951
|
|
|
|
|
|
|
|
952
|
0
|
|
|
|
|
|
$self->counter_write( log=>$countfile, values=>$spam_ref, fatal=>0 ); |
953
|
0
|
|
|
|
|
|
exit 0; |
954
|
|
|
|
|
|
|
} |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
sub roll_pop3_logs { |
957
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
958
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
959
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
960
|
|
|
|
|
|
|
|
961
|
0
|
|
|
|
|
|
$self->process_pop3_logs( |
962
|
|
|
|
|
|
|
roll => 1, |
963
|
|
|
|
|
|
|
files => $self->check_log_files( "$logbase/pop3/current" ), |
964
|
|
|
|
|
|
|
); |
965
|
|
|
|
|
|
|
|
966
|
0
|
|
|
|
|
|
$self->compress_yesterdays_logs( "pop3log" ); |
967
|
|
|
|
|
|
|
} |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
sub compress_yesterdays_logs { |
970
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
971
|
0
|
0
|
|
|
|
|
my $file = shift or croak "missing log file!"; |
972
|
|
|
|
|
|
|
|
973
|
0
|
|
|
|
|
|
my ( $dd, $mm, $yy ) = $self->util->get_the_date(bump=>1 ); |
974
|
|
|
|
|
|
|
|
975
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
976
|
0
|
|
|
|
|
|
$file = "$logbase/$yy/$mm/$dd/$file"; |
977
|
|
|
|
|
|
|
|
978
|
0
|
0
|
|
|
|
|
return $self->audit( " $file is already compressed") if -e "$file.gz"; |
979
|
0
|
0
|
|
|
|
|
return $self->audit( " $file does not exist.") if ! -e $file; |
980
|
0
|
0
|
|
|
|
|
return $self->error( "insufficient permissions to compress $file",fatal=>0) |
981
|
|
|
|
|
|
|
if ! $self->util->is_writable( "$file.gz",fatal=>0 ); |
982
|
|
|
|
|
|
|
|
983
|
0
|
0
|
|
|
|
|
my $gzip = $self->util->find_bin('gzip',fatal=>0) or return; |
984
|
0
|
0
|
|
|
|
|
$self->util->syscmd( "$gzip $file", fatal=>0 ) |
985
|
|
|
|
|
|
|
or return $self->error( "compressing the logfile $file: $!", fatal=>0); |
986
|
|
|
|
|
|
|
|
987
|
0
|
|
|
|
|
|
$self->audit("compressed $file"); |
988
|
0
|
|
|
|
|
|
return 1; |
989
|
|
|
|
|
|
|
} |
990
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
sub purge_last_months_logs { |
992
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
993
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
994
|
|
|
|
|
|
|
|
995
|
0
|
0
|
|
|
|
|
if ( ! $self->conf->{logs_archive_purge} ) { |
996
|
0
|
|
|
|
|
|
$self->audit( "logs_archive_purge is disabled in toaster.conf, skipping.\n"); |
997
|
0
|
|
|
|
|
|
return 1; |
998
|
|
|
|
|
|
|
}; |
999
|
|
|
|
|
|
|
|
1000
|
0
|
0
|
|
|
|
|
my ( $dd, $mm, $yy ) = $self->util->get_the_date(bump=>31 ) or return; |
1001
|
|
|
|
|
|
|
|
1002
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
1003
|
|
|
|
|
|
|
|
1004
|
0
|
0
|
0
|
|
|
|
unless ( $logbase && -d $logbase ) { |
1005
|
0
|
|
|
|
|
|
carp "purge_last_months_logs: no log directory $logbase. I'm done!"; |
1006
|
0
|
|
|
|
|
|
return 1; |
1007
|
|
|
|
|
|
|
}; |
1008
|
|
|
|
|
|
|
|
1009
|
0
|
|
|
|
|
|
my $last_m_log = "$logbase/$yy/$mm"; |
1010
|
|
|
|
|
|
|
|
1011
|
0
|
0
|
|
|
|
|
if ( ! -d $last_m_log ) { |
1012
|
0
|
0
|
|
|
|
|
print "purge_last_months_logs: log dir $last_m_log doesn't exist. I'm done.\n" if $verbose; |
1013
|
0
|
|
|
|
|
|
return 1; |
1014
|
|
|
|
|
|
|
}; |
1015
|
|
|
|
|
|
|
|
1016
|
0
|
0
|
|
|
|
|
print "\nI'm about to delete $last_m_log...." if $verbose; |
1017
|
0
|
0
|
|
|
|
|
if ( rmtree($last_m_log) ) { |
1018
|
0
|
0
|
|
|
|
|
print "done.\n\n" if $verbose; |
1019
|
0
|
|
|
|
|
|
return 1; |
1020
|
|
|
|
|
|
|
}; |
1021
|
|
|
|
|
|
|
|
1022
|
0
|
|
|
|
|
|
return; |
1023
|
|
|
|
|
|
|
} |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
sub check_log_files { |
1026
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1027
|
0
|
|
|
|
|
|
my @exists; |
1028
|
0
|
|
|
|
|
|
foreach my $file ( @_ ) { |
1029
|
0
|
0
|
0
|
|
|
|
next if !$file || ! -e $file; |
1030
|
0
|
|
|
|
|
|
push @exists, $file; |
1031
|
|
|
|
|
|
|
}; |
1032
|
0
|
|
|
|
|
|
return \@exists; |
1033
|
|
|
|
|
|
|
} |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
sub check_log_files_2 { |
1036
|
|
|
|
|
|
|
# this will be for logcheck based counters - someday |
1037
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
1038
|
0
|
|
|
|
|
|
my @exists; |
1039
|
0
|
|
|
|
|
|
foreach my $file ( @_ ) { }; |
1040
|
0
|
|
|
|
|
|
return \@exists; |
1041
|
|
|
|
|
|
|
}; |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
sub process_pop3_logs { |
1044
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1045
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
1046
|
|
|
|
|
|
|
|
1047
|
0
|
|
|
|
|
|
my %p = validate(@_, { |
1048
|
|
|
|
|
|
|
'roll' => { type=>BOOLEAN, optional=>1, default=>0 }, |
1049
|
|
|
|
|
|
|
'files' => { type=>ARRAYREF, optional=>1 } |
1050
|
|
|
|
|
|
|
} |
1051
|
|
|
|
|
|
|
); |
1052
|
|
|
|
|
|
|
|
1053
|
0
|
|
|
|
|
|
my $files_ref = $p{files}; |
1054
|
|
|
|
|
|
|
|
1055
|
0
|
|
|
|
|
|
my $skip_archive = 0; |
1056
|
0
|
0
|
0
|
|
|
|
$skip_archive++ if !$files_ref || !$files_ref->[0]; # no log file(s)! |
1057
|
|
|
|
|
|
|
|
1058
|
0
|
0
|
|
|
|
|
if ( $p{roll} ) { |
1059
|
|
|
|
|
|
|
|
1060
|
0
|
|
|
|
|
|
my $PIPE_TO_CRONOLOG; |
1061
|
0
|
0
|
|
|
|
|
if ( ! $skip_archive ) { |
1062
|
0
|
0
|
|
|
|
|
$PIPE_TO_CRONOLOG = $self->get_cronolog_handle("pop3log") |
1063
|
|
|
|
|
|
|
or $skip_archive++; |
1064
|
|
|
|
|
|
|
}; |
1065
|
|
|
|
|
|
|
|
1066
|
0
|
|
|
|
|
|
while (<STDIN>) { |
1067
|
0
|
0
|
|
|
|
|
print $_ if $self->conf->{logs_taifiles}; |
1068
|
0
|
0
|
|
|
|
|
print $PIPE_TO_CRONOLOG $_ if ! $skip_archive; |
1069
|
|
|
|
|
|
|
} |
1070
|
0
|
0
|
|
|
|
|
close $PIPE_TO_CRONOLOG if ! $skip_archive; |
1071
|
0
|
|
|
|
|
|
return $skip_archive; |
1072
|
|
|
|
|
|
|
} |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
# these logfiles are empty unless verbose is enabled |
1075
|
0
|
|
|
|
|
|
foreach my $file ( @$files_ref ) { |
1076
|
0
|
|
|
|
|
|
$self->audit( " reading file $file..."); |
1077
|
|
|
|
|
|
|
|
1078
|
0
|
|
|
|
|
|
my $MULTILOG_FILE; |
1079
|
0
|
0
|
|
|
|
|
open ($MULTILOG_FILE, '<', $file ) or do { |
1080
|
0
|
|
|
|
|
|
carp "couldn't read $file: $!"; |
1081
|
0
|
|
|
|
|
|
$skip_archive++; |
1082
|
0
|
|
|
|
|
|
next; |
1083
|
|
|
|
|
|
|
}; |
1084
|
|
|
|
|
|
|
|
1085
|
0
|
|
|
|
|
|
while (<$MULTILOG_FILE>) { |
1086
|
0
|
|
|
|
|
|
chomp; |
1087
|
|
|
|
|
|
|
#count_pop3_line( $_ ); |
1088
|
|
|
|
|
|
|
} |
1089
|
0
|
|
|
|
|
|
close $MULTILOG_FILE; |
1090
|
0
|
0
|
|
|
|
|
$self->audit( "done.") if $verbose; |
1091
|
|
|
|
|
|
|
} |
1092
|
|
|
|
|
|
|
|
1093
|
0
|
|
|
|
|
|
return $skip_archive; |
1094
|
|
|
|
|
|
|
} |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
sub process_rbl_logs { |
1097
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1098
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
1099
|
|
|
|
|
|
|
|
1100
|
0
|
|
|
|
|
|
my %p = validate( @_, { |
1101
|
|
|
|
|
|
|
'roll' => { type=>BOOLEAN, optional=>1, default=>0 }, |
1102
|
|
|
|
|
|
|
'files' => { type=>ARRAYREF,optional=>1, }, |
1103
|
|
|
|
|
|
|
}, |
1104
|
|
|
|
|
|
|
); |
1105
|
|
|
|
|
|
|
|
1106
|
0
|
|
|
|
|
|
my $files_ref = $p{files}; |
1107
|
|
|
|
|
|
|
|
1108
|
0
|
|
|
|
|
|
my $skip_archive = 0; |
1109
|
0
|
0
|
0
|
|
|
|
$skip_archive++ if ! $files_ref || !$files_ref->[0]; # no log file(s)! |
1110
|
|
|
|
|
|
|
|
1111
|
0
|
0
|
|
|
|
|
if ( $p{roll} ) { |
1112
|
0
|
|
|
|
|
|
my $PIPE_TO_CRONOLOG; |
1113
|
0
|
0
|
|
|
|
|
if ( ! $skip_archive ) { |
1114
|
0
|
0
|
|
|
|
|
$PIPE_TO_CRONOLOG = $self->get_cronolog_handle('smtplog') |
1115
|
|
|
|
|
|
|
or $skip_archive++; |
1116
|
|
|
|
|
|
|
}; |
1117
|
|
|
|
|
|
|
|
1118
|
0
|
|
|
|
|
|
while (<STDIN>) { |
1119
|
0
|
|
|
|
|
|
$self->count_rbl_line ( $_ ); |
1120
|
0
|
0
|
|
|
|
|
print $_ if $self->conf->{logs_taifiles}; |
1121
|
0
|
0
|
|
|
|
|
print $PIPE_TO_CRONOLOG $_ if ! $skip_archive; |
1122
|
|
|
|
|
|
|
} |
1123
|
0
|
0
|
|
|
|
|
close $PIPE_TO_CRONOLOG if ! $skip_archive; |
1124
|
0
|
|
|
|
|
|
return $skip_archive; |
1125
|
|
|
|
|
|
|
} |
1126
|
|
|
|
|
|
|
|
1127
|
0
|
|
|
|
|
|
foreach my $file ( @$files_ref ) { |
1128
|
0
|
0
|
|
|
|
|
print "process_rbl_logs: reading file $file..." if $verbose; |
1129
|
|
|
|
|
|
|
|
1130
|
0
|
|
|
|
|
|
my $MULTILOG_FILE; |
1131
|
0
|
0
|
|
|
|
|
open ($MULTILOG_FILE, "<", $file ) or do { |
1132
|
0
|
|
|
|
|
|
carp "couldn't read $file: $!"; |
1133
|
0
|
|
|
|
|
|
$skip_archive++; |
1134
|
0
|
|
|
|
|
|
next; |
1135
|
|
|
|
|
|
|
}; |
1136
|
|
|
|
|
|
|
|
1137
|
0
|
|
|
|
|
|
while (<$MULTILOG_FILE>) { $self->count_rbl_line( $_ ); } |
|
0
|
|
|
|
|
|
|
1138
|
0
|
|
|
|
|
|
close $MULTILOG_FILE ; |
1139
|
0
|
0
|
|
|
|
|
print "done.\n" if $verbose; |
1140
|
|
|
|
|
|
|
} |
1141
|
|
|
|
|
|
|
|
1142
|
0
|
|
|
|
|
|
return $skip_archive; |
1143
|
|
|
|
|
|
|
} |
1144
|
|
|
|
|
|
|
|
1145
|
|
|
|
|
|
|
sub count_rbl_line { |
1146
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1147
|
0
|
0
|
|
|
|
|
my $line = shift or return; |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
# comment out print lines |
1150
|
0
|
|
|
|
|
|
chomp $line; |
1151
|
|
|
|
|
|
|
|
1152
|
0
|
0
|
|
|
|
|
if ( $line =~ /rblsmtpd/ ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
# match the most common entries earliest |
1154
|
0
|
0
|
|
|
|
|
if ( $line =~ /spamhaus/ ) { $spam_ref->{spamhaus}++ } |
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1155
|
0
|
|
|
|
|
|
elsif ( $line =~ /spamcop/ ) { $spam_ref->{spamcop}++ } |
1156
|
0
|
|
|
|
|
|
elsif ( $line =~ /dsbl\.org/ ) { $spam_ref->{dsbl}++ } |
1157
|
0
|
|
|
|
|
|
elsif ( $line =~ /services/ ) { $spam_ref->{services}++ } |
1158
|
0
|
|
|
|
|
|
elsif ( $line =~ /rfc-ignorant/ ) { $spam_ref->{ignorant}++ } |
1159
|
0
|
|
|
|
|
|
elsif ( $line =~ /sorbs/ ) { $spam_ref->{sorbs}++ } |
1160
|
0
|
|
|
|
|
|
elsif ( $line =~ /njabl/ ) { $spam_ref->{njabl}++ } |
1161
|
0
|
|
|
|
|
|
elsif ( $line =~ /ORDB/ ) { $spam_ref->{ordb}++ } |
1162
|
0
|
|
|
|
|
|
elsif ( $line =~ /mail-abuse/ ) { $spam_ref->{maps}++ } |
1163
|
0
|
|
|
|
|
|
elsif ( $line =~ /monkeys/ ) { $spam_ref->{monkeys}++ } |
1164
|
0
|
|
|
|
|
|
elsif ( $line =~ /visi/ ) { $spam_ref->{visi}++ } |
1165
|
|
|
|
|
|
|
else { |
1166
|
|
|
|
|
|
|
#print $line; |
1167
|
0
|
|
|
|
|
|
$spam_ref->{other}++; |
1168
|
|
|
|
|
|
|
} |
1169
|
|
|
|
|
|
|
} |
1170
|
|
|
|
|
|
|
elsif ( $line =~ /CHKUSER/ ) { |
1171
|
0
|
0
|
|
|
|
|
if ( $line =~ /CHKUSER acce/ ) { $spam_ref->{ham}++ } |
|
0
|
0
|
|
|
|
|
|
1172
|
0
|
|
|
|
|
|
elsif ( $line =~ /CHKUSER reje/ ) { $spam_ref->{chkuser}++ } |
1173
|
|
|
|
|
|
|
else { |
1174
|
|
|
|
|
|
|
#print $line; |
1175
|
0
|
|
|
|
|
|
$spam_ref->{other}++; |
1176
|
|
|
|
|
|
|
} |
1177
|
|
|
|
|
|
|
} |
1178
|
|
|
|
|
|
|
elsif ( $line =~ /simscan/i ) { |
1179
|
0
|
0
|
|
|
|
|
if ( $line =~ /clean/i ) { $spam_ref->{ham}++ } |
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1180
|
0
|
|
|
|
|
|
elsif ( $line =~ /virus:/i ) { $spam_ref->{virus}++ } |
1181
|
0
|
|
|
|
|
|
elsif ( $line =~ /spam rej/i ) { $spam_ref->{spamassassin}++ } |
1182
|
|
|
|
|
|
|
else { |
1183
|
|
|
|
|
|
|
#print $line; |
1184
|
0
|
|
|
|
|
|
$spam_ref->{other}++; |
1185
|
|
|
|
|
|
|
}; |
1186
|
|
|
|
|
|
|
} |
1187
|
|
|
|
|
|
|
else { |
1188
|
0
|
0
|
|
|
|
|
if ( $line =~ /badhelo:/ ) { $spam_ref->{badhelo}++ } |
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1189
|
0
|
|
|
|
|
|
elsif ( $line =~ /badmailfrom:/ ) { $spam_ref->{badmailfrom}++ } |
1190
|
0
|
|
|
|
|
|
elsif ( $line =~ /badmailto:/ ) { $spam_ref->{badmailto}++ } |
1191
|
0
|
|
|
|
|
|
elsif ( $line =~ /Reverse/ ) { $spam_ref->{dns}++ } |
1192
|
|
|
|
|
|
|
else { |
1193
|
|
|
|
|
|
|
#print $line; |
1194
|
0
|
|
|
|
|
|
$spam_ref->{other}++; |
1195
|
|
|
|
|
|
|
}; |
1196
|
|
|
|
|
|
|
} |
1197
|
|
|
|
|
|
|
|
1198
|
0
|
|
|
|
|
|
$spam_ref->{count}++; |
1199
|
0
|
|
|
|
|
|
return 1; |
1200
|
|
|
|
|
|
|
} |
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
sub process_send_logs { |
1203
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1204
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
1205
|
|
|
|
|
|
|
|
1206
|
0
|
|
|
|
|
|
my %p = validate( @_, { |
1207
|
|
|
|
|
|
|
'roll' => { type=>SCALAR, optional=>1, default=>0 }, |
1208
|
|
|
|
|
|
|
'files' => { type=>ARRAYREF,optional=>1, }, |
1209
|
|
|
|
|
|
|
}, |
1210
|
|
|
|
|
|
|
); |
1211
|
|
|
|
|
|
|
|
1212
|
0
|
|
|
|
|
|
my $files_ref = $p{files}; |
1213
|
|
|
|
|
|
|
|
1214
|
0
|
|
|
|
|
|
my $skip_archive = 0; |
1215
|
0
|
0
|
0
|
|
|
|
$skip_archive++ if ! $files_ref || !$files_ref->[0]; # no log files |
1216
|
|
|
|
|
|
|
|
1217
|
0
|
0
|
|
|
|
|
if ( $p{roll} ) { |
1218
|
|
|
|
|
|
|
|
1219
|
0
|
0
|
|
|
|
|
print "process_send_logs: log rolling is enabled.\n" if $verbose; |
1220
|
|
|
|
|
|
|
|
1221
|
0
|
|
|
|
|
|
my $PIPE_TO_CRONOLOG; |
1222
|
0
|
0
|
|
|
|
|
if ( ! $skip_archive ) { |
1223
|
0
|
0
|
|
|
|
|
$PIPE_TO_CRONOLOG = $self->get_cronolog_handle("sendlog") |
1224
|
|
|
|
|
|
|
or $skip_archive++; |
1225
|
|
|
|
|
|
|
}; |
1226
|
|
|
|
|
|
|
|
1227
|
0
|
|
|
|
|
|
while (<STDIN>) { |
1228
|
0
|
|
|
|
|
|
$self->count_send_line( $_ ); |
1229
|
0
|
0
|
|
|
|
|
print $_ if $self->conf->{logs_taifiles}; |
1230
|
0
|
0
|
|
|
|
|
print $PIPE_TO_CRONOLOG $_ if ! $skip_archive; |
1231
|
|
|
|
|
|
|
} |
1232
|
0
|
0
|
|
|
|
|
close $PIPE_TO_CRONOLOG if ! $skip_archive; |
1233
|
0
|
|
|
|
|
|
return $skip_archive; |
1234
|
|
|
|
|
|
|
} |
1235
|
|
|
|
|
|
|
|
1236
|
0
|
0
|
|
|
|
|
print "process_send_logs: log rolling is disabled.\n" if $verbose; |
1237
|
|
|
|
|
|
|
|
1238
|
0
|
|
|
|
|
|
foreach my $file ( @$files_ref ) { |
1239
|
|
|
|
|
|
|
|
1240
|
0
|
0
|
|
|
|
|
print "process_send_logs: reading file $file.\n" if $verbose; |
1241
|
|
|
|
|
|
|
|
1242
|
0
|
|
|
|
|
|
my $INFILE; |
1243
|
0
|
0
|
|
|
|
|
open( $INFILE, "<", $file ) or do { |
1244
|
0
|
|
|
|
|
|
carp "process_send_logs couldn't read $file: $!"; |
1245
|
0
|
|
|
|
|
|
$skip_archive++; |
1246
|
0
|
|
|
|
|
|
next; |
1247
|
|
|
|
|
|
|
}; |
1248
|
|
|
|
|
|
|
|
1249
|
0
|
|
|
|
|
|
while (<$INFILE>) { |
1250
|
0
|
|
|
|
|
|
chomp; |
1251
|
0
|
|
|
|
|
|
$self->count_send_line( $_ ); |
1252
|
|
|
|
|
|
|
} |
1253
|
0
|
|
|
|
|
|
close $INFILE; |
1254
|
|
|
|
|
|
|
} |
1255
|
|
|
|
|
|
|
|
1256
|
0
|
|
|
|
|
|
return $skip_archive; |
1257
|
|
|
|
|
|
|
} |
1258
|
|
|
|
|
|
|
|
1259
|
|
|
|
|
|
|
sub count_send_line { |
1260
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1261
|
0
|
0
|
|
|
|
|
my $line = shift or do { |
1262
|
0
|
|
|
|
|
|
$count_ref->{message_other}++; |
1263
|
0
|
|
|
|
|
|
return; |
1264
|
|
|
|
|
|
|
}; |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
########## $line will have a log entry in this format ######## |
1267
|
|
|
|
|
|
|
# @40000000450c020b32315f74 new msg 71198 |
1268
|
|
|
|
|
|
|
# @40000000450c020b32356e84 info msg 71198: bytes 3042 from <doc-committers@FreeBSD.org> qp 44209 uid 89 |
1269
|
|
|
|
|
|
|
# @40000000450c020b357ed10c starting delivery 196548: msg 71198 to localexample.org-user@example.org |
1270
|
|
|
|
|
|
|
# @40000000450c020b357f463c status: local 1/10 remote 0/100 |
1271
|
|
|
|
|
|
|
# @40000000450c020c06ac5dcc delivery 196548: success: did_0+0+1/ |
1272
|
|
|
|
|
|
|
# @40000000450c020c06b6122c status: local 0/10 remote 0/100 |
1273
|
|
|
|
|
|
|
# @40000000450c020c06be6ae4 end msg 71198 |
1274
|
|
|
|
|
|
|
################################################ |
1275
|
|
|
|
|
|
|
|
1276
|
0
|
|
|
|
|
|
chomp $line; |
1277
|
|
|
|
|
|
|
#carp "$line"; |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
# split the line into date and activity |
1280
|
0
|
|
|
|
|
|
my ( $tai_date, $activity ) = $line =~ /\A@([a-z0-9]*)\s(.*)\z/xms; |
1281
|
|
|
|
|
|
|
|
1282
|
0
|
0
|
|
|
|
|
unless ($activity) { |
1283
|
0
|
|
|
|
|
|
$count_ref->{message_other}++; |
1284
|
0
|
|
|
|
|
|
return; |
1285
|
|
|
|
|
|
|
}; |
1286
|
|
|
|
|
|
|
|
1287
|
0
|
0
|
|
|
|
|
if ( $activity =~ /^new msg/ ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1288
|
|
|
|
|
|
|
# new msg 71512 |
1289
|
|
|
|
|
|
|
# the complete line match: /^new msg ([0-9]*)/ |
1290
|
0
|
|
|
|
|
|
$count_ref->{message_new}++; |
1291
|
|
|
|
|
|
|
} |
1292
|
|
|
|
|
|
|
elsif ( $activity =~ /^info msg / ) { |
1293
|
|
|
|
|
|
|
# info msg 71766: bytes 28420 from <elfer@club-internet.fr> qp 5419 uid 89 |
1294
|
|
|
|
|
|
|
# a complete line match |
1295
|
|
|
|
|
|
|
# /^info msg ([0-9]*): bytes ([0-9]*) from \<(.*)\> qp ([0-9]*)/ |
1296
|
|
|
|
|
|
|
|
1297
|
0
|
|
|
|
|
|
$activity =~ /^info msg ([0-9]*): bytes ([0-9]*) from/; |
1298
|
|
|
|
|
|
|
|
1299
|
0
|
|
|
|
|
|
$count_ref->{message_bytes} += $2; |
1300
|
0
|
|
|
|
|
|
$count_ref->{message_info}++; |
1301
|
|
|
|
|
|
|
} |
1302
|
|
|
|
|
|
|
elsif ( $activity =~ /^starting delivery/ ) { |
1303
|
|
|
|
|
|
|
|
1304
|
|
|
|
|
|
|
# starting delivery 136986: msg 71766 to remote bbarnes@example.com |
1305
|
|
|
|
|
|
|
|
1306
|
|
|
|
|
|
|
# a more complete line match |
1307
|
|
|
|
|
|
|
# /^starting delivery ([0-9]*): msg ([0-9]*) to ([a-z]*) ([a-zA-Z\@\._-])$/ |
1308
|
|
|
|
|
|
|
|
1309
|
0
|
|
|
|
|
|
$activity =~ /^starting delivery ([0-9]*): msg ([0-9]*) to ([a-z]*) /; |
1310
|
|
|
|
|
|
|
|
1311
|
0
|
0
|
|
|
|
|
if ( $3 eq "remote" ) { $count_ref->{start_delivery_remote}++ } |
|
0
|
0
|
|
|
|
|
|
1312
|
0
|
|
|
|
|
|
elsif ( $3 eq "local" ) { $count_ref->{start_delivery_local}++ } |
1313
|
0
|
|
|
|
|
|
else { print "count_send_line: unknown delivery line format\n"; }; |
1314
|
|
|
|
|
|
|
|
1315
|
0
|
|
|
|
|
|
$count_ref->{start_delivery}++; |
1316
|
|
|
|
|
|
|
} |
1317
|
|
|
|
|
|
|
elsif ( $activity =~ /^status: local/ ) { |
1318
|
|
|
|
|
|
|
# status: local 0/10 remote 3/100 |
1319
|
0
|
|
|
|
|
|
$activity =~ /^status: local ([0-9]*)\/([0-9]*) remote ([0-9]*)\/([0-9]*)/; |
1320
|
|
|
|
|
|
|
|
1321
|
0
|
|
|
|
|
|
$count_ref->{status_localp} += ( $1 / $2 ); |
1322
|
0
|
|
|
|
|
|
$count_ref->{status_remotep} += ( $3 / $4 ); |
1323
|
|
|
|
|
|
|
|
1324
|
0
|
|
|
|
|
|
$count_ref->{status}++; |
1325
|
|
|
|
|
|
|
} |
1326
|
|
|
|
|
|
|
elsif ( $activity =~ /^end msg/ ) { |
1327
|
|
|
|
|
|
|
# end msg 71766 |
1328
|
|
|
|
|
|
|
# /^end msg ([0-9]*)$/ |
1329
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
# this line is useless, why was it here? |
1331
|
|
|
|
|
|
|
#$count_ref->{local}++ if ( $3 && $3 eq "local" ); |
1332
|
|
|
|
|
|
|
|
1333
|
0
|
|
|
|
|
|
$count_ref->{message_end}++; |
1334
|
|
|
|
|
|
|
} |
1335
|
|
|
|
|
|
|
elsif ( $activity =~ /^delivery/ ) { |
1336
|
|
|
|
|
|
|
# delivery 136986: success: 67.109.54.82_accepted_message./Remote_host_said: |
1337
|
|
|
|
|
|
|
# _250_2.6.0__<000c01c6c92a$97f4a580$8a46c3d4@p3>_Queued_mail_for_delivery/ |
1338
|
|
|
|
|
|
|
|
1339
|
0
|
|
|
|
|
|
$activity =~ /^delivery ([0-9]*): ([a-z]*): /; |
1340
|
|
|
|
|
|
|
|
1341
|
0
|
0
|
|
|
|
|
if ( $2 eq "success" ) { $count_ref->{delivery_success}++ } |
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1342
|
0
|
|
|
|
|
|
elsif ( $2 eq "deferral" ) { $count_ref->{delivery_deferral}++ } |
1343
|
0
|
|
|
|
|
|
elsif ( $2 eq "failure" ) { $count_ref->{delivery_failure}++ } |
1344
|
0
|
|
|
|
|
|
else { print "unknown " . $activity . "\n"; }; |
1345
|
|
|
|
|
|
|
|
1346
|
0
|
|
|
|
|
|
$count_ref->{delivery}++; |
1347
|
|
|
|
|
|
|
} |
1348
|
|
|
|
|
|
|
elsif ( $activity =~ /^bounce/ ) { |
1349
|
|
|
|
|
|
|
# /^bounce msg ([0-9]*) [a-z]* ([0-9]*)/ |
1350
|
0
|
|
|
|
|
|
$count_ref->{message_bounce}++; |
1351
|
|
|
|
|
|
|
} |
1352
|
|
|
|
|
|
|
else { |
1353
|
|
|
|
|
|
|
#warn "other: $activity"; |
1354
|
0
|
|
|
|
|
|
$count_ref->{other}++; |
1355
|
|
|
|
|
|
|
} |
1356
|
|
|
|
|
|
|
|
1357
|
0
|
|
|
|
|
|
return 1; |
1358
|
|
|
|
|
|
|
} |
1359
|
|
|
|
|
|
|
|
1360
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
sub counter_create { |
1362
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
1363
|
0
|
|
|
|
|
|
my $file = shift; |
1364
|
|
|
|
|
|
|
|
1365
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
1366
|
0
|
0
|
|
|
|
|
carp "\nWARN: the file $file is missing! I will try to create it." if $verbose; |
1367
|
|
|
|
|
|
|
|
1368
|
0
|
0
|
|
|
|
|
if ( ! $self->util->is_writable( $file,verbose=>0,fatal=>0) ) { |
1369
|
0
|
0
|
|
|
|
|
carp "FAILED.\n $file does not exist and the user $UID has " |
1370
|
|
|
|
|
|
|
. "insufficent privileges to create it!" if $verbose; |
1371
|
0
|
|
|
|
|
|
return; |
1372
|
|
|
|
|
|
|
}; |
1373
|
|
|
|
|
|
|
|
1374
|
0
|
|
|
|
|
|
$self->counter_write( log => $file, values => { created => time, },); |
1375
|
|
|
|
|
|
|
|
1376
|
0
|
|
0
|
|
|
|
my $user = $self->{conf}{logs_user} || "qmaill"; |
1377
|
0
|
|
0
|
|
|
|
my $group = $self->{conf}{logs_group} || "qnofiles"; |
1378
|
|
|
|
|
|
|
|
1379
|
0
|
|
|
|
|
|
$self->util->chown( $file, uid=>$user, gid=>$group, verbose=>0); |
1380
|
|
|
|
|
|
|
|
1381
|
0
|
|
|
|
|
|
print "done.\n"; |
1382
|
0
|
|
|
|
|
|
return 1; |
1383
|
|
|
|
|
|
|
}; |
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
sub counter_read { |
1386
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1387
|
0
|
|
|
|
|
|
my %p = validate(@_, { 'file' => SCALAR, $self->get_std_opts } ); |
1388
|
0
|
|
|
|
|
|
my %args = $self->get_std_args( %p ); |
1389
|
|
|
|
|
|
|
|
1390
|
0
|
0
|
|
|
|
|
my $file = $p{file} or croak "you must pass a filename!\n"; |
1391
|
0
|
|
|
|
|
|
my $verbose = $p{verbose}; |
1392
|
|
|
|
|
|
|
|
1393
|
0
|
0
|
|
|
|
|
if ( ! -e $file ) { |
1394
|
0
|
0
|
|
|
|
|
$self->counter_create( $file ) or return; |
1395
|
|
|
|
|
|
|
} |
1396
|
|
|
|
|
|
|
|
1397
|
0
|
|
|
|
|
|
my %hash = ( |
1398
|
|
|
|
|
|
|
connect_last => 0, |
1399
|
|
|
|
|
|
|
success_last => 0 |
1400
|
|
|
|
|
|
|
); |
1401
|
|
|
|
|
|
|
|
1402
|
0
|
|
|
|
|
|
foreach ( $self->util->file_read( $file, verbose=>$verbose ) ) { |
1403
|
0
|
|
|
|
|
|
my ($description, $count) = split( /:/, $_ ); |
1404
|
0
|
|
|
|
|
|
$hash{ $description } = $count; |
1405
|
|
|
|
|
|
|
} |
1406
|
|
|
|
|
|
|
|
1407
|
0
|
|
|
|
|
|
$self->audit( "counter_read: read counters from $file", %args ); |
1408
|
|
|
|
|
|
|
|
1409
|
0
|
|
|
|
|
|
return \%hash; |
1410
|
|
|
|
|
|
|
} |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
sub counter_write { |
1413
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1414
|
0
|
|
|
|
|
|
my %p = validate( @_, { |
1415
|
|
|
|
|
|
|
'values' => HASHREF, |
1416
|
|
|
|
|
|
|
'log' => SCALAR, |
1417
|
|
|
|
|
|
|
$self->get_std_opts, |
1418
|
|
|
|
|
|
|
}, |
1419
|
|
|
|
|
|
|
); |
1420
|
0
|
|
|
|
|
|
my %args = $self->get_std_args( %p ); |
1421
|
|
|
|
|
|
|
|
1422
|
0
|
|
|
|
|
|
my ( $logfile, $values_ref ) = ( $p{log}, $p{values} ); |
1423
|
|
|
|
|
|
|
|
1424
|
0
|
0
|
|
|
|
|
if ( -d $logfile ) { |
1425
|
0
|
|
|
|
|
|
print "FAILURE: counter_write $logfile is a directory!\n"; |
1426
|
|
|
|
|
|
|
} |
1427
|
|
|
|
|
|
|
|
1428
|
0
|
0
|
|
|
|
|
return $self->error( "counter_write: $logfile is not writable",fatal=>0 ) |
1429
|
|
|
|
|
|
|
unless $self->util->is_writable( $logfile, %args ); |
1430
|
|
|
|
|
|
|
|
1431
|
0
|
0
|
|
|
|
|
unless ( -e $logfile ) { |
1432
|
0
|
|
|
|
|
|
print "NOTICE: counter_write is creating $logfile"; |
1433
|
|
|
|
|
|
|
} |
1434
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
# it might be necessary to wrap the counters |
1436
|
|
|
|
|
|
|
# |
1437
|
|
|
|
|
|
|
# if so, the 32 and 64 bit limits are listed below. Just |
1438
|
|
|
|
|
|
|
# check the number, and subtract the maximum value for it. |
1439
|
|
|
|
|
|
|
# rrdtool will continue to Do The Right Thing. :) |
1440
|
|
|
|
|
|
|
|
1441
|
0
|
|
|
|
|
|
my @lines; |
1442
|
0
|
|
|
|
|
|
while ( my ($key, $value) = each %$values_ref ) { |
1443
|
0
|
|
|
|
|
|
$self->audit( "key: $key \t val: $value", %args); |
1444
|
0
|
0
|
0
|
|
|
|
if ( $key && defined $value ) { |
1445
|
|
|
|
|
|
|
# 32 bit - 4294967295 |
1446
|
|
|
|
|
|
|
# 64 bit - 18446744073709551615 |
1447
|
0
|
0
|
|
|
|
|
if ( $value > 4294967295 ) { $value = $value - 4294967295; }; |
|
0
|
|
|
|
|
|
|
1448
|
0
|
|
|
|
|
|
push @lines, "$key:$value"; |
1449
|
|
|
|
|
|
|
} |
1450
|
|
|
|
|
|
|
} |
1451
|
|
|
|
|
|
|
|
1452
|
0
|
|
|
|
|
|
return $self->util->file_write( $logfile, lines => \@lines, %args ); |
1453
|
|
|
|
|
|
|
} |
1454
|
|
|
|
|
|
|
|
1455
|
|
|
|
|
|
|
sub get_cronolog_handle { |
1456
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
1457
|
0
|
0
|
|
|
|
|
my $file = shift or croak "missing file!"; |
1458
|
0
|
|
|
|
|
|
my $verbose = $self->{verbose}; |
1459
|
|
|
|
|
|
|
|
1460
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
# archives disabled in toaster.conf |
1463
|
0
|
0
|
|
|
|
|
if ( ! $self->conf->{logs_archive} ) { |
1464
|
0
|
0
|
|
|
|
|
warn "get_cronolog_handle: archives disabled, skipping cronolog handle.\n" if $verbose; |
1465
|
0
|
|
|
|
|
|
return; |
1466
|
|
|
|
|
|
|
}; |
1467
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
# $logbase is missing and we haven't permission to create it |
1469
|
0
|
0
|
|
|
|
|
unless ( -w $logbase ) { |
1470
|
0
|
|
|
|
|
|
warn "WARN: could not write to $logbase. FAILURE!"; |
1471
|
0
|
|
|
|
|
|
return; |
1472
|
|
|
|
|
|
|
}; |
1473
|
|
|
|
|
|
|
|
1474
|
0
|
|
|
|
|
|
my $cronolog = $self->util->find_bin( "cronolog", verbose=>0, fatal=>0 ); |
1475
|
0
|
0
|
0
|
|
|
|
if ( ! $cronolog || !-x $cronolog) { |
1476
|
0
|
|
|
|
|
|
warn "cronolog could not be found. Please install it!"; |
1477
|
0
|
|
|
|
|
|
return; |
1478
|
|
|
|
|
|
|
} |
1479
|
|
|
|
|
|
|
|
1480
|
0
|
|
|
|
|
|
my $tai64nlocal; |
1481
|
|
|
|
|
|
|
|
1482
|
0
|
0
|
|
|
|
|
if ( $self->conf->{logs_archive_untai} ) { |
1483
|
0
|
|
|
|
|
|
my $taibin = $self->util->find_bin( "tai64nlocal",verbose=>0, fatal=>0 ); |
1484
|
|
|
|
|
|
|
|
1485
|
0
|
0
|
|
|
|
|
if ( ! $taibin ) { |
1486
|
0
|
|
|
|
|
|
carp "tai64nlocal is selected in toaster.conf but cannot be found!"; |
1487
|
|
|
|
|
|
|
}; |
1488
|
|
|
|
|
|
|
|
1489
|
0
|
0
|
0
|
|
|
|
if ( $taibin && ! -x $taibin ) { |
1490
|
0
|
|
|
|
|
|
carp "tai64nlocal is not executable by you! ERROR!"; |
1491
|
|
|
|
|
|
|
} |
1492
|
|
|
|
|
|
|
|
1493
|
0
|
|
|
|
|
|
$tai64nlocal = $taibin; |
1494
|
|
|
|
|
|
|
} |
1495
|
|
|
|
|
|
|
|
1496
|
0
|
|
|
|
|
|
my $cronolog_invocation = "| "; |
1497
|
0
|
0
|
|
|
|
|
$cronolog_invocation .= "$tai64nlocal | " if $tai64nlocal; |
1498
|
0
|
|
|
|
|
|
$cronolog_invocation .= "$cronolog $logbase/\%Y/\%m/\%d/$file"; |
1499
|
|
|
|
|
|
|
|
1500
|
|
|
|
|
|
|
## no critic |
1501
|
0
|
0
|
|
|
|
|
open my $PIPE_TO_CRONOLOG, $cronolog_invocation or return; |
1502
|
|
|
|
|
|
|
## use critic |
1503
|
|
|
|
|
|
|
|
1504
|
0
|
|
|
|
|
|
return $PIPE_TO_CRONOLOG; |
1505
|
|
|
|
|
|
|
}; |
1506
|
|
|
|
|
|
|
|
1507
|
|
|
|
|
|
|
sub syslog_locate { |
1508
|
0
|
|
|
0
|
1
|
|
my ( $self, $verbose ) = @_; |
1509
|
|
|
|
|
|
|
|
1510
|
0
|
|
|
|
|
|
my $log = "/var/log/maillog"; |
1511
|
|
|
|
|
|
|
|
1512
|
0
|
0
|
|
|
|
|
if ( -e $log ) { |
1513
|
0
|
0
|
|
|
|
|
print "syslog_locate: using $log\n" if $verbose; |
1514
|
0
|
|
|
|
|
|
return "$log"; |
1515
|
|
|
|
|
|
|
} |
1516
|
|
|
|
|
|
|
|
1517
|
0
|
|
|
|
|
|
$log = "/var/log/mail.log"; |
1518
|
0
|
0
|
|
|
|
|
if ( $OSNAME eq "darwin" ) { |
1519
|
0
|
0
|
|
|
|
|
print "syslog_locate: Darwin detected...using $log\n" if $verbose; |
1520
|
0
|
|
|
|
|
|
return $log; |
1521
|
|
|
|
|
|
|
} |
1522
|
|
|
|
|
|
|
|
1523
|
0
|
0
|
|
|
|
|
if ( -e $log ) { |
1524
|
0
|
0
|
|
|
|
|
print "syslog_locate: using $log\n" if $verbose; |
1525
|
0
|
|
|
|
|
|
return $log; |
1526
|
|
|
|
|
|
|
}; |
1527
|
|
|
|
|
|
|
|
1528
|
0
|
|
|
|
|
|
$log = "/var/log/messages"; |
1529
|
0
|
0
|
|
|
|
|
return $log if -e $log; |
1530
|
|
|
|
|
|
|
|
1531
|
0
|
|
|
|
|
|
$log = "/var/log/system.log"; |
1532
|
0
|
0
|
|
|
|
|
return $log if -e $log; |
1533
|
|
|
|
|
|
|
|
1534
|
0
|
|
|
|
|
|
croak "syslog_locate: can't find your syslog mail log\n"; |
1535
|
|
|
|
|
|
|
} |
1536
|
|
|
|
|
|
|
|
1537
|
|
|
|
|
|
|
sub set_countfile { |
1538
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
1539
|
|
|
|
|
|
|
|
1540
|
0
|
|
|
|
|
|
my %p = validate(@_, { prot=>SCALAR } ); |
1541
|
0
|
|
|
|
|
|
my $prot = $p{prot}; |
1542
|
|
|
|
|
|
|
|
1543
|
0
|
|
|
|
|
|
my $logbase = $self->toaster->get_log_dir; |
1544
|
0
|
|
0
|
|
|
|
my $counters = $self->conf->{logs_counters} || "counters"; |
1545
|
0
|
|
0
|
|
|
|
my $prot_file = $self->conf->{'logs_'.$prot.'_count'} || "$prot.txt"; |
1546
|
|
|
|
|
|
|
|
1547
|
|
|
|
|
|
|
# $self->audit( "countfile: $logbase/$counters/$prot_file"); |
1548
|
|
|
|
|
|
|
|
1549
|
0
|
|
|
|
|
|
return "$logbase/$counters/$prot_file"; |
1550
|
|
|
|
|
|
|
} |
1551
|
|
|
|
|
|
|
|
1552
|
|
|
|
|
|
|
1; |
1553
|
|
|
|
|
|
|
__END__ |
1554
|
|
|
|
|
|
|
sub {} |
1555
|
|
|
|
|
|
|
|
1556
|
|
|
|
|
|
|
=head1 NAME |
1557
|
|
|
|
|
|
|
|
1558
|
|
|
|
|
|
|
Mail::Toaster::Logs - objects and functions for interacting with email logs |
1559
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
This module contains functions related to mail logging and are used primarily in maillogs. Some functions are also used in toaster-watcher.pl and toaster_setup.pl. |
1561
|
|
|
|
|
|
|
|
1562
|
|
|
|
|
|
|
|
1563
|
|
|
|
|
|
|
=head1 METHODS |
1564
|
|
|
|
|
|
|
|
1565
|
|
|
|
|
|
|
=over 8 |
1566
|
|
|
|
|
|
|
|
1567
|
|
|
|
|
|
|
=item new |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
Create a new Mail::Toaster::Logs object. |
1570
|
|
|
|
|
|
|
|
1571
|
|
|
|
|
|
|
use Mail::Toaster::Logs; |
1572
|
|
|
|
|
|
|
$logs = Mail::Toaster::Logs->new; |
1573
|
|
|
|
|
|
|
|
1574
|
|
|
|
|
|
|
|
1575
|
|
|
|
|
|
|
=item report_yesterdays_activity |
1576
|
|
|
|
|
|
|
|
1577
|
|
|
|
|
|
|
email a report of yesterdays email traffic. |
1578
|
|
|
|
|
|
|
|
1579
|
|
|
|
|
|
|
|
1580
|
|
|
|
|
|
|
=item verify_settings |
1581
|
|
|
|
|
|
|
|
1582
|
|
|
|
|
|
|
Does some checks to make sure things are set up correctly. |
1583
|
|
|
|
|
|
|
|
1584
|
|
|
|
|
|
|
$logs->verify_settings; |
1585
|
|
|
|
|
|
|
|
1586
|
|
|
|
|
|
|
tests: |
1587
|
|
|
|
|
|
|
|
1588
|
|
|
|
|
|
|
logs base directory exists |
1589
|
|
|
|
|
|
|
logs based owned by qmaill |
1590
|
|
|
|
|
|
|
counters directory exists |
1591
|
|
|
|
|
|
|
maillogs is installed |
1592
|
|
|
|
|
|
|
|
1593
|
|
|
|
|
|
|
|
1594
|
|
|
|
|
|
|
=item parse_cmdline_flags |
1595
|
|
|
|
|
|
|
|
1596
|
|
|
|
|
|
|
Do the appropriate things based on what argument is passed on the command line. |
1597
|
|
|
|
|
|
|
|
1598
|
|
|
|
|
|
|
$logs->parse_cmdline_flags(prot=>$prot, verbose=>0); |
1599
|
|
|
|
|
|
|
|
1600
|
|
|
|
|
|
|
$prot is the protocol we're supposed to work on. |
1601
|
|
|
|
|
|
|
|
1602
|
|
|
|
|
|
|
|
1603
|
|
|
|
|
|
|
=item check_log_files |
1604
|
|
|
|
|
|
|
|
1605
|
|
|
|
|
|
|
$logs->check_log_files( $check ); |
1606
|
|
|
|
|
|
|
|
1607
|
|
|
|
|
|
|
|
1608
|
|
|
|
|
|
|
=item compress_yesterdays_logs |
1609
|
|
|
|
|
|
|
|
1610
|
|
|
|
|
|
|
$logs->compress_yesterdays_logs( $file ); |
1611
|
|
|
|
|
|
|
|
1612
|
|
|
|
|
|
|
|
1613
|
|
|
|
|
|
|
=item count_rbl_line |
1614
|
|
|
|
|
|
|
|
1615
|
|
|
|
|
|
|
$logs->count_rbl_line($line); |
1616
|
|
|
|
|
|
|
|
1617
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
=item count_send_line |
1619
|
|
|
|
|
|
|
|
1620
|
|
|
|
|
|
|
usage: |
1621
|
|
|
|
|
|
|
$logs->count_send_line( $count, $line ); |
1622
|
|
|
|
|
|
|
|
1623
|
|
|
|
|
|
|
arguments required: |
1624
|
|
|
|
|
|
|
count - a hashref of counter values |
1625
|
|
|
|
|
|
|
line - an entry from qmail's send logs |
1626
|
|
|
|
|
|
|
|
1627
|
|
|
|
|
|
|
results: |
1628
|
|
|
|
|
|
|
a hashref will be returned with updated counters |
1629
|
|
|
|
|
|
|
|
1630
|
|
|
|
|
|
|
|
1631
|
|
|
|
|
|
|
=item counter_read |
1632
|
|
|
|
|
|
|
|
1633
|
|
|
|
|
|
|
$logs->counter_read( file=>$file ); |
1634
|
|
|
|
|
|
|
|
1635
|
|
|
|
|
|
|
$file is the file to read from. The sub returns a hashref full of key value pairs. |
1636
|
|
|
|
|
|
|
|
1637
|
|
|
|
|
|
|
|
1638
|
|
|
|
|
|
|
=item counter_write |
1639
|
|
|
|
|
|
|
|
1640
|
|
|
|
|
|
|
$logs->counter_write(log=>$file, values=>$values); |
1641
|
|
|
|
|
|
|
|
1642
|
|
|
|
|
|
|
arguments required: |
1643
|
|
|
|
|
|
|
file - the logfile to write. |
1644
|
|
|
|
|
|
|
values - a hashref of value=count style pairs. |
1645
|
|
|
|
|
|
|
|
1646
|
|
|
|
|
|
|
result: |
1647
|
|
|
|
|
|
|
1 if written |
1648
|
|
|
|
|
|
|
0 if not. |
1649
|
|
|
|
|
|
|
|
1650
|
|
|
|
|
|
|
=cut |
1651
|
|
|
|
|
|
|
|
1652
|
|
|
|
|
|
|
=item imap_count |
1653
|
|
|
|
|
|
|
|
1654
|
|
|
|
|
|
|
$logs->imap_count; |
1655
|
|
|
|
|
|
|
|
1656
|
|
|
|
|
|
|
Count the number of connections and successful authentications via IMAP and IMAP-SSL. |
1657
|
|
|
|
|
|
|
|
1658
|
|
|
|
|
|
|
|
1659
|
|
|
|
|
|
|
=item pop3_count |
1660
|
|
|
|
|
|
|
|
1661
|
|
|
|
|
|
|
$logs->pop3_count; |
1662
|
|
|
|
|
|
|
|
1663
|
|
|
|
|
|
|
Count the number of connections and successful authentications via POP3 and POP3-SSL. |
1664
|
|
|
|
|
|
|
|
1665
|
|
|
|
|
|
|
|
1666
|
|
|
|
|
|
|
=item process_pop3_logs |
1667
|
|
|
|
|
|
|
|
1668
|
|
|
|
|
|
|
|
1669
|
|
|
|
|
|
|
=item process_rbl_logs |
1670
|
|
|
|
|
|
|
|
1671
|
|
|
|
|
|
|
process_rbl_logs( |
1672
|
|
|
|
|
|
|
roll => 0, |
1673
|
|
|
|
|
|
|
files => $self->check_log_files( "$logbase/smtp/current" ), |
1674
|
|
|
|
|
|
|
); |
1675
|
|
|
|
|
|
|
|
1676
|
|
|
|
|
|
|
|
1677
|
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
=item process_send_logs |
1679
|
|
|
|
|
|
|
|
1680
|
|
|
|
|
|
|
|
1681
|
|
|
|
|
|
|
|
1682
|
|
|
|
|
|
|
=item qms_count |
1683
|
|
|
|
|
|
|
|
1684
|
|
|
|
|
|
|
$logs->qms_count; |
1685
|
|
|
|
|
|
|
|
1686
|
|
|
|
|
|
|
Count statistics logged by qmail scanner. |
1687
|
|
|
|
|
|
|
|
1688
|
|
|
|
|
|
|
|
1689
|
|
|
|
|
|
|
=item purge_last_months_logs |
1690
|
|
|
|
|
|
|
|
1691
|
|
|
|
|
|
|
$logs->purge_last_months_logs( |
1692
|
|
|
|
|
|
|
fatal => 0, |
1693
|
|
|
|
|
|
|
); |
1694
|
|
|
|
|
|
|
|
1695
|
|
|
|
|
|
|
For a supplied protocol, cleans out last months email logs. |
1696
|
|
|
|
|
|
|
|
1697
|
|
|
|
|
|
|
|
1698
|
|
|
|
|
|
|
=item rbl_count |
1699
|
|
|
|
|
|
|
|
1700
|
|
|
|
|
|
|
Count the number of connections we've blocked (via rblsmtpd) for each RBL that we use. |
1701
|
|
|
|
|
|
|
|
1702
|
|
|
|
|
|
|
$logs->rbl_count( |
1703
|
|
|
|
|
|
|
|
1704
|
|
|
|
|
|
|
=item roll_rbl_logs |
1705
|
|
|
|
|
|
|
|
1706
|
|
|
|
|
|
|
$logs->roll_rbl_logs; |
1707
|
|
|
|
|
|
|
|
1708
|
|
|
|
|
|
|
Roll the qmail-smtpd logs (without 2>&1 output generated by rblsmtpd). |
1709
|
|
|
|
|
|
|
|
1710
|
|
|
|
|
|
|
=item RollPOP3Logs |
1711
|
|
|
|
|
|
|
|
1712
|
|
|
|
|
|
|
$logs->RollPOP3Logs; |
1713
|
|
|
|
|
|
|
|
1714
|
|
|
|
|
|
|
These logs will only exist if tcpserver verbose is enabled. Rolling them is not likely to be necessary but the code is here should it ever prove necessary. |
1715
|
|
|
|
|
|
|
|
1716
|
|
|
|
|
|
|
|
1717
|
|
|
|
|
|
|
=item roll_send_logs |
1718
|
|
|
|
|
|
|
|
1719
|
|
|
|
|
|
|
$logs->roll_send_logs; |
1720
|
|
|
|
|
|
|
|
1721
|
|
|
|
|
|
|
Roll the qmail-send multilog logs. Update the maillogs counter. |
1722
|
|
|
|
|
|
|
|
1723
|
|
|
|
|
|
|
|
1724
|
|
|
|
|
|
|
=item send_count |
1725
|
|
|
|
|
|
|
|
1726
|
|
|
|
|
|
|
$logs->send_count; |
1727
|
|
|
|
|
|
|
|
1728
|
|
|
|
|
|
|
Count the number of messages we deliver, and a whole mess of stats from qmail-send. |
1729
|
|
|
|
|
|
|
|
1730
|
|
|
|
|
|
|
|
1731
|
|
|
|
|
|
|
=item smtp_auth_count |
1732
|
|
|
|
|
|
|
|
1733
|
|
|
|
|
|
|
$logs->smtp_auth_count; |
1734
|
|
|
|
|
|
|
|
1735
|
|
|
|
|
|
|
Count the number of times users authenticate via SMTP-AUTH to our qmail-smtpd daemon. |
1736
|
|
|
|
|
|
|
|
1737
|
|
|
|
|
|
|
|
1738
|
|
|
|
|
|
|
=item spama_count |
1739
|
|
|
|
|
|
|
|
1740
|
|
|
|
|
|
|
$logs->spama_count; |
1741
|
|
|
|
|
|
|
|
1742
|
|
|
|
|
|
|
Count statistics logged by SpamAssassin. |
1743
|
|
|
|
|
|
|
|
1744
|
|
|
|
|
|
|
|
1745
|
|
|
|
|
|
|
=item syslog_locate |
1746
|
|
|
|
|
|
|
|
1747
|
|
|
|
|
|
|
$logs->syslog_locate; |
1748
|
|
|
|
|
|
|
|
1749
|
|
|
|
|
|
|
Determine where syslog.mail is logged to. Right now we just test based on the OS you're running on and assume you've left it in the default location. This is easy to expand later. |
1750
|
|
|
|
|
|
|
|
1751
|
|
|
|
|
|
|
=cut |
1752
|
|
|
|
|
|
|
|
1753
|
|
|
|
|
|
|
=item webmail_count |
1754
|
|
|
|
|
|
|
|
1755
|
|
|
|
|
|
|
$logs->webmail_count; |
1756
|
|
|
|
|
|
|
|
1757
|
|
|
|
|
|
|
Count the number of webmail authentications. |
1758
|
|
|
|
|
|
|
|
1759
|
|
|
|
|
|
|
=back |
1760
|
|
|
|
|
|
|
|
1761
|
|
|
|
|
|
|
=head1 AUTHOR |
1762
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
Matt Simerson <matt@tnpi.net> |
1764
|
|
|
|
|
|
|
|
1765
|
|
|
|
|
|
|
|
1766
|
|
|
|
|
|
|
=head1 BUGS |
1767
|
|
|
|
|
|
|
|
1768
|
|
|
|
|
|
|
None known. Report any to author. |
1769
|
|
|
|
|
|
|
Patches welcome. |
1770
|
|
|
|
|
|
|
|
1771
|
|
|
|
|
|
|
|
1772
|
|
|
|
|
|
|
=head1 SEE ALSO |
1773
|
|
|
|
|
|
|
|
1774
|
|
|
|
|
|
|
The following are relevant man/perldoc pages: |
1775
|
|
|
|
|
|
|
|
1776
|
|
|
|
|
|
|
maillogs |
1777
|
|
|
|
|
|
|
Mail::Toaster |
1778
|
|
|
|
|
|
|
toaster.conf |
1779
|
|
|
|
|
|
|
|
1780
|
|
|
|
|
|
|
http://mail-toaster.org/ |
1781
|
|
|
|
|
|
|
|
1782
|
|
|
|
|
|
|
|
1783
|
|
|
|
|
|
|
=head1 COPYRIGHT |
1784
|
|
|
|
|
|
|
|
1785
|
|
|
|
|
|
|
Copyright (c) 2004-2008, The Network People, Inc. All rights reserved. |
1786
|
|
|
|
|
|
|
|
1787
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
1788
|
|
|
|
|
|
|
|
1789
|
|
|
|
|
|
|
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
1790
|
|
|
|
|
|
|
|
1791
|
|
|
|
|
|
|
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
1792
|
|
|
|
|
|
|
|
1793
|
|
|
|
|
|
|
Neither the name of the The Network People, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. |
1794
|
|
|
|
|
|
|
|
1795
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
1796
|
|
|
|
|
|
|
|
1797
|
|
|
|
|
|
|
=cut |