mirror of
https://github.com/darold/sendmailanalyzer.git
synced 2026-05-15 06:05:52 -06:00
5454 lines
182 KiB
Perl
Executable file
5454 lines
182 KiB
Perl
Executable file
#!/usr/bin/env perl
|
||
#
|
||
# SendmailAnalyzer: maillog parser and statistics reports tool for Sendmail
|
||
# Copyright (C) 2002-2020 Gilles Darold
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#
|
||
use vars qw($VERSION $AUTHOR $COPYRIGHT);
|
||
|
||
use strict;
|
||
no strict qw/refs/;
|
||
|
||
use CGI;
|
||
use Benchmark;
|
||
use Getopt::Long;
|
||
use POSIX qw / strftime :sys_wait_h /;
|
||
use Time::Local 'timelocal_nocheck';
|
||
|
||
|
||
$VERSION = '9.4';
|
||
$AUTHOR = "Gilles Darold <gilles\@darold.net>";
|
||
$COPYRIGHT = "(c) 2002-2020 - Gilles Darold <gilles\@darold.net>";
|
||
|
||
# Configuration storage hash
|
||
my %CONFIG = ();
|
||
|
||
# Other configuration directives
|
||
my $CONFIG_FILE = "/usr/local/sendmailanalyzer/sendmailanalyzer.conf";
|
||
my $DEF_CONF = $CONFIG_FILE;
|
||
my $CACHE_DATE = '';
|
||
my $HOST = '';
|
||
my $HELP = '';
|
||
my $DAYCACHE = 0;
|
||
my $PID_FILE = 'sa_cache.pid';
|
||
|
||
# Die on kill -2, -3 or -15
|
||
$SIG{'INT'} = $SIG{'QUIT'} = $SIG{'TERM'} = 'terminate';
|
||
|
||
our %ANTISPAM_NAME = (
|
||
'spamdmilter' => 'Spamd-Milter',
|
||
'jchkmail' => 'J-ChkMail',
|
||
'dnsbl' => 'RBL Check',
|
||
'spamassassin' => 'SpamAssassin',
|
||
'amavis' => 'Amavis',
|
||
'mimedefang' => 'MIMEDefang',
|
||
'dnsblmilter' => 'DNSBL-Milter',
|
||
'spamd' => 'Spamd',
|
||
'policydweight' => 'Policyd-weight',
|
||
);
|
||
|
||
# Collect command line arguments
|
||
GetOptions (
|
||
'config|c=s' => \$CONFIG_FILE,
|
||
'date|d=s' => \$CACHE_DATE,
|
||
'syslog|s=s' => \$HOST,
|
||
'help|h' => \$HELP,
|
||
'actual-day-only|a' => \$DAYCACHE,
|
||
);
|
||
|
||
&usage() if ($HELP);
|
||
if ($CACHE_DATE && ($CACHE_DATE !~ /^\d{4}\/\d{2}$/)) {
|
||
&usage();
|
||
}
|
||
|
||
sub usage
|
||
{
|
||
print "Usage: sa_cache [-s hostname] [-c conf_file] [-d yyyy/mm]\n\n";
|
||
print "This script generate cache statistics for past months and year until now.\n";
|
||
print "Using the --actual-day-only will compute statstics for the current day only\n";
|
||
print " -c | --config file => Path to sendmailanalyzer configuration file.\n";
|
||
print " Default: $CONFIG_FILE\n";
|
||
print " -d | --date \"yyyy/mm\" => year/month cache to proceed. Default is all month/year.\n";
|
||
print " -h | --help => Show this message.\n";
|
||
print " -s | --syslog hostname => syslog name of the host to proceed. Default all.\n\n";
|
||
print " -a | --actual-day-only => Proceed only the current day, this option replace the old\n";
|
||
print " and obsolete day_cache script. You still have to run it often like each five minutes.\n\n";
|
||
exit 0;
|
||
|
||
}
|
||
|
||
# Global variable to store temporary parsed data
|
||
my $t0 = new Benchmark;
|
||
|
||
# Read configuration file
|
||
&read_config($CONFIG_FILE);
|
||
|
||
# Check if output dir exist
|
||
if (!-d $CONFIG{OUT_DIR}) {
|
||
die "FATAL: Output directory $CONFIG{OUT_DIR} should exists !\n";
|
||
}
|
||
|
||
my $cgi = new CGI;
|
||
|
||
# Add global caching
|
||
push(@{$CONFIG{DOMAIN_REPORT}}, '');
|
||
|
||
# Check if we have a SQL-host configured for virtual domains
|
||
if ( $CONFIG{VIRTUAL_DOMAIN_DB} && $CONFIG{VIRTUAL_DOMAIN_DB_QUERY} ) {
|
||
eval("use DBI;");
|
||
my $dbh = DBI->connect(
|
||
$CONFIG{VIRTUAL_DOMAIN_DB},
|
||
$CONFIG{VIRTUAL_DOMAIN_DB_USER},
|
||
$CONFIG{VIRTUAL_DOMAIN_DB_PASS},
|
||
) or die "Couldn't connect to database: " . DBI->errstr;
|
||
# Get all virtual domains and stores them in $CONFIG{LOCAL_DOMAIN} array
|
||
my $sth = $dbh->prepare( $CONFIG{VIRTUAL_DOMAIN_DB_QUERY} );
|
||
$sth->execute();
|
||
while (my @row = $sth->fetchrow_array) {
|
||
push(@{ $CONFIG{LOCAL_DOMAIN} }, $row[0]);
|
||
}
|
||
$sth->finish();
|
||
$dbh->disconnect() if (defined $dbh);
|
||
}
|
||
|
||
my $UNIQID = 0;
|
||
|
||
if (-e "$CONFIG{PID_DIR}/$PID_FILE") {
|
||
logerror("pid file $CONFIG{PID_DIR}/$PID_FILE exists, maybe sa_cache is already running.\n");
|
||
exit 0;
|
||
} else {
|
||
if (not open(OUT, ">$CONFIG{PID_DIR}/$PID_FILE")) {
|
||
logerror("Can't create pid file $CONFIG{PID_DIR}/$PID_FILE\n");
|
||
exit 0;
|
||
} else {
|
||
print OUT "$$";
|
||
close(OUT);
|
||
}
|
||
}
|
||
|
||
# Try to find syslog hosts
|
||
if (not opendir(DIR, "$CONFIG{OUT_DIR}/")) {
|
||
logerror("Can't open directory $CONFIG{OUT_DIR}: $!\n");
|
||
return;
|
||
}
|
||
my @sysloghost = grep { !/^(data|lang|[\.]+)$/ && -d "$CONFIG{OUT_DIR}/$_" } readdir(DIR);
|
||
closedir(DIR);
|
||
|
||
foreach my $h (@sysloghost) {
|
||
next if ($HOST && ($h ne $HOST));
|
||
$UNIQID = 0;
|
||
# Dump daily statistics
|
||
&cache_stat($cgi, $h);
|
||
}
|
||
|
||
# Show total run time
|
||
my $t1 = new Benchmark;
|
||
my $td = timediff($t1, $t0);
|
||
print "Cache generation took:",timestr($td),"\n";
|
||
|
||
unlink("$CONFIG{PID_DIR}/$PID_FILE");
|
||
|
||
exit 0;
|
||
|
||
#-------------------------------- ROUTINES ------------------------------------
|
||
|
||
####
|
||
# Routine used to log sendmailanalyzer errors or send emails alert if requested
|
||
####
|
||
sub logerror
|
||
{
|
||
my $str = shift;
|
||
|
||
print STDERR "ERROR: $str\n";
|
||
|
||
}
|
||
|
||
|
||
####
|
||
# Read configuration file
|
||
####
|
||
sub read_config
|
||
{
|
||
my $file = shift;
|
||
|
||
if (!-e $file) {
|
||
$file = '/etc/sendmailanalyzer.conf';
|
||
}
|
||
if (!-e $file) {
|
||
die "FATAL: Configuration file $file doesn't exists !\n";
|
||
} else {
|
||
if (not open(IN, $file)) {
|
||
die "FATAL: Can't read configuration file $file: $!\n";
|
||
} else {
|
||
while (<IN>) {
|
||
chomp;
|
||
s/#.*//;
|
||
s/^[\s\t]+//;
|
||
s/[\s\t]$//;
|
||
if ($_ ne '') {
|
||
my ($var, $val) = split(/[\s\t]+/, $_, 2);
|
||
if ($var =~ /DOMAIN_USER/i) {
|
||
my ($usr, @doms) = split(/[\t,;\s]+/, $val);
|
||
push(@{$CONFIG{DOMAIN_USER}{$usr}}, @doms);
|
||
} elsif ($var =~ /DOMAIN_HOST_REPORT/i) {
|
||
my ($hst, @doms) = split(/[\t,;\s]/, $val);
|
||
push(@{$CONFIG{DOMAIN_HOST_REPORT}{$hst}}, @doms);
|
||
} elsif ($var =~ /DOMAIN_REPORT/i) {
|
||
push(@{$CONFIG{DOMAIN_REPORT}}, split(/[\t,;\s]/, $val));
|
||
} elsif ($var =~ /LOCAL_DOMAIN/i) {
|
||
if (-e $val) {
|
||
if (open(my $in, '<', $val)) {
|
||
@{$CONFIG{LOCAL_DOMAIN}} = <$in>;
|
||
chomp(@{$CONFIG{LOCAL_DOMAIN}});
|
||
close($in);
|
||
} else {
|
||
&logerror("LOCAL_DOMAIN file $val can not be read, $!");
|
||
}
|
||
} else {
|
||
push(@{$CONFIG{LOCAL_DOMAIN}}, split(/[\t,;\s]/, $val));
|
||
}
|
||
} elsif ($var =~ /LOCAL_HOST_DOMAIN/i) {
|
||
my ($hst, @doms) = split(/[\t,;\s]/, $val);
|
||
if ($#doms == 0 && -e $doms[0]) {
|
||
if (open(my $in, '<', $doms[0])) {
|
||
@{$CONFIG{LOCAL_HOST_DOMAIN}{$hst}} = <$in>;
|
||
chomp(@{$CONFIG{LOCAL_HOST_DOMAIN}{$hst}});
|
||
close($in);
|
||
} else {
|
||
&logerror("LOCAL_DOMAIN file $doms[0] can not be read, $!");
|
||
}
|
||
} else {
|
||
push(@{$CONFIG{LOCAL_HOST_DOMAIN}{$hst}}, @doms);
|
||
}
|
||
} else {
|
||
$CONFIG{$var} = $val if (!defined $CONFIG{$var} && ($val ne ''));
|
||
}
|
||
}
|
||
}
|
||
close(IN);
|
||
}
|
||
}
|
||
# Set default values
|
||
$CONFIG{OUT_DIR} ||= '/var/www/htdocs/sendmailanalyzer';
|
||
$CONFIG{TOP} ||= 25;
|
||
$CONFIG{MAIL_HUB} ||= '';
|
||
$CONFIG{MAIL_GW} ||= '';
|
||
$CONFIG{PID_DIR} ||= $CONFIG{PID_FILE};
|
||
$CONFIG{LANG} ||= 'lang/en_US';
|
||
if (!exists $CONFIG{SPAM_DETAIL}) {
|
||
$CONFIG{SPAM_DETAIL} = 1;
|
||
}
|
||
$CONFIG{WEEKLY_FREE_SPACE} ||= 0;
|
||
|
||
}
|
||
|
||
|
||
our %topsender = ();
|
||
our %toprcpt = ();
|
||
our %topspam = ();
|
||
our %topvirus = ();
|
||
our %topdsn = ();
|
||
our %topreject = ();
|
||
our %toperr = ();
|
||
our %topmaxrcpt = ();
|
||
our %topmaxsize = ();
|
||
our %delivery = ();
|
||
our %messaging = ();
|
||
our %spam = ();
|
||
our %dsn = ();
|
||
our %virus = ();
|
||
our %reject = ();
|
||
our %err = ();
|
||
our %GLOBAL_STATUS = ();
|
||
our %topspamdetail = ();
|
||
our %auth = ();
|
||
our %topauth = ();
|
||
our %postgrey = ();
|
||
our %toppostgrey = ();
|
||
our %starttls = ();
|
||
our %spf_dkim = ();
|
||
|
||
|
||
####
|
||
# Cache statistic for the given date
|
||
####
|
||
sub cache_stat
|
||
{
|
||
my ($q, $hostname) = @_;
|
||
|
||
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
||
$mon++;
|
||
$year += 1900;
|
||
|
||
|
||
my $currentday = $year . sprintf("%02d",$mon) . sprintf("%02d",$mday);
|
||
my $currentmonth = $year . sprintf("%02d",$mon);
|
||
|
||
# Lookup years directories for a given host
|
||
opendir(DIR, "$CONFIG{OUT_DIR}/$hostname") || die "can't opendir $CONFIG{OUT_DIR}/$hostname: $!";
|
||
my @ydirs = grep { /^\d+$/ && -d "$CONFIG{OUT_DIR}/$hostname/$_" } readdir(DIR);
|
||
closedir DIR;
|
||
|
||
foreach my $y (sort {$a <=> $b } @ydirs) {
|
||
next if ($DAYCACHE && ($y ne $year));
|
||
print "Checking directory: $CONFIG{OUT_DIR}/$hostname/$y\n" if ($CONFIG{DEBUG});
|
||
# Lookup months directories for the current host/year
|
||
opendir(DIR, "$CONFIG{OUT_DIR}/$hostname/$y") || die "can't opendir $CONFIG{OUT_DIR}/$hostname/$y: $!";
|
||
my @mdirs = grep { /^\d+$/ && -d "$CONFIG{OUT_DIR}/$hostname/$y/$_" } readdir(DIR);
|
||
closedir DIR;
|
||
foreach my $m (sort {$a <=> $b } @mdirs) {
|
||
next if ($DAYCACHE && ("$y$m" ne $currentmonth));
|
||
next if ($CACHE_DATE && ($CACHE_DATE ne "$y/$m"));
|
||
print "\t$CONFIG{OUT_DIR}/$hostname/$y/$m\n" if ($CONFIG{DEBUG});
|
||
# Lookup days directories for the current host/year/month
|
||
opendir(DIR, "$CONFIG{OUT_DIR}/$hostname/$y/$m") || die "can't opendir $CONFIG{OUT_DIR}/$hostname/$y/$m: $!";
|
||
my @ddirs = grep { /^\d+$/ && -d "$CONFIG{OUT_DIR}/$hostname/$y/$m/$_" } readdir(DIR);
|
||
closedir DIR;
|
||
foreach my $d (sort {$a <=> $b } @ddirs) {
|
||
last if (!$DAYCACHE && ("$y$m$d" eq "$currentday"));
|
||
next if ($DAYCACHE && ("$y$m$d" ne "$currentday"));
|
||
print "\t\t$CONFIG{OUT_DIR}/$hostname/$y/$m/$d\n" if ($CONFIG{DEBUG});
|
||
&do_hour_cache($hostname,$y,$m,$d,$currentday, $hour);
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_REPORT}}) {
|
||
&do_day_cache($hostname,$DOMAIN,$y,$m,$d,$currentday);
|
||
}
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_HOST_REPORT}{$hostname}}) {
|
||
&do_day_cache($hostname,$DOMAIN,$y,$m,$d,$currentday);
|
||
}
|
||
}
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_REPORT}}) {
|
||
&do_month_cache($hostname,$DOMAIN,$y,$m,$currentmonth);
|
||
}
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_HOST_REPORT}{$hostname}}) {
|
||
&do_month_cache($hostname,$DOMAIN,$y,$m,$currentmonth);
|
||
}
|
||
}
|
||
# Build years cache
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_REPORT}}) {
|
||
&do_year_cache($hostname,$DOMAIN,$y,$year);
|
||
}
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_HOST_REPORT}{$hostname}}) {
|
||
&do_year_cache($hostname,$DOMAIN,$y,$year);
|
||
}
|
||
# Build weeks cache
|
||
my $curweek = POSIX::strftime("%W", gmtime time);
|
||
foreach my $week ("00" .. "53") {
|
||
last if ( ($y eq $year) && ($week > $curweek));
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_REPORT}}) {
|
||
&do_week_cache($hostname,$DOMAIN,$y,$year,$week,$curweek);
|
||
}
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_HOST_REPORT}{$hostname}}) {
|
||
&do_week_cache($hostname,$DOMAIN,$y,$year,$week,$curweek);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
####
|
||
# Get week number
|
||
####
|
||
sub get_week_number
|
||
{
|
||
my ($year, $month, $day) = @_;
|
||
|
||
# Check if the date is valide first
|
||
my $datefmt = POSIX::strftime("%F", 1, 1, 1, $day, $month - 1, $year - 1900);
|
||
if ($datefmt ne "$year-$month-$day") {
|
||
return -1;
|
||
}
|
||
my $weekNumber = POSIX::strftime("%W", 1, 1, 1, $day, $month - 1, $year - 1900);
|
||
|
||
return $weekNumber;
|
||
}
|
||
|
||
####
|
||
# Hour cache statistics
|
||
####
|
||
sub do_hour_cache
|
||
{
|
||
my ($hostname, $year, $month, $day, $curday, $curhour) = @_;
|
||
|
||
|
||
# Do not proceed the current day this is the work of day_cache option
|
||
return if (!$DAYCACHE && ("$year$month$day" eq "$curday"));
|
||
|
||
my @data = ();
|
||
|
||
# Remove the file flag and all cache files generated by day_cache option
|
||
if (!$DAYCACHE) {
|
||
if (-e "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/flag") {
|
||
unlink("$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/flag");
|
||
`rm -f $CONFIG{OUT_DIR}/$hostname/$year/$month/$day/*cache.pm*`;
|
||
}
|
||
return if (-e "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/cache.pm");
|
||
} else {
|
||
# remove cache file for the current hour and previous one for the current day
|
||
`rm -f $CONFIG{OUT_DIR}/$hostname/$year/$month/$day/${curhour}cache.pm*`;
|
||
$curhour--;
|
||
if ($curhour >= 0) {
|
||
$curhour = sprintf("%02d",$curhour);
|
||
`rm -f $CONFIG{OUT_DIR}/$hostname/$year/$month/$day/${curhour}cache.pm*`;
|
||
}
|
||
`rm -f $CONFIG{OUT_DIR}/$hostname/$year/$month/$day/cache.pm*`;
|
||
}
|
||
print "Reading hourly statistics from $CONFIG{OUT_DIR}/$hostname/$year/$month/$day/\n" if ($CONFIG{DEBUG});
|
||
my $begin = "00";
|
||
my $end = "23";
|
||
if ($DAYCACHE) {
|
||
$end = sprintf("%02d", $curhour+1);
|
||
}
|
||
|
||
foreach my $hour ("$begin" .. "$end") {
|
||
|
||
next if (-e "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/${hour}cache.pm");
|
||
my %localstat = ();
|
||
my %localglobstat = ();
|
||
my %sourceid = ();
|
||
|
||
my $file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/dsn.dat";
|
||
if (open(IN, $file)) {
|
||
my @done = ();
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:SourceId:Status
|
||
@data = split(/:/, $l, 4);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$localstat{$data[1]}{idx_dsn} = "$1";
|
||
$localstat{$data[1]}{hour} = $data[0] if (!exists $localstat{$data[1]}{hour});
|
||
$localstat{$data[1]}{srcid} = $data[2];
|
||
$localstat{$data[1]}{dsnstatus} = $data[3];
|
||
$sourceid{$data[2]} = $data[1];
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/senders.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:Sender:Size:Nrcpts:Relay:Subject
|
||
@data = split(/:/, $l);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$data[5] = &clean_relay($data[5]);
|
||
$localstat{$data[1]}{idx_sender} = "$1";
|
||
$localstat{$data[1]}{hour} = $data[0];
|
||
$data[2] ||= '<>';
|
||
$localstat{$data[1]}{sender} = $data[2];
|
||
$localstat{$data[1]}{size} = $data[3];
|
||
$localstat{$data[1]}{nrcpt} = $data[4];
|
||
$localstat{$data[1]}{sender_relay} = $data[5];
|
||
if (exists $sourceid{$data[1]}) {
|
||
$localstat{TOPDSN}{$sourceid{$data[1]}}{sender} = $data[2];
|
||
$localstat{TOPDSN}{$sourceid{$data[1]}}{sender_relay} = $data[5];
|
||
}
|
||
for (my $i = 6; $i <= $#data; $i++) {
|
||
$localstat{$data[1]}{subject} .= ($i > 6) ? ':' : '';
|
||
$localstat{$data[1]}{subject} .= $data[$i];
|
||
}
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/recipient.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:recipient:Relay:Status
|
||
@data = split(/:/, $l);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$data[3] = &clean_relay($data[3]);
|
||
$localstat{$data[1]}{idx_rcpt} = "$1";
|
||
push(@{$localstat{$data[1]}{rcpt}}, $data[2]);
|
||
push(@{$localstat{$data[1]}{hour}}, $data[0]);
|
||
push(@{$localstat{$data[1]}{rcpt_relay}}, $data[3]);
|
||
push(@{$localstat{$data[1]}{status}}, $data[4]);
|
||
if (exists $sourceid{$data[1]} && ($data[4] ne 'Sent')) {
|
||
push(@{$localstat{TOPDSN}{$sourceid{$data[1]}}{rcpt}}, $data[2]);
|
||
}
|
||
}
|
||
close(IN);
|
||
}
|
||
%sourceid = ();
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/rejected.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:Rule:Relay:Arg1:Status
|
||
@data = split(/:/, $l);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$data[3] = &clean_relay($data[3]);
|
||
$localstat{$data[1]}{idx_reject} = "$1";
|
||
$localstat{$data[1]}{rule} = $data[2];
|
||
$localstat{$data[1]}{hour} = $data[0] if (!exists $localstat{$data[1]}{hour});
|
||
$localstat{$data[1]}{sender_relay} = $data[3] if (!$localstat{$data[1]}{sender_relay});
|
||
if ($#data > 4) {
|
||
if ($data[2] eq 'check_relay') {
|
||
$localstat{$data[1]}{sender_relay} = $data[4];
|
||
} elsif ($data[2] eq 'check_rcpt') {
|
||
push(@{$localstat{$data[1]}{chck_rcpt}}, $data[4]);
|
||
} elsif ($data[5] eq 'postscreen reject' && $data[4] ne '') {
|
||
$data[5] .= " (score: $data[4])";
|
||
} else {
|
||
# $data[2] eq 'check_mail' or POSTFIX
|
||
$localstat{$data[1]}{sender} = $data[4];
|
||
}
|
||
push(@{$localstat{$data[1]}{chck_status}}, $data[5]);
|
||
} else {
|
||
push(@{$localstat{$data[1]}{chck_status}}, $data[4]);
|
||
}
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/spam.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:From:To:Spam
|
||
@data = split(/:/, $l, 5);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$localstat{$data[1]}{idx_spam} = "$1";
|
||
$localstat{$data[1]}{hour} = $data[0] if (!exists $localstat{$data[1]}{hour});
|
||
$localstat{$data[1]}{sender} = $data[2] if (!exists $localstat{$data[1]}{sender});
|
||
foreach my $a (split(/,/, $data[3])) {
|
||
if (!grep(/^$a$/i, @{$localstat{$data[1]}{rcpt}})) {
|
||
push(@{$localstat{$data[1]}{rcpt}}, $a);
|
||
}
|
||
}
|
||
$localstat{$data[1]}{spam} = $data[4];
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/virus.dat";
|
||
if (open(IN, $file)) {
|
||
my @done = ();
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:file:virus
|
||
@data = split(/:/, $l, 4);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$localstat{$data[1]}{idx_virus} = "$1";
|
||
$localstat{$data[1]}{hour} = $data[0] if (!exists $localstat{$data[1]}{hour});
|
||
$localstat{$data[1]}{file} = $data[2];
|
||
$localstat{$data[1]}{virus} = $data[3];
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/syserr.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:Message
|
||
@data = split(/:/, $l);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$localstat{$data[1]}{idx_syserr} = "$1";
|
||
$localstat{$data[1]}{hour} = $data[0] if (!exists $localstat{$data[1]}{hour});
|
||
shift(@data);
|
||
my $id = shift(@data);
|
||
$localstat{$id}{error} = join(':', @data);
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/other.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Message
|
||
@data = split(/:/, $l);
|
||
my $hms = shift(@data);
|
||
$hms =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
next if (&clear_postfix(join(':', @data)));
|
||
$localstat{$UNIQID}{idx_other} = "$1";
|
||
$localstat{$UNIQID}{hour} = $hms;
|
||
$localstat{$UNIQID}{error} = join(':', @data);
|
||
$UNIQID++;
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/starttls.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:FAIL=count;NO=count,OK=count
|
||
@data = split(/:/, $l, 2);
|
||
my $hms = shift(@data);
|
||
$hms =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
my %verify = split(/[=;]/, $data[0]);
|
||
foreach my $v (keys %verify) {
|
||
$localstat{STARTTLS}{$v} += $verify{$v};
|
||
}
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/postgrey.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:Relay:From:To:Action:Reason
|
||
@data = split(/:/, $l);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$data[2] = &clean_relay($data[2]);
|
||
$localstat{$data[1]}{idx_postgrey} = "$1";
|
||
$localstat{$data[1]}{hour} = $data[0] if (!exists $localstat{$data[1]}{hour});
|
||
$localstat{$data[1]}{sender_relay} = $data[2];
|
||
$localstat{$data[1]}{sender} = $data[3];
|
||
push(@{$localstat{$data[1]}{rcpt}}, $data[4]);
|
||
$localstat{$data[1]}{action} = $data[5];
|
||
$localstat{$data[1]}{reason} = $data[6];
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/spf_dkim.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:Type:Rule:Domain:Status
|
||
@data = split(/:/, $l);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
if ($data[2] eq 'spf') {
|
||
$localstat{$data[1]}{$data[2]}{$data[3]}{hour} = $data[0] if (!exists $localstat{$data[1]}{$data[2]}{$data[3]}{hour});
|
||
#$localstat{$data[1]}{$data[2]}{$data[3]}{domain}{$data[4]}++;
|
||
$localstat{$data[1]}{$data[2]}{$data[3]}{status}{$data[5]}++;
|
||
} elsif ($data[2] eq 'dkim') {
|
||
$localstat{$data[1]}{$data[2]}{hour} = $data[0] if (!exists $localstat{$data[1]}{$data[2]}{hour});
|
||
#$localstat{$data[1]}{$data[2]}{domain}{$data[4]}++;
|
||
$localstat{$data[1]}{$data[2]}{status}{$data[5]}++;
|
||
}
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
for my $typ (sort keys %ANTISPAM_NAME) {
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/$typ.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:type:score:cache:autolearn:spam
|
||
@data = split(/:/, $l, 7);
|
||
$data[0] =~ /^(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$localstat{$data[1]}{idx_spamd} = "$1";
|
||
$localstat{$data[1]}{hour} = $data[0] if (!exists $localstat{$data[1]}{hour});
|
||
$localstat{$data[1]}{spamtype} = $data[2];
|
||
$localstat{$data[1]}{score} = $data[3];
|
||
$localstat{$data[1]}{cache} = $data[4];
|
||
$localstat{$data[1]}{autolearn} = $data[5];
|
||
$localstat{$data[1]}{spamdetail} = $data[6];
|
||
}
|
||
close(IN);
|
||
}
|
||
}
|
||
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/auth.dat";
|
||
if (open(IN, $file)) {
|
||
while (my $l = <IN>) {
|
||
chomp($l);
|
||
# Format: Hour:Id:Relay:Mech:Type
|
||
@data = split(/:/, $l);
|
||
$data[0] =~ /^(\d{2})(\d{2})/;
|
||
next if ($1 ne $hour);
|
||
$data[2] = &clean_relay($data[2]);
|
||
push(@{$localstat{$data[1]}{idx_auth}}, "$1");
|
||
push(@{$localstat{$data[1]}{auth_hour}}, $data[0]);
|
||
push(@{$localstat{$data[1]}{auth_relay}}, $data[2]);
|
||
push(@{$localstat{$data[1]}{auth_mech}}, $data[3]);
|
||
push(@{$localstat{$data[1]}{auth_type}}, $data[4]);
|
||
}
|
||
close(IN);
|
||
}
|
||
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_REPORT}}) {
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/${hour}cache.pm\U$DOMAIN\E";
|
||
print "Writing cache file: $file\n" if ($CONFIG{DEBUG});
|
||
&clean_globals();
|
||
&compute_top_stats($file, $DOMAIN, \%localstat);
|
||
&compute_global_stats($file, $DOMAIN, \%localstat, '00', '60', 'Minutes of the hour', $hostname);
|
||
}
|
||
foreach my $DOMAIN (@{$CONFIG{DOMAIN_HOST_REPORT}{$hostname}}) {
|
||
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/${hour}cache.pm\U$DOMAIN\E";
|
||
print "Writing cache file: $file\n" if ($CONFIG{DEBUG});
|
||
&clean_globals();
|
||
&compute_top_stats($file, $DOMAIN, \%localstat);
|
||
&compute_global_stats($file, $DOMAIN, \%localstat, '00', '60', 'Minutes of the hour', $hostname);
|
||
}
|
||
}
|
||
}
|
||
|
||
sub clean_globals
|
||
{
|
||
%topsender = ();
|
||
%toprcpt = ();
|
||
%topspam = ();
|
||
%topvirus = ();
|
||
%topdsn = ();
|
||
%topreject = ();
|
||
%toperr = ();
|
||
%topmaxrcpt = ();
|
||
%topmaxsize = ();
|
||
%topspamdetail = ();
|
||
%topauth = ();
|
||
%toppostgrey = ();
|
||
|
||
%delivery = ();
|
||
%messaging = ();
|
||
%spam = ();
|
||
%virus = ();
|
||
%reject = ();
|
||
%err = ();
|
||
%dsn = ();
|
||
%auth = ();
|
||
%postgrey = ();
|
||
%starttls = ();
|
||
%GLOBAL_STATUS = ();
|
||
|
||
}
|
||
|
||
sub compute_top_stats
|
||
{
|
||
|
||
my ($file, $DOMAIN, $STATS) = @_;
|
||
|
||
if (open(OUT, ">$file")) {
|
||
foreach my $id (keys %$STATS) {
|
||
next if (($id eq 'TOPDSN') || ($id eq 'STARTTLS'));
|
||
next if ($DOMAIN && ($STATS->{$id}{sender} !~ /$DOMAIN/) && !grep(/$DOMAIN/, @{$STATS->{$id}{rcpt}}));
|
||
if ($STATS->{$id}{nrcpt} > $CONFIG{MAX_RCPT}) {
|
||
push(@{$topmaxrcpt{$STATS->{$id}{nrcpt}}{sender}}, $STATS->{$id}{sender});
|
||
push(@{$topmaxrcpt{$STATS->{$id}{nrcpt}}{sa_id}}, $id);
|
||
}
|
||
if ($STATS->{$id}{sender} && grep(/Sent/, @{$STATS->{$id}{status}})) {
|
||
my $sender = $STATS->{$id}{sender};
|
||
$topsender{email}{$sender}++;
|
||
my $dom = $sender || '';
|
||
$dom =~ s/^.*\@//;
|
||
$topsender{domain}{$dom}++;
|
||
$topsender{relay}{$STATS->{$id}{sender_relay}}++;
|
||
}
|
||
|
||
if ($STATS->{$id}{size} && $STATS->{$id}{nrcpt}) {
|
||
if ($STATS->{$id}{size} > $CONFIG{MAX_SIZE}) {
|
||
$topmaxsize{$id}{sender} = $STATS->{$id}{sender};
|
||
$topmaxsize{$id}{size} = $STATS->{$id}{size};
|
||
$topmaxsize{$id}{nrcpt} = $STATS->{$id}{nrcpt};
|
||
}
|
||
}
|
||
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{status}}; $i++) {
|
||
if ($STATS->{$id}{status}[$i] eq 'Sent') {
|
||
$toprcpt{email}{$STATS->{$id}{rcpt}[$i]}++;
|
||
my $dom = $STATS->{$id}{rcpt}[$i] || '<>';
|
||
$dom =~ s/^.*\@//;
|
||
$toprcpt{domain}{$dom}++;
|
||
$toprcpt{relay}{$STATS->{$id}{rcpt_relay}[$i]}++;
|
||
}
|
||
}
|
||
if (exists $STATS->{$id}{dsnstatus}) {
|
||
$topdsn{sender}{$STATS->{TOPDSN}{$id}{sender}}++;
|
||
$topdsn{relay}{$STATS->{TOPDSN}{$id}{sender_relay}}++;
|
||
$topdsn{dsnstatus}->{$STATS->{$id}{dsnstatus}}++;
|
||
for (my $i = 0; $i <= $#{$STATS->{TOPDSN}{$id}{rcpt}}; $i++) {
|
||
$topdsn{rcpt}{$STATS->{TOPDSN}{$id}{rcpt}[$i]}++;
|
||
}
|
||
|
||
}
|
||
if (exists $STATS->{$id}{spam}) {
|
||
$topspam{sender}{$STATS->{$id}{sender}}++;
|
||
my $dom = $STATS->{$id}{sender} || '<>';
|
||
$dom =~ s/^.*\@//;
|
||
$topspam{domain}{$dom}++;
|
||
$topspam{sender_relay}{$STATS->{$id}{sender_relay}}++;
|
||
$topspam{rule}{$STATS->{$id}{spam}}++;
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{rcpt}}; $i++) {
|
||
$topspam{rcpt}{$STATS->{$id}{rcpt}[$i]}++;
|
||
}
|
||
}
|
||
if (exists $STATS->{$id}{virus}) {
|
||
$topvirus{sender}{$STATS->{$id}{sender}}++;
|
||
$topvirus{relay}{$STATS->{$id}{sender_relay}}++;
|
||
$topvirus{file}{$STATS->{$id}{file}}++;
|
||
$topvirus{virus}{$STATS->{$id}{virus}}++;
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{status}}; $i++) {
|
||
$topvirus{rcpt}{$STATS->{$id}{rcpt}[$i]}++;
|
||
}
|
||
}
|
||
if (exists $STATS->{$id}{rule}) {
|
||
$topreject{sender}{$STATS->{$id}{sender}}++;
|
||
my $dom = $STATS->{$id}{sender} || '<>';
|
||
$dom =~ s/^.*\@//;
|
||
$topreject{domain}{$dom}++;
|
||
$topreject{relay}{$STATS->{$id}{sender_relay}}++;
|
||
$topreject{rule}{$STATS->{$id}{rule}}++;
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{chck_status}}; $i++) {
|
||
next if ($STATS->{$id}{chck_status}[$i] =~ /Queued/);
|
||
$topreject{chck_status}{$STATS->{$id}{chck_status}[$i]}++;
|
||
}
|
||
}
|
||
if (exists $STATS->{$id}{error}) {
|
||
$toperr{$STATS->{$id}{error}}++;
|
||
}
|
||
|
||
if (exists $STATS->{$id}{reason}) {
|
||
$toppostgrey{sender}{$STATS->{$id}{sender}}++;
|
||
$toppostgrey{sender_relay}{$STATS->{$id}{sender_relay}}++;
|
||
$STATS->{$id}{sender} =~ s/^.*\@//;
|
||
$STATS->{$id}{sender} ||= 'Unknown';
|
||
$toppostgrey{domain}{$STATS->{$id}{sender}}++;
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{rcpt}}; $i++) {
|
||
$toppostgrey{rcpt}{$STATS->{$id}{rcpt}[$i]}++;
|
||
}
|
||
$toppostgrey{reason}{$STATS->{$id}{reason}}++;
|
||
}
|
||
|
||
if (exists $STATS->{$id}{spamtype} && grep(/^$STATS->{$id}{spamtype}$/, keys %ANTISPAM_NAME)) {
|
||
$topspamdetail{$STATS->{$id}{spamtype}}{score}{$STATS->{$id}{score}}++ if ($STATS->{$id}{score});
|
||
$topspamdetail{$STATS->{$id}{spamtype}}{rule}{$STATS->{$id}{spamdetail}}++;
|
||
$topspamdetail{$STATS->{$id}{spamtype}}{cache}{$STATS->{$id}{cache}}++ if ($STATS->{$id}{cache});
|
||
$topspamdetail{$STATS->{$id}{spamtype}}{autolearn}{$STATS->{$id}{autolearn}}++ if ($STATS->{$id}{autolearn});
|
||
}
|
||
if (exists $STATS->{$id}{auth_relay}) {
|
||
$topauth{authid}{$id} += ($#{$STATS->{$id}{auth_relay}} + 1);
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{auth_relay}}; $i++) {
|
||
$topauth{relay}{$STATS->{$id}{auth_relay}[$i]}++;
|
||
$topauth{mech}{$STATS->{$id}{auth_mech}[$i]}++;
|
||
}
|
||
}
|
||
}
|
||
|
||
# Top SMTP Auth statistics
|
||
my $top = 0;
|
||
print OUT "\%::topauth = (\n";
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $topauth{relay}{$b} <=> $topauth{relay}{$a} } keys %{$topauth{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topauth{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topauth{relay};
|
||
$top = 0;
|
||
print OUT "'mech' => {";
|
||
foreach my $d (sort { $topauth{mech}{$b} <=> $topauth{mech}{$a} } keys %{$topauth{mech}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topauth{mech}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topauth{mech};
|
||
$top = 0;
|
||
print OUT "'authid' => {";
|
||
foreach my $d (sort { $topauth{authid}{$b} <=> $topauth{authid}{$a} } keys %{$topauth{authid}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topauth{authid}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%topauth = ();
|
||
|
||
# Top sender statistics
|
||
$top = 0;
|
||
print OUT "\%::topsender = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $topsender{domain}{$b} <=> $topsender{domain}{$a} } keys %{$topsender{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topsender{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topsender{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $topsender{relay}{$b} <=> $topsender{relay}{$a} } keys %{$topsender{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topsender{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topsender{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $topsender{email}{$b} <=> $topsender{email}{$a} } keys %{$topsender{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topsender{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%topsender = ();
|
||
|
||
# Top recipient statistics
|
||
$top = 0;
|
||
print OUT "\%::toprcpt = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $toprcpt{domain}{$b} <=> $toprcpt{domain}{$a} } keys %{$toprcpt{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$toprcpt{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $toprcpt{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $toprcpt{relay}{$b} <=> $toprcpt{relay}{$a} } keys %{$toprcpt{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$toprcpt{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $toprcpt{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $toprcpt{email}{$b} <=> $toprcpt{email}{$a} } keys %{$toprcpt{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$toprcpt{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%toprcpt = ();
|
||
|
||
# Top rejection statistics
|
||
$top = 0;
|
||
print OUT "\%::topreject = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $topreject{rule}{$b} <=> $topreject{rule}{$a} } keys %{$topreject{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $topreject{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topreject{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $topreject{domain}{$b} <=> $topreject{domain}{$a} } keys %{$topreject{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topreject{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topreject{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $topreject{relay}{$b} <=> $topreject{relay}{$a} } keys %{$topreject{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topreject{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topreject{relay};
|
||
$top = 0;
|
||
print OUT "'chck_status' => {";
|
||
foreach my $d (sort { $topreject{chck_status}{$b} <=> $topreject{chck_status}{$a} } keys %{$topreject{chck_status}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $topreject{chck_status}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topreject{chck_status};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $topreject{sender}{$b} <=> $topreject{sender}{$a} } keys %{$topreject{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topreject{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%topreject = ();
|
||
|
||
# Top virus statistics
|
||
$top = 0;
|
||
print OUT "\%::topvirus = (\n";
|
||
print OUT "'virus' => {";
|
||
foreach my $d (sort { $topvirus{virus}{$b} <=> $topvirus{virus}{$a} } keys %{$topvirus{virus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $topvirus{virus}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topvirus{virus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $topvirus{sender}{$b} <=> $topvirus{sender}{$a} } keys %{$topvirus{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topvirus{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topvirus{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $topvirus{relay}{$b} <=> $topvirus{relay}{$a} } keys %{$topvirus{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topvirus{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topvirus{relay};
|
||
$top = 0;
|
||
print OUT "'file' => {";
|
||
foreach my $d (sort { $topvirus{file}{$b} <=> $topvirus{file}{$a} } keys %{$topvirus{file}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $topvirus{file}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topvirus{file};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $topvirus{rcpt}{$b} <=> $topvirus{rcpt}{$a} } keys %{$topvirus{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topvirus{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%topvirus = ();
|
||
|
||
# Top dsn statistics
|
||
$top = 0;
|
||
print OUT "\%::topdsn = (\n";
|
||
print OUT "'dsnstatus' => {";
|
||
foreach my $d (sort { $topdsn{dsnstatus}{$b} <=> $topdsn{dsnstatus}{$a} } keys %{$topdsn{dsnstatus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $topdsn{dsnstatus}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topdsn{dsnstatus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $topdsn{sender}{$b} <=> $topdsn{sender}{$a} } keys %{$topdsn{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topdsn{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topdsn{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $topdsn{relay}{$b} <=> $topdsn{relay}{$a} } keys %{$topdsn{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topdsn{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topdsn{relay};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $topdsn{rcpt}{$b} <=> $topdsn{rcpt}{$a} } keys %{$topdsn{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topdsn{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $topdsn{rcpt};
|
||
$top = 0;
|
||
print OUT ");\n\n";
|
||
%topdsn = ();
|
||
|
||
print OUT "\%::topmaxrcpt = (\n";
|
||
foreach my $nb (sort { $b <=> $a } keys %topmaxrcpt) {
|
||
print OUT "'$nb' => { 'sender' => [(";
|
||
for (my $i = 0; $i <= $#{$topmaxrcpt{$nb}{sender}}; $i++) {
|
||
print OUT "'$topmaxrcpt{$nb}{sender}[$i]',";
|
||
}
|
||
print OUT ")],";
|
||
print OUT "'sa_id' => [(";
|
||
for (my $i = 0; $i <= $#{$topmaxrcpt{$nb}{sa_id}}; $i++) {
|
||
print OUT "'$topmaxrcpt{$nb}{sa_id}[$i]',";
|
||
}
|
||
print OUT ")],";
|
||
print OUT "},";
|
||
}
|
||
print OUT ");\n\n";
|
||
|
||
print OUT "\%::topmaxsize = (\n";
|
||
foreach my $id (sort { $b <=> $a } keys %topmaxsize) {
|
||
print OUT "'$id' => { ";
|
||
print OUT "'sender' => '$topmaxsize{$id}{sender}',";
|
||
print OUT "'size' => '$topmaxsize{$id}{size}',";
|
||
print OUT "'nrcpt' => '$topmaxsize{$id}{nrcpt}'";
|
||
print OUT "},\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
|
||
# Top spam statistics
|
||
$top = 0;
|
||
print OUT "\%::topspam = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $topspam{rule}{$b} <=> $topspam{rule}{$a} } keys %{$topspam{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $topspam{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $topspam{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $topspam{domain}{$b} <=> $topspam{domain}{$a} } keys %{$topspam{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topspam{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $topspam{domain};
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $topspam{sender_relay}{$b} <=> $topspam{sender_relay}{$a} } keys %{$topspam{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topspam{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $topspam{sender_relay};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $topspam{sender}{$b} <=> $topspam{sender}{$a} } keys %{$topspam{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topspam{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $topspam{sender};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $topspam{rcpt}{$b} <=> $topspam{rcpt}{$a} } keys %{$topspam{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topspam{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
print OUT ");\n\n";
|
||
%topspam = ();
|
||
|
||
# Top spam detail statistics
|
||
$top = 0;
|
||
print OUT "\%::topspamdetail = (\n";
|
||
foreach my $t (sort keys %topspamdetail) {
|
||
print OUT "'$t' => {";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $topspamdetail{$t}{rule}{$b} <=> $topspamdetail{$t}{rule}{$a} } keys %{$topspamdetail{$t}{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $topspamdetail{$t}{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $topspamdetail{$t}{rule};
|
||
$top = 0;
|
||
print OUT "'score' => {";
|
||
foreach my $d (sort { $topspamdetail{$t}{score}{$b} <=> $topspamdetail{$t}{score}{$a} } keys %{$topspamdetail{$t}{score}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topspamdetail{$t}{score}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $topspamdetail{$t}{score};
|
||
$top = 0;
|
||
print OUT "'cache' => {";
|
||
foreach my $d (sort { $topspamdetail{$t}{cache}{$b} <=> $topspamdetail{$t}{cache}{$a} } keys %{$topspamdetail{$t}{cache}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topspamdetail{$t}{cache}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $topspamdetail{$t}{cache};
|
||
$top = 0;
|
||
print OUT "'autolearn' => {";
|
||
foreach my $d (sort { $topspamdetail{$t}{autolearn}{$b} <=> $topspamdetail{$t}{autolearn}{$a} } keys %{$topspamdetail{$t}{autolearn}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$topspamdetail{$t}{autolearn}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $topspamdetail{$t}{autolearn};
|
||
$top = 0;
|
||
print OUT "},";
|
||
}
|
||
print OUT ");\n\n";
|
||
%topspamdetail = ();
|
||
|
||
# Top system message statistics
|
||
$top = 0;
|
||
print OUT "\%::toperr = (\n";
|
||
foreach my $m ( keys %toperr) {
|
||
my $c = $toperr{$m};
|
||
$m =~ s/'/\\'/gs;
|
||
print OUT "'$m' => '$c',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%toperr = ();
|
||
|
||
# Top postgrey statistics
|
||
$top = 0;
|
||
print OUT "\%::toppostgrey = (\n";
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $toppostgrey{sender}{$b} <=> $toppostgrey{sender}{$a} } keys %{$toppostgrey{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$toppostgrey{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $toppostgrey{sender};
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $toppostgrey{sender_relay}{$b} <=> $toppostgrey{sender_relay}{$a} } keys %{$toppostgrey{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$toppostgrey{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $toppostgrey{sender_relay};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $toppostgrey{domain}{$b} <=> $toppostgrey{domain}{$a} } keys %{$toppostgrey{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$toppostgrey{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $toppostgrey{domain};
|
||
$top = 0;
|
||
print OUT "'reason' => {";
|
||
foreach my $d (sort { $toppostgrey{reason}{$b} <=> $toppostgrey{reason}{$a} } keys %{$toppostgrey{reason}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$toppostgrey{reason}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $toppostgrey{reason};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $toppostgrey{rcpt}{$b} <=> $toppostgrey{rcpt}{$a} } keys %{$toppostgrey{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$toppostgrey{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%toppostgrey = ();
|
||
|
||
close(OUT);
|
||
} else {
|
||
&logerror("can't write cache file $file: $!");
|
||
}
|
||
|
||
}
|
||
|
||
sub get_minute_range
|
||
{
|
||
my $val = shift;
|
||
|
||
for (my $i = 5; $i <= 60; $i += 5) {
|
||
return $i if ( ($val < $i) && ($val >= ($i - 5)) );
|
||
}
|
||
|
||
return $val;
|
||
|
||
}
|
||
|
||
sub compute_global_stats
|
||
{
|
||
my ($file, $DOMAIN, $STATS, $begin, $end, $x_label, $hostname) = @_;
|
||
|
||
my %PERIOD_STAT = ();
|
||
|
||
foreach my $id (keys %$STATS) {
|
||
next if (($id eq 'TOPDSN') || ($id eq 'STARTTLS'));
|
||
next if ($DOMAIN && ($STATS->{$id}{sender} !~ /$DOMAIN/) && !grep(/$DOMAIN/, @{$STATS->{$id}{rcpt}}));
|
||
if (exists $STATS->{$id}{dsnstatus}) {
|
||
next if ($DOMAIN && ($STATS->{$STATS->{$id}{srcid}}{sender} !~ /$DOMAIN/) && !grep(/$DOMAIN/, @{$STATS->{$id}{rcpt}}));
|
||
$PERIOD_STAT{dsn}{"$STATS->{$id}{idx_dsn}"}++;
|
||
if (($end > 31) && ($STATS->{$id}{hour} =~ /^\d\d(\d\d)/)) {
|
||
my $m = &get_minute_range($1);
|
||
$PERIOD_STAT{count_dsn}{$m}++;
|
||
}
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{status}}; $i++) {
|
||
if ($STATS->{$id}{status}[$i] eq 'Sent') {
|
||
my $direction = &set_direction($STATS->{$id}{sender_relay}, $STATS->{$id}{rcpt_relay}[$i], $hostname);
|
||
$direction =~ s/^Ext_/Int_/; # DSN are always sent by localhost
|
||
$dsn{$direction}++;
|
||
if ($direction =~ /_Int/) {
|
||
$dsn{local_outbound}++;
|
||
} else {
|
||
$dsn{outbound}++;
|
||
}
|
||
} else {
|
||
$dsn{error}++;
|
||
}
|
||
}
|
||
} elsif (exists $STATS->{$id}{nrcpt}) {
|
||
if ($STATS->{$id}{sender_relay} eq 'localhost') {
|
||
$messaging{local_inbound}++;
|
||
$messaging{local_inbound_bytes} += $STATS->{$id}{size} || 0;
|
||
} elsif (exists $STATS->{$id}{sender_relay}) {
|
||
$messaging{inbound}++;
|
||
$messaging{inbound_bytes} += $STATS->{$id}{size} || 0;
|
||
}
|
||
$PERIOD_STAT{flow}{"$STATS->{$id}{idx_sender}"}{inbound}++;
|
||
$PERIOD_STAT{flow}{"$STATS->{$id}{idx_sender}"}{inbound_bytes} += $STATS->{$id}{size};
|
||
if (($end > 31) && ($STATS->{$id}{hour} =~ /^\d\d(\d\d)/)) {
|
||
my $m = &get_minute_range($1);
|
||
$PERIOD_STAT{count}{$m}++;
|
||
$PERIOD_STAT{count_bytes}{$m} += $STATS->{$id}{size} || 0;
|
||
}
|
||
}
|
||
|
||
if (exists $STATS->{$id}{status}) {
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{status}}; $i++) {
|
||
$GLOBAL_STATUS{"$STATS->{$id}{status}[$i]"}++;
|
||
$GLOBAL_STATUS{"$STATS->{$id}{status}[$i]" . '_bytes'} += $STATS->{$id}{size};
|
||
if ($STATS->{$id}{status}[$i] eq 'Sent') {
|
||
$PERIOD_STAT{flow}{"$STATS->{$id}{idx_rcpt}"}{outbound}++;
|
||
$PERIOD_STAT{flow}{"$STATS->{$id}{idx_rcpt}"}{outbound_bytes} += $STATS->{$id}{size};
|
||
$messaging{nbsender}{"$STATS->{$id}{sender}"} = '';
|
||
$messaging{nbrcpt}{"$STATS->{$id}{rcpt}[$i]"} = '';
|
||
$delivery{'total'}++;
|
||
my $direction = &set_direction($STATS->{$id}{sender_relay}, $STATS->{$id}{rcpt_relay}[$i], $hostname);
|
||
$delivery{$direction}++;
|
||
$direction .= '_bytes';
|
||
$delivery{$direction} += $STATS->{$id}{size};
|
||
if ($direction =~ /_Int/) {
|
||
$messaging{local_outbound}++;
|
||
$messaging{local_outbound_bytes} += $STATS->{$id}{size} || 0;
|
||
} else {
|
||
$messaging{outbound}++;
|
||
$messaging{outbound_bytes} += $STATS->{$id}{size} || 0;
|
||
}
|
||
if (($end > 31) && ($STATS->{$id}{hour}[$i] =~ /^\d\d(\d\d)/)) {
|
||
my $m = &get_minute_range($1);
|
||
$PERIOD_STAT{count1}{$m}++;
|
||
$PERIOD_STAT{count1_bytes}{$m} += $STATS->{$id}{size} || 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (exists $STATS->{$id}{spam}) {
|
||
$PERIOD_STAT{spam}{"$STATS->{$id}{idx_spam}"}++;
|
||
$GLOBAL_STATUS{Spam}++;
|
||
$GLOBAL_STATUS{Spam_bytes} += $STATS->{$id}{size};
|
||
if ($STATS->{$id}{sender_relay} =~ /localhost/) {
|
||
$spam{local_inbound}++;
|
||
$spam{local_inbound_bytes} += $STATS->{$id}{size};
|
||
} elsif ($CONFIG{MAIL_HUB} && $STATS->{$id}{sender_relay} =~ /$CONFIG{MAIL_HUB}/) {
|
||
$spam{local_inbound}++;
|
||
$spam{local_inbound_bytes} += $STATS->{$id}{size};
|
||
} else {
|
||
$spam{inbound}++;
|
||
$spam{inbound_bytes} += $STATS->{$id}{size} || 0;
|
||
}
|
||
if (($end > 31) && ($STATS->{$id}{hour} =~ /^\d\d(\d\d)/)) {
|
||
my $m = &get_minute_range($1);
|
||
$PERIOD_STAT{count_spam}{$m}++;
|
||
}
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{status}}; $i++) {
|
||
if ($STATS->{$id}{status}[$i] eq 'Sent') {
|
||
my $direction = &set_direction($STATS->{$id}{sender_relay}, $STATS->{$id}{rcpt_relay}[$i], $hostname);
|
||
$spam{$direction}++;
|
||
$direction .= '_bytes';
|
||
$spam{$direction} += $STATS->{$id}{size};
|
||
if ($direction =~ /_Int/) {
|
||
$spam{local_outbound}++;
|
||
$spam{local_outbound_bytes} += $STATS->{$id}{size} || 0;
|
||
} else {
|
||
$spam{outbound}++;
|
||
$spam{outbound_bytes} += $STATS->{$id}{size} || 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (exists $STATS->{$id}{virus}) {
|
||
$PERIOD_STAT{virus}{"$STATS->{$id}{idx_virus}"}++;
|
||
$GLOBAL_STATUS{Virus}++;
|
||
$GLOBAL_STATUS{Virus_bytes} += $STATS->{$id}{size};
|
||
if ($STATS->{$id}{sender_relay} =~ /localhost/) {
|
||
$virus{local_inbound}++;
|
||
$virus{local_inbound_bytes} += $STATS->{$id}{size};
|
||
} elsif ($CONFIG{MAIL_HUB} && $STATS->{$id}{sender_relay} =~ /$CONFIG{MAIL_HUB}/) {
|
||
$virus{local_inbound}++;
|
||
$virus{local_inbound_bytes} += $STATS->{$id}{size};
|
||
} else {
|
||
$virus{inbound}++;
|
||
$virus{inbound_bytes} += $STATS->{$id}{size} || 0;
|
||
}
|
||
if (($end > 31) && ($STATS->{$id}{hour} =~ /^\d\d(\d\d)/)) {
|
||
my $m = &get_minute_range($1);
|
||
$PERIOD_STAT{count_virus}{$m}++;
|
||
}
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{status}}; $i++) {
|
||
if ($STATS->{$id}{status}[$i] eq 'Sent') {
|
||
my $direction = &set_direction($STATS->{$id}{sender_relay}, $STATS->{$id}{rcpt_relay}[$i], $hostname);
|
||
$virus{$direction}++;
|
||
$direction .= '_bytes';
|
||
$virus{$direction} += $STATS->{$id}{size};
|
||
if ($direction =~ /_Int/) {
|
||
$virus{local_outbound}++;
|
||
$virus{local_outbound_bytes} += $STATS->{$id}{size} || 0;
|
||
} else {
|
||
$virus{outbound}++;
|
||
$virus{outbound_bytes} += $STATS->{$id}{size} || 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (exists $STATS->{$id}{rule}) {
|
||
$PERIOD_STAT{reject}{"$STATS->{$id}{idx_reject}"}++;
|
||
$GLOBAL_STATUS{Rejected}++;
|
||
$GLOBAL_STATUS{Rejected_bytes} += $STATS->{$id}{size};
|
||
if ($STATS->{$id}{sender_relay} =~ /localhost/) {
|
||
$reject{local_inbound}++;
|
||
$reject{local_inbound_bytes} += $STATS->{$id}{size};
|
||
} elsif ($CONFIG{MAIL_HUB} && $STATS->{$id}{sender_relay} =~ /$CONFIG{MAIL_HUB}/) {
|
||
$reject{local_inbound}++;
|
||
$reject{local_inbound_bytes} += $STATS->{$id}{size};
|
||
} else {
|
||
$reject{inbound}++;
|
||
$reject{inbound_bytes} += $STATS->{$id}{size};
|
||
}
|
||
}
|
||
|
||
if (exists $STATS->{$id}{error}) {
|
||
$GLOBAL_STATUS{SysErr}++;
|
||
$GLOBAL_STATUS{SysErr_bytes} += $STATS->{$id}{size};
|
||
if ($STATS->{$id}{sender_relay} =~ /localhost/) {
|
||
$err{local_inbound}++;
|
||
$err{local_inbound_bytes} += $STATS->{$id}{size};
|
||
} elsif ($CONFIG{MAIL_HUB} && $STATS->{$id}{sender_relay} =~ /$CONFIG{MAIL_HUB}/) {
|
||
$err{local_inbound}++;
|
||
$err{local_inbound_bytes} += $STATS->{$id}{size};
|
||
} else {
|
||
$err{inbound}++;
|
||
$err{inbound_bytes} += $STATS->{$id}{size};
|
||
}
|
||
}
|
||
|
||
if (!$DOMAIN && exists $STATS->{$id}{auth_relay}) {
|
||
for (my $i = 0; $i <= $#{$STATS->{$id}{auth_relay}}; $i++) {
|
||
$PERIOD_STAT{auth}{$STATS->{$id}{auth_type}[$i]}{"$STATS->{$id}{idx_auth}[$i]"}++;
|
||
$auth{$STATS->{$id}{auth_type}[$i]}{$STATS->{$id}{auth_mech}[$i]}++;
|
||
if (($end > 31) && ($STATS->{$id}{auth_hour}[$i] =~ /^\d\d(\d\d)/)) {
|
||
my $m = &get_minute_range($1);
|
||
$PERIOD_STAT{count_auth}{$STATS->{$id}{auth_type}[$i]}{$m}++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (exists $STATS->{$id}{reason}) {
|
||
$postgrey{reason}{$STATS->{$id}{reason}}++;
|
||
}
|
||
|
||
if (exists $STATS->{$id}{spf}) {
|
||
foreach my $r (keys %{ $STATS->{$id}{spf} }) {
|
||
#foreach my $k (keys %{ $STATS->{$id}{spf}{$r}{domain} }) {
|
||
# $spf_dkim{spf}{$r}{domain}{$k} += $STATS->{$id}{spf}{$r}{domain}{$k};
|
||
#}
|
||
foreach my $k (keys %{ $STATS->{$id}{spf}{$r}{status} }) {
|
||
$spf_dkim{spf}{$r}{status}{$k} += $STATS->{$id}{spf}{$r}{status}{$k};
|
||
}
|
||
}
|
||
}
|
||
if (exists $STATS->{$id}{dkim}) {
|
||
foreach my $k (keys %{ $STATS->{$id}{dkim}{status} }) {
|
||
$spf_dkim{dkim}{status}{$k} += $STATS->{$id}{dkim}{status}{$k};
|
||
}
|
||
#foreach my $k (keys %{ $STATS->{$id}{dkim}{domain} }) {
|
||
# $spf_dkim{dkim}{domain}{$k} += $STATS->{$id}{dkim}{domain}{$k};
|
||
#}
|
||
}
|
||
|
||
}
|
||
|
||
# Top STARTTLS stats
|
||
foreach my $v (keys %{$STATS->{'STARTTLS'}}) {
|
||
$starttls{$v} = $STATS->{'STARTTLS'}{$v};
|
||
}
|
||
|
||
# Messaging aggregation
|
||
$messaging{total_inbound} = $messaging{inbound} + $messaging{local_inbound};
|
||
$messaging{total_inbound_bytes} = $messaging{inbound_bytes} + $messaging{local_inbound_bytes};
|
||
$messaging{total_outbound} = $messaging{outbound} + $messaging{local_outbound};
|
||
$messaging{total_outbound_bytes} = $messaging{outbound_bytes} + $messaging{local_outbound_bytes};
|
||
|
||
# Messaging flows
|
||
my $lbls = '';
|
||
# Per five minutes stats
|
||
if ($end > 31) {
|
||
for (my $i = 5; $i <= 60; $i += 5) {
|
||
my $t = sprintf("%02d", $i);
|
||
$lbls .= "$t:";
|
||
$messaging{values} .= ($PERIOD_STAT{count}{$i} || 0) . ':';
|
||
$messaging{values1}.= ($PERIOD_STAT{count1}{$i} || 0) . ':';
|
||
$messaging{values_bytes} .= ($PERIOD_STAT{count_bytes}{$i} || 0) . ':';
|
||
$messaging{values1_bytes} .= ($PERIOD_STAT{count1_bytes}{$i} || 0) . ':';
|
||
$spam{values} .= ($PERIOD_STAT{count_spam}{$i} || 0) . ':';
|
||
$virus{values} .= ($PERIOD_STAT{count_virus}{$i} || 0) . ':';
|
||
$dsn{values} .= ($PERIOD_STAT{count_dsn}{$i} || 0) . ':';
|
||
foreach my $type (keys %{$PERIOD_STAT{auth}}) {
|
||
$auth{$type}{values} .= ($PERIOD_STAT{count_auth}{$type}{$i} || 0) . ':';
|
||
}
|
||
}
|
||
|
||
} else {
|
||
|
||
foreach my $t ("$begin" .. "$end") {
|
||
$lbls .= "$t:";
|
||
$messaging{values} .= ($PERIOD_STAT{flow}{"$t"}{inbound} || 0) . ':';
|
||
$messaging{values1}.= ($PERIOD_STAT{flow}{"$t"}{outbound} || 0) . ':';
|
||
$messaging{values_bytes} .= ($PERIOD_STAT{flow}{"$t"}{inbound_bytes} || 0) . ':';
|
||
$messaging{values1_bytes} .= ($PERIOD_STAT{flow}{"$t"}{outbound_bytes} || 0) . ':';
|
||
$spam{values} .= ($PERIOD_STAT{spam}{"$t"} || 0) . ':';
|
||
$virus{values} .= ($PERIOD_STAT{virus}{"$t"} || 0) . ':';
|
||
$dsn{values} .= ($PERIOD_STAT{dsn}{"$t"} || 0) . ':';
|
||
foreach my $type (keys %{$PERIOD_STAT{auth}}) {
|
||
$auth{$type}{values} .= ($PERIOD_STAT{auth}{$type}{"$t"} || 0) . ':';
|
||
}
|
||
}
|
||
}
|
||
$lbls =~ s/:$//;
|
||
$messaging{values} =~ s/:$//;
|
||
$messaging{values1} =~ s/:$//;
|
||
$messaging{values_bytes} =~ s/:$//;
|
||
$messaging{values1_bytes} =~ s/:$//;
|
||
$spam{values} =~ s/:$//;
|
||
$virus{values} =~ s/:$//;
|
||
$dsn{values} =~ s/:$//;
|
||
foreach my $type (keys %auth) {
|
||
$auth{$type}{values} =~ s/:$//;
|
||
}
|
||
$err{total_inbound} = $err{inbound} + $err{local_inbound};
|
||
$err{total_inbound_bytes} = $err{inbound_bytes} + $err{local_inbound_bytes};
|
||
$spam{total_inbound} = $spam{inbound} + $spam{local_inbound};
|
||
$spam{total_inbound_bytes} = $spam{inbound_bytes} + $spam{local_inbound_bytes};
|
||
$spam{total_outbound} = $spam{outbound} + $spam{local_outbound};
|
||
$spam{total_outbound_bytes} = $spam{outbound_bytes} + $spam{local_outbound_bytes};
|
||
$reject{total_inbound} = $reject{inbound} + $reject{local_inbound};
|
||
$reject{total_inbound_bytes} = $reject{inbound_bytes} + $reject{local_inbound_bytes};
|
||
$virus{total_inbound} = $virus{inbound} + $virus{local_inbound};
|
||
$virus{total_inbound_bytes} = $virus{inbound_bytes} + $virus{local_inbound_bytes};
|
||
$virus{total_outbound} = $virus{outbound} + $virus{local_outbound};
|
||
$virus{total_outbound_bytes} = $virus{outbound_bytes} + $virus{local_outbound_bytes};
|
||
$dsn{total_outbound} = $dsn{outbound} + $dsn{local_outbound};
|
||
my $nbsender = scalar keys %{$messaging{nbsender}};
|
||
my $nbrcpt = scalar keys %{$messaging{nbrcpt}};
|
||
delete $messaging{nbsender};
|
||
delete $messaging{nbrcpt};
|
||
|
||
if (open(OUT, ">>$file")) {
|
||
print OUT "\%::auth = (\n";
|
||
foreach my $type (keys %auth) {
|
||
print OUT "'$type' => {";
|
||
print OUT "'values' => '$auth{$type}{values}',";
|
||
print OUT "'lbls' => '$lbls',";
|
||
print OUT "'x_label' => '$x_label',";
|
||
foreach my $mech (keys %{$auth{$type}}) {
|
||
next if ($mech eq 'values');
|
||
print OUT "'$mech' => '$auth{$type}{$mech}',";
|
||
}
|
||
print OUT "},\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%auth = ();
|
||
print OUT "\%::messaging = (\n";
|
||
print OUT "'inbound' => '$messaging{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$messaging{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$messaging{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$messaging{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$messaging{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$messaging{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$messaging{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$messaging{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$messaging{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$messaging{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$messaging{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$messaging{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => '$x_label',\n";
|
||
print OUT "'values' => '$messaging{values}',\n";
|
||
print OUT "'values1' => '$messaging{values1}',\n";
|
||
print OUT "'values_bytes' => '$messaging{values_bytes}',\n";
|
||
print OUT "'values1_bytes' => '$messaging{values1_bytes}',\n";
|
||
print OUT "'nbsender' => '$nbsender',\n";
|
||
print OUT "'nbrcpt' => '$nbrcpt',\n";
|
||
print OUT ");\n\n";
|
||
%messaging = ();
|
||
|
||
# Spamming flows + Spam delivery flows + Rejection flows
|
||
print OUT "\%::spam = (\n";
|
||
print OUT "'inbound' => '$spam{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$spam{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$spam{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$spam{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$spam{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$spam{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$spam{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$spam{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$spam{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$spam{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$spam{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$spam{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => '$x_label',\n";
|
||
print OUT "'values' => '$spam{values}',\n";
|
||
print OUT "'Ext_Int' => '$spam{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$spam{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$spam{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$spam{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$spam{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$spam{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$spam{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$spam{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%spam = ();
|
||
|
||
print OUT "\%::reject = (\n";
|
||
print OUT "'inbound' => '$reject{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$reject{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$reject{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$reject{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$reject{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$reject{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%reject = ();
|
||
|
||
print OUT "\%::postgrey = (\n";
|
||
print OUT "'reason' => {";
|
||
foreach my $k (keys %{$postgrey{reason}}) {
|
||
print OUT "\t'$k' => '$postgrey{reason}{$k}',";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%postgrey = ();
|
||
|
||
print OUT "\%::spf_dkim = (\n";
|
||
print OUT "'spf' => {\n";
|
||
foreach my $r (keys %{$spf_dkim{spf}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$spf_dkim{spf}{$r}}) {
|
||
print OUT "\t\t'$s' => { ";
|
||
foreach my $v (keys %{$spf_dkim{spf}{$r}{$s}}) {
|
||
print OUT "'$v' => '$spf_dkim{spf}{$r}{$s}{$v}',";
|
||
}
|
||
print OUT " },\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT "'dkim' => {\n";
|
||
foreach my $r (keys %{$spf_dkim{dkim}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$spf_dkim{dkim}{$r}}) {
|
||
print OUT "\t\t'$s' => '$spf_dkim{dkim}{$r}{$s}',\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%spf_dkim = ();
|
||
|
||
# Viruses flows / Viruses delivery flows / syserr flows
|
||
print OUT "\%::virus = (\n";
|
||
print OUT "'inbound' => '$virus{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$virus{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$virus{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$virus{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$virus{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$virus{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$virus{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$virus{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$virus{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$virus{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$virus{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$virus{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => '$x_label',\n";
|
||
print OUT "'values' => '$virus{values}',\n";
|
||
print OUT "'Ext_Int' => '$virus{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$virus{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$virus{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$virus{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$virus{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$virus{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$virus{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$virus{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%virus = ();
|
||
|
||
print OUT "\%::err = (\n";
|
||
print OUT "'inbound' => '$err{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$err{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$err{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$err{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$err{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$err{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%err = ();
|
||
|
||
print OUT "\%::GLOBAL_STATUS = (\n";
|
||
foreach my $s (sort {$GLOBAL_STATUS{$b} <=> $GLOBAL_STATUS{$a}} keys %GLOBAL_STATUS) {
|
||
next if ($s =~ /_bytes/);
|
||
my $slbl = $s;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "'$slbl' => '$GLOBAL_STATUS{$s}',\n";
|
||
print OUT "'$slbl", "_bytes' => '", $GLOBAL_STATUS{$s . '_bytes'}, "',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
|
||
my $elbls = 'Ext -> Int:Ext -> Ext:Int -> Int:Int -> Ext';
|
||
print OUT "\%::delivery = (\n";
|
||
print OUT "'lbls' => '$elbls',\n";
|
||
print OUT "'x_label' => '$x_label',\n";
|
||
print OUT "'Ext_Int' => '$delivery{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$delivery{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$delivery{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$delivery{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$delivery{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$delivery{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$delivery{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$delivery{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
|
||
# DSN
|
||
$dsn{total_outbound} = ($dsn{local_outbound}+$dsn{outbound}) || 0;
|
||
print OUT "\%::dsn = (\n";
|
||
print OUT "'outbound' => '$dsn{outbound}',\n";
|
||
print OUT "'local_outbound' => '$dsn{local_outbound}',\n";
|
||
print OUT "'error' => '$dsn{error}',\n";
|
||
print OUT "'total_outbound' => '$dsn{total_outbound}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => '$x_label',\n";
|
||
print OUT "'values' => '$dsn{values}',\n";
|
||
print OUT "'Ext_Int' => '$dsn{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$dsn{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$dsn{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$dsn{Ext_Ext}',\n";
|
||
print OUT ");\n\n";
|
||
%dsn = ();
|
||
|
||
print OUT "\%::starttls = (\n";
|
||
foreach my $k (keys %starttls) {
|
||
my $slbl = $k;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "\t'$slbl' => '$starttls{$k}',";
|
||
}
|
||
print OUT ");\n\n";
|
||
%starttls = ();
|
||
|
||
close(OUT);
|
||
} else {
|
||
&logerror("can't write cache file $file: $!");
|
||
}
|
||
|
||
}
|
||
|
||
sub free_space
|
||
{
|
||
my $path = shift;
|
||
my @days = @_;
|
||
|
||
return if ( !$CONFIG{FREE_SPACE} || (lc($CONFIG{FREE_SPACE}) eq 'none') );
|
||
|
||
if ( (lc($CONFIG{FREE_SPACE}) eq 'archive') && !-e "$path/history.tar.gz") {
|
||
print "Backuping monthly data files into $path/history.tar.gz\n" if ($CONFIG{DEBUG});
|
||
my @found = `find $path -name "*.dat" 2>/dev/null`;
|
||
if ($#found >= 0) {
|
||
`tar czf $path/history.tar.gz \`find $path -name "*.dat"\` 2>/dev/null`;
|
||
if ($? != 0) {
|
||
print STDERR "ERROR: can't create archive $path/history.tar.gz, reason: $!\n";
|
||
}
|
||
}
|
||
}
|
||
if (-e "$path/history.tar.gz" || (lc($CONFIG{FREE_SPACE}) eq 'delete')) {
|
||
opendir(DIR, "$path") || die "can't opendir $path: $!";
|
||
my @ddirs = grep { /^\d+$/ && -d "$path/$_" } readdir(DIR);
|
||
closedir DIR;
|
||
foreach my $d (@ddirs) {
|
||
my @files = `ls $path/$d/*.dat 2>/dev/null`;
|
||
if ($#files >= 0) {
|
||
print "Removing monthly data file $path/$d/*.dat\n" if ($CONFIG{DEBUG});
|
||
`rm -f $path/$d/*.dat`;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
sub free_space_week
|
||
{
|
||
my ($path, @days) = @_;
|
||
|
||
return if ( !$CONFIG{FREE_SPACE} || (lc($CONFIG{FREE_SPACE}) eq 'none') );
|
||
|
||
if ( (lc($CONFIG{FREE_SPACE}) eq 'archive') && !-e "$path/history.tar.gz") {
|
||
print "Backuping weekly data files into $path/history.tar.gz\n" if ($CONFIG{DEBUG});
|
||
my @found = ();
|
||
foreach my $d (@days) {
|
||
push(@found, `find $d -name "*.dat" 2>/dev/null`);
|
||
}
|
||
if ($#found >= 0) {
|
||
chomp(@found);
|
||
my $files = join(" ", @found);
|
||
`tar czf $path/history.tar.gz $files 2>/dev/null`;
|
||
if ($? != 0) {
|
||
print STDERR "ERROR: can't create archive $path/history.tar.gz, reason: $!\n";
|
||
}
|
||
}
|
||
}
|
||
if (-e "$path/history.tar.gz" || (lc($CONFIG{FREE_SPACE}) eq 'delete')) {
|
||
foreach my $d (@days) {
|
||
my @files = `ls $d/*.dat 2>/dev/null`;
|
||
if ($#files >= 0) {
|
||
print "Removing weekly data files $d/*.dat\n" if ($CONFIG{DEBUG});
|
||
`rm -f $d/*.dat`;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
####
|
||
# Day cache statistics
|
||
####
|
||
sub do_day_cache
|
||
{
|
||
my ($hostname, $DOMAIN, $year, $month, $day, $curday) = @_;
|
||
|
||
if (-e "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/cache.pm\U$DOMAIN\E" && ("$year$month$day" < $curday)) {
|
||
return;
|
||
}
|
||
|
||
print "Reading daily statistics from $CONFIG{OUT_DIR}/$hostname/$year/$month/$day\n" if ($CONFIG{DEBUG});
|
||
|
||
my %localtopsender = ();
|
||
my %localtoprcpt = ();
|
||
my %localtopspam = ();
|
||
my %localtopvirus = ();
|
||
my %localtopdsn = ();
|
||
my %localtopreject = ();
|
||
my %localtoperr = ();
|
||
my %localdelivery = ();
|
||
my %localmessaging = ();
|
||
my %localspam = ();
|
||
my %localvirus = ();
|
||
my %localdsn = ();
|
||
my %localreject = ();
|
||
my %localerr = ();
|
||
my %localGLOBAL_STATUS = ();
|
||
my %localtopspamdetail = ();
|
||
my %localauth = ();
|
||
my %localtopauth = ();
|
||
my %localpostgrey = ();
|
||
my %localtoppostgrey = ();
|
||
my %localstarttls = ();
|
||
my %localspf_dkim = ();
|
||
my $lbls = '';
|
||
my %authval = ();
|
||
foreach my $hour ("00" .. "23") {
|
||
$lbls .= "$hour:";
|
||
if (!-e "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/${hour}cache.pm\U$DOMAIN\E") {
|
||
$localmessaging{values} .= '0:';
|
||
$localmessaging{values1} .= '0:';
|
||
$localmessaging{values_bytes} .= '0:';
|
||
$localmessaging{values1_bytes} .= '0:';
|
||
$localspam{values} .= '0:';
|
||
$localvirus{values} .= '0:';
|
||
$localdsn{values} .= '0:';
|
||
$localmessaging{nbsender} .= '0:';
|
||
$localmessaging{nbrcpt} .= '0:';
|
||
next;
|
||
} else {
|
||
&clean_globals();
|
||
my $file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/${hour}cache.pm\U$DOMAIN\E";
|
||
print "Loading cache statistics from $file\n" if ($CONFIG{DEBUG});
|
||
do "$file";
|
||
foreach my $k (keys %messaging) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values','values1','values_bytes','values1_bytes','nbsender','nbrcpt')) {
|
||
$localmessaging{$k} += $messaging{$k};
|
||
}
|
||
}
|
||
$localmessaging{values} .= ($messaging{total_inbound} || 0) . ':';
|
||
$localmessaging{values1} .= ($messaging{total_outbound} || 0) . ':';
|
||
$localmessaging{values_bytes} .= ($messaging{total_inbound_bytes} || 0) . ':';
|
||
$localmessaging{values1_bytes} .= ($messaging{total_outbound_bytes} || 0) . ':';
|
||
my $tmp = 0;
|
||
foreach (split(/:/, $messaging{nbsender})) {
|
||
$tmp += $_;
|
||
}
|
||
$localmessaging{nbsender} .= $tmp . ':';
|
||
$tmp = 0;
|
||
foreach (split(/:/, $messaging{nbrcpt})) {
|
||
$tmp += $_;
|
||
}
|
||
$localmessaging{nbrcpt} .= $tmp . ':';
|
||
%messaging = ();
|
||
|
||
foreach my $t (keys %auth) {
|
||
foreach my $m (keys %{$auth{$t}}) {
|
||
if (!grep(/^$m$/, 'lbls','x_label','values')) {
|
||
$localauth{$t}{$m} += $auth{$t}{$m};
|
||
$localauth{$t}{values}{"$hour"} += $auth{$t}{$m};
|
||
}
|
||
}
|
||
}
|
||
%auth = ();
|
||
|
||
foreach my $k (keys %spam) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localspam{$k} += $spam{$k};
|
||
}
|
||
}
|
||
$localspam{values} .= ($spam{total_inbound} || 0) . ':';
|
||
%spam = ();
|
||
foreach my $k (keys %reject) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localreject{$k} += $reject{$k};
|
||
}
|
||
}
|
||
%reject = ();
|
||
foreach my $k (keys %{$postgrey{reason}}) {
|
||
$localpostgrey{reason}{$k} += $postgrey{reason}{$k};
|
||
}
|
||
%postgrey = ();
|
||
|
||
foreach my $r (keys %{$spf_dkim{spf}}) {
|
||
foreach my $k (keys %{$spf_dkim{spf}{$r}{status}}) {
|
||
$localspf_dkim{spf}{$r}{status}{$k} += $spf_dkim{spf}{$r}{status}{$k};
|
||
}
|
||
foreach my $k (keys %{$spf_dkim{spf}{$r}{domain}}) {
|
||
$localspf_dkim{spf}{$r}{domain}{$k} += $spf_dkim{spf}{$r}{domain}{$k};
|
||
}
|
||
}
|
||
foreach my $r (keys %{$spf_dkim{dkim}{status}}) {
|
||
$localspf_dkim{dkim}{status}{$r} += $spf_dkim{dkim}{status}{$r};
|
||
}
|
||
%spf_dkim = ();
|
||
|
||
foreach my $k (keys %virus) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localvirus{$k} += $virus{$k};
|
||
}
|
||
}
|
||
$localvirus{values} .= ($virus{total_inbound} || 0) . ':';
|
||
%virus = ();
|
||
foreach my $k (keys %dsn) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localdsn{$k} += $dsn{$k};
|
||
}
|
||
}
|
||
$localdsn{values} .= ($dsn{total_outbound} || 0) . ':';
|
||
%dsn = ();
|
||
|
||
foreach my $k (keys %err) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localerr{$k} += $err{$k};
|
||
}
|
||
}
|
||
%err = ();
|
||
foreach my $k (keys %GLOBAL_STATUS) {
|
||
$localGLOBAL_STATUS{$k} += $GLOBAL_STATUS{$k};
|
||
}
|
||
%GLOBAL_STATUS = ();
|
||
foreach my $k (keys %delivery) {
|
||
if (!grep(/^$k$/, 'lbls','x_label')) {
|
||
$localdelivery{$k} += $delivery{$k};
|
||
}
|
||
}
|
||
|
||
foreach my $k (keys %topsender) {
|
||
foreach my $d (keys %{$topsender{$k}}) {
|
||
$localtopsender{$k}{$d} += $topsender{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topsender = ();
|
||
|
||
foreach my $k (keys %toprcpt) {
|
||
foreach my $d (keys %{$toprcpt{$k}}) {
|
||
$localtoprcpt{$k}{$d} += $toprcpt{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%toprcpt = ();
|
||
|
||
foreach my $k (keys %topreject) {
|
||
foreach my $d (keys %{$topreject{$k}}) {
|
||
$localtopreject{$k}{$d} += $topreject{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topreject = ();
|
||
|
||
foreach my $k (keys %topvirus) {
|
||
foreach my $d (keys %{$topvirus{$k}}) {
|
||
$localtopvirus{$k}{$d} += $topvirus{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topvirus = ();
|
||
|
||
foreach my $k (keys %topdsn) {
|
||
foreach my $d (keys %{$topdsn{$k}}) {
|
||
$localtopdsn{$k}{$d} += $topdsn{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topdsn = ();
|
||
|
||
foreach my $k (keys %topspam) {
|
||
foreach my $d (keys %{$topspam{$k}}) {
|
||
$localtopspam{$k}{$d} += $topspam{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topspam = ();
|
||
foreach my $k (keys %toperr) {
|
||
$localtoperr{$k} += $toperr{$k} || 0;
|
||
}
|
||
%toperr = ();
|
||
|
||
foreach my $k (keys %toppostgrey) {
|
||
foreach my $d (keys %{$toppostgrey{$k}}) {
|
||
$localtoppostgrey{$k}{$d} += $toppostgrey{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%toppostgrey = ();
|
||
|
||
foreach my $t (keys %topspamdetail) {
|
||
foreach my $k (keys %{$topspamdetail{$t}}) {
|
||
foreach my $d (keys %{$topspamdetail{$t}{$k}}) {
|
||
$localtopspamdetail{$t}{$k}{$d} += $topspamdetail{$t}{$k}{$d} || 0;
|
||
}
|
||
}
|
||
}
|
||
%topspamdetail = ();
|
||
|
||
foreach my $k (keys %topauth) {
|
||
foreach my $d (keys %{$topauth{$k}}) {
|
||
$localtopauth{$k}{$d} += $topauth{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topauth = ();
|
||
foreach my $t (keys %localauth) {
|
||
$authval{$t} .= ($localauth{$t}{values}{"$hour"} || 0) . ':';
|
||
}
|
||
foreach my $k (keys %starttls) {
|
||
$localstarttls{$k} += $starttls{$k};
|
||
}
|
||
%starttls = ();
|
||
}
|
||
}
|
||
foreach my $t (keys %localauth) {
|
||
delete $localauth{$t}{values};
|
||
$localauth{$t}{values} = $authval{$t};
|
||
$localauth{$t}{lbls} =~ s/:$//;
|
||
$localauth{$t}{values} =~ s/:$//;
|
||
}
|
||
|
||
$lbls =~ s/:$//;
|
||
$localmessaging{values} =~ s/:$//;
|
||
$localmessaging{values1} =~ s/:$//;
|
||
$localmessaging{values_bytes} =~ s/:$//;
|
||
$localmessaging{values1_bytes} =~ s/:$//;
|
||
$localspam{values} =~ s/:$//;
|
||
$localvirus{values} =~ s/:$//;
|
||
$localdsn{values} =~ s/:$//;
|
||
$localmessaging{nbrcpt} =~ s/:$//;
|
||
$localmessaging{nbsender} =~ s/:$//;
|
||
|
||
my $file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/cache.pm\U$DOMAIN\E";
|
||
|
||
print "Writing cache file: $file\n" if ($CONFIG{DEBUG});
|
||
|
||
if (open(OUT, ">$file")) {
|
||
print OUT "\%::auth = (\n";
|
||
foreach my $type (keys %localauth) {
|
||
print OUT "'$type' => {";
|
||
print OUT "'values' => '$localauth{$type}{values}',";
|
||
print OUT "'lbls' => '$lbls',";
|
||
print OUT "'x_label' => 'Day of the month',";
|
||
foreach my $mech (keys %{$localauth{$type}}) {
|
||
next if (grep(/^$mech$/,'lbls','x_label','values'));
|
||
print OUT "'$mech' => '$localauth{$type}{$mech}',";
|
||
}
|
||
print OUT "},\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localauth = ();
|
||
print OUT "\%::messaging = (\n";
|
||
print OUT "'inbound' => '$localmessaging{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localmessaging{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localmessaging{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localmessaging{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localmessaging{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localmessaging{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localmessaging{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localmessaging{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localmessaging{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localmessaging{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localmessaging{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localmessaging{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Day of the month',\n";
|
||
print OUT "'values' => '$localmessaging{values}',\n";
|
||
print OUT "'values1' => '$localmessaging{values1}',\n";
|
||
print OUT "'values_bytes' => '$localmessaging{values_bytes}',\n";
|
||
print OUT "'values1_bytes' => '$localmessaging{values1_bytes}',\n";
|
||
print OUT "'nbsender' => '$localmessaging{nbsender}',\n";
|
||
print OUT "'nbrcpt' => '$localmessaging{nbrcpt}',\n";
|
||
print OUT ");\n\n";
|
||
%localmessaging = ();
|
||
|
||
print OUT "\%::spam = (\n";
|
||
print OUT "'inbound' => '$localspam{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localspam{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localspam{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localspam{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localspam{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localspam{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localspam{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localspam{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localspam{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localspam{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localspam{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localspam{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Day of the month',\n";
|
||
print OUT "'values' => '$localspam{values}',\n";
|
||
print OUT "'Ext_Int' => '$localspam{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localspam{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localspam{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localspam{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localspam{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localspam{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localspam{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localspam{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localspam = ();
|
||
|
||
print OUT "\%::reject = (\n";
|
||
print OUT "'inbound' => '$localreject{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localreject{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localreject{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localreject{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localreject{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localreject{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localreject = ();
|
||
|
||
print OUT "\%::postgrey = (\n";
|
||
print OUT "'reason' => {";
|
||
foreach my $k (keys %{$localpostgrey{reason}}) {
|
||
print OUT "\t'$k' => '$localpostgrey{reason}{$k}',";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localpostgrey = ();
|
||
|
||
print OUT "\%::spf_dkim = (\n";
|
||
print OUT "'spf' => {\n";
|
||
foreach my $r (keys %{$localspf_dkim{spf}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$localspf_dkim{spf}{$r}}) {
|
||
print OUT "\t\t'$s' => { ";
|
||
foreach my $v (keys %{$localspf_dkim{spf}{$r}{$s}}) {
|
||
print OUT "'$v' => '$localspf_dkim{spf}{$r}{$s}{$v}',";
|
||
}
|
||
print OUT " },\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT "'dkim' => {\n";
|
||
foreach my $r (keys %{$localspf_dkim{dkim}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$localspf_dkim{dkim}{$r}}) {
|
||
print OUT "\t\t'$s' => '$localspf_dkim{dkim}{$r}{$s}',\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localspf_dkim = ();
|
||
|
||
print OUT "\%::virus = (\n";
|
||
print OUT "'inbound' => '$localvirus{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localvirus{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localvirus{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localvirus{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localvirus{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localvirus{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localvirus{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localvirus{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localvirus{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localvirus{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localvirus{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localvirus{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Day of the month',\n";
|
||
print OUT "'values' => '$localvirus{values}',\n";
|
||
print OUT "'Ext_Int' => '$localvirus{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localvirus{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localvirus{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localvirus{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localvirus{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localvirus{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localvirus{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localvirus{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localvirus = ();
|
||
|
||
print OUT "\%::dsn = (\n";
|
||
print OUT "'outbound' => '$localdsn{outbound}',\n";
|
||
print OUT "'local_outbound' => '$localdsn{local_outbound}',\n";
|
||
print OUT "'total_outbound' => '$localdsn{total_outbound}',\n";
|
||
print OUT "'error' => '$localdsn{error}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Day of the month',\n";
|
||
print OUT "'values' => '$localdsn{values}',\n";
|
||
print OUT "'Ext_Int' => '$localdsn{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localdsn{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localdsn{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localdsn{Ext_Ext}',\n";
|
||
print OUT ");\n\n";
|
||
%localdsn = ();
|
||
|
||
print OUT "\%::err = (\n";
|
||
print OUT "'inbound' => '$localerr{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localerr{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localerr{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localerr{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localerr{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localerr{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localerr = ();
|
||
|
||
print OUT "\%::GLOBAL_STATUS = (\n";
|
||
foreach my $k (keys %localGLOBAL_STATUS) {
|
||
my $slbl = $k;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "'$slbl' => '$localGLOBAL_STATUS{$k}',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localGLOBAL_STATUS = ();
|
||
|
||
print OUT "\%::starttls = (\n";
|
||
foreach my $v (sort keys %localstarttls) {
|
||
my $slbl = $v;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "'$slbl' => '$localstarttls{$v}',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localstarttls = ();
|
||
|
||
my $elbls = 'Ext -> Int:Ext -> Ext:Int -> Int:Int -> Ext';
|
||
print OUT "\%::delivery = (\n";
|
||
print OUT "'lbls' => '$elbls',\n";
|
||
print OUT "'x_label' => 'Day of the month',\n";
|
||
print OUT "'Ext_Int' => '$localdelivery{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localdelivery{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localdelivery{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localdelivery{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localdelivery{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localdelivery{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localdelivery{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localdelivery{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localdelivery = ();
|
||
|
||
# Top SMTP Auth statistics
|
||
my $top = 0;
|
||
print OUT "\%::topauth = (\n";
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopauth{relay}{$b} <=> $localtopauth{relay}{$a} } keys %{$localtopauth{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopauth{relay};
|
||
$top = 0;
|
||
print OUT "'mech' => {";
|
||
foreach my $d (sort { $localtopauth{mech}{$b} <=> $localtopauth{mech}{$a} } keys %{$localtopauth{mech}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{mech}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopauth{mech};
|
||
$top = 0;
|
||
print OUT "'authid' => {";
|
||
foreach my $d (sort { $localtopauth{authid}{$b} <=> $localtopauth{authid}{$a} } keys %{$localtopauth{authid}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{authid}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopauth = ();
|
||
|
||
# Top sender statistics
|
||
$top = 0;
|
||
print OUT "\%::topsender = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopsender{domain}{$b} <=> $localtopsender{domain}{$a} } keys %{$localtopsender{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopsender{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopsender{relay}{$b} <=> $localtopsender{relay}{$a} } keys %{$localtopsender{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopsender{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $localtopsender{email}{$b} <=> $localtopsender{email}{$a} } keys %{$localtopsender{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopsender = ();
|
||
|
||
# Top recipient statistics
|
||
$top = 0;
|
||
print OUT "\%::toprcpt = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtoprcpt{domain}{$b} <=> $localtoprcpt{domain}{$a} } keys %{$localtoprcpt{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoprcpt{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtoprcpt{relay}{$b} <=> $localtoprcpt{relay}{$a} } keys %{$localtoprcpt{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoprcpt{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $localtoprcpt{email}{$b} <=> $localtoprcpt{email}{$a} } keys %{$localtoprcpt{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtoprcpt = ();
|
||
|
||
# Top rejection statistics
|
||
$top = 0;
|
||
print OUT "\%::topreject = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopreject{rule}{$b} <=> $localtopreject{rule}{$a} } keys %{$localtopreject{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopreject{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopreject{domain}{$b} <=> $localtopreject{domain}{$a} } keys %{$localtopreject{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopreject{relay}{$b} <=> $localtopreject{relay}{$a} } keys %{$localtopreject{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{relay};
|
||
$top = 0;
|
||
print OUT "'chck_status' => {";
|
||
foreach my $d (sort { $localtopreject{chck_status}{$b} <=> $localtopreject{chck_status}{$a} } keys %{$localtopreject{chck_status}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopreject{chck_status}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{chck_status};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopreject{sender}{$b} <=> $localtopreject{sender}{$a} } keys %{$localtopreject{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopreject = ();
|
||
|
||
# Top virus statistics
|
||
$top = 0;
|
||
print OUT "\%::topvirus = (\n";
|
||
print OUT "'virus' => {";
|
||
foreach my $d (sort { $localtopvirus{virus}{$b} <=> $localtopvirus{virus}{$a} } keys %{$localtopvirus{virus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopvirus{virus}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{virus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopvirus{sender}{$b} <=> $localtopvirus{sender}{$a} } keys %{$localtopvirus{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopvirus{relay}{$b} <=> $localtopvirus{relay}{$a} } keys %{$localtopvirus{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{relay};
|
||
$top = 0;
|
||
print OUT "'file' => {";
|
||
foreach my $d (sort { $localtopvirus{file}{$b} <=> $localtopvirus{file}{$a} } keys %{$localtopvirus{file}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{file}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{file};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopvirus{rcpt}{$b} <=> $localtopvirus{rcpt}{$a} } keys %{$localtopvirus{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopvirus = ();
|
||
|
||
# Top dsn statistics
|
||
$top = 0;
|
||
print OUT "\%::topdsn = (\n";
|
||
print OUT "'dsnstatus' => {";
|
||
foreach my $d (sort { $localtopdsn{dsnstatus}{$b} <=> $localtopdsn{dsnstatus}{$a} } keys %{$localtopdsn{dsnstatus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopdsn{dsnstatus}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{dsnstatus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopdsn{sender}{$b} <=> $localtopdsn{sender}{$a} } keys %{$localtopdsn{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopdsn{relay}{$b} <=> $localtopdsn{relay}{$a} } keys %{$localtopdsn{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{relay};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopdsn{rcpt}{$b} <=> $localtopdsn{rcpt}{$a} } keys %{$localtopdsn{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopdsn = ();
|
||
|
||
# Top spam statistics
|
||
$top = 0;
|
||
print OUT "\%::topspam = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopspam{rule}{$b} <=> $localtopspam{rule}{$a} } keys %{$localtopspam{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopspam{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopspam{domain}{$b} <=> $localtopspam{domain}{$a} } keys %{$localtopspam{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{domain};
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $localtopspam{sender_relay}{$b} <=> $localtopspam{sender_relay}{$a} } keys %{$localtopspam{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{sender_relay};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopspam{sender}{$b} <=> $localtopspam{sender}{$a} } keys %{$localtopspam{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{sender};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopspam{rcpt}{$b} <=> $localtopspam{rcpt}{$a} } keys %{$localtopspam{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
print OUT ");\n\n";
|
||
%localtopspam = ();
|
||
|
||
# Top system message statistics
|
||
$top = 0;
|
||
print OUT "\%::toperr = (\n";
|
||
foreach my $m (sort { $localtopspam{$b} <=> $localtopspam{$a} } keys %localtoperr) {
|
||
my $c = $localtoperr{$m};
|
||
$m =~ s/'/\\'/g;
|
||
print OUT "'$m' => $c,\n";
|
||
}
|
||
print OUT ");\n";
|
||
%localtoperr = ();
|
||
|
||
# Top postgrey statistics
|
||
$top = 0;
|
||
print OUT "\%::toppostgrey = (\n";
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtoppostgrey{sender}{$b} <=> $localtoppostgrey{sender}{$a} } keys %{$localtoppostgrey{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{sender};
|
||
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $localtoppostgrey{sender_relay}{$b} <=> $localtoppostgrey{sender_relay}{$a} } keys %{$localtoppostgrey{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{sender_relay};
|
||
$top= 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtoppostgrey{domain}{$b} <=> $localtoppostgrey{domain}{$a} } keys %{$localtoppostgrey{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{domain};
|
||
$top= 0;
|
||
print OUT "'reason' => {";
|
||
foreach my $d (sort { $localtoppostgrey{reason}{$b} <=> $localtoppostgrey{reason}{$a} } keys %{$localtoppostgrey{reason}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{reason}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{reason};
|
||
$top= 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtoppostgrey{rcpt}{$b} <=> $localtoppostgrey{rcpt}{$a} } keys %{$localtoppostgrey{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtoppostgrey = ();
|
||
|
||
# Top spam detail statistics
|
||
$top = 0;
|
||
print OUT "\%::topspamdetail = (\n";
|
||
foreach my $t (sort keys %localtopspamdetail) {
|
||
print OUT "'$t' => {";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{rule}{$b} <=> $localtopspamdetail{$t}{rule}{$a} } keys %{$localtopspamdetail{$t}{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopspamdetail{$t}{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{rule};
|
||
$top = 0;
|
||
print OUT "'score' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{score}{$b} <=> $localtopspamdetail{$t}{score}{$a} } keys %{$localtopspamdetail{$t}{score}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{score}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{score};
|
||
$top = 0;
|
||
print OUT "'cache' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{cache}{$b} <=> $localtopspamdetail{$t}{cache}{$a} } keys %{$localtopspamdetail{$t}{cache}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{cache}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{cache};
|
||
$top = 0;
|
||
print OUT "'autolearn' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{autolearn}{$b} <=> $localtopspamdetail{$t}{autolearn}{$a} } keys %{$localtopspamdetail{$t}{autolearn}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{autolearn}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{autolearn};
|
||
$top = 0;
|
||
print OUT "},";
|
||
}
|
||
print OUT ");\n";
|
||
close(OUT);
|
||
} else {
|
||
&logerror("can't write cache file $file: $!");
|
||
}
|
||
|
||
}
|
||
|
||
####
|
||
# Month cache statistics
|
||
####
|
||
sub do_month_cache
|
||
{
|
||
my ($hostname, $DOMAIN, $year, $month, $curmonth) = @_;
|
||
|
||
if (!$DOMAIN && -e "$CONFIG{OUT_DIR}/$hostname/$year/$month/cache.pm" && ("$year$month" < $curmonth)) {
|
||
# reduce disk space storage by deleting or archiving data file
|
||
if (!$CONFIG{WEEKLY_FREE_SPACE}) {
|
||
&free_space("$CONFIG{OUT_DIR}/$hostname/$year/$month");
|
||
return;
|
||
}
|
||
}
|
||
if (-e "$CONFIG{OUT_DIR}/$hostname/$year/$month/cache.pm\U$DOMAIN\E" && ("$year$month" < $curmonth)) {
|
||
return;
|
||
}
|
||
|
||
print "Reading statistics from $CONFIG{OUT_DIR}/$hostname/$year/$month\n" if ($CONFIG{DEBUG});
|
||
|
||
my %localtopsender = ();
|
||
my %localtoprcpt = ();
|
||
my %localtopspam = ();
|
||
my %localtopvirus = ();
|
||
my %localtopdsn = ();
|
||
my %localtopreject = ();
|
||
my %localtoperr = ();
|
||
my %localdelivery = ();
|
||
my %localmessaging = ();
|
||
my %localspam = ();
|
||
my %localvirus = ();
|
||
my %localdsn = ();
|
||
my %localreject = ();
|
||
my %localerr = ();
|
||
my %localGLOBAL_STATUS = ();
|
||
my %localtopspamdetail = ();
|
||
my %localauth = ();
|
||
my %localtopauth = ();
|
||
my %localpostgrey = ();
|
||
my %localtoppostgrey = ();
|
||
my %localstarttls = ();
|
||
my %localspf_dkim = ();
|
||
my $lbls = '';
|
||
foreach my $day ("01" .. "31") {
|
||
$lbls .= "$day:";
|
||
if (!-e "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/cache.pm\U$DOMAIN\E") {
|
||
$localmessaging{values} .= '0:';
|
||
$localmessaging{values1} .= '0:';
|
||
$localmessaging{values_bytes} .= '0:';
|
||
$localmessaging{values1_bytes} .= '0:';
|
||
$localspam{values} .= '0:';
|
||
$localvirus{values} .= '0:';
|
||
$localdsn{values} .= '0:';
|
||
$localmessaging{nbsender} .= '0:';
|
||
$localmessaging{nbrcpt} .= '0:';
|
||
next;
|
||
} else {
|
||
&clean_globals();
|
||
my $file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/cache.pm\U$DOMAIN\E";
|
||
print "Loading cache statistics from $file\n" if ($CONFIG{DEBUG});
|
||
do "$file";
|
||
foreach my $k (keys %messaging) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values','values1','values_bytes','values1_bytes','nbsender','nbrcpt')) {
|
||
$localmessaging{$k} += $messaging{$k};
|
||
}
|
||
}
|
||
|
||
$localmessaging{values} .= ($messaging{total_inbound} || 0) . ':';
|
||
$localmessaging{values1} .= ($messaging{total_outbound} || 0) . ':';
|
||
$localmessaging{values_bytes} .= ($messaging{total_inbound_bytes} || 0) . ':';
|
||
$localmessaging{values1_bytes} .= ($messaging{total_outbound_bytes} || 0) . ':';
|
||
my $tmp = 0;
|
||
foreach (split(/:/, $messaging{nbsender})) {
|
||
$tmp += $_;
|
||
}
|
||
$localmessaging{nbsender} .= $tmp . ':';
|
||
$tmp = 0;
|
||
foreach (split(/:/, $messaging{nbrcpt})) {
|
||
$tmp += $_;
|
||
}
|
||
$localmessaging{nbrcpt} .= $tmp . ':';
|
||
%messaging = ();
|
||
|
||
foreach my $t (keys %auth) {
|
||
foreach my $m (keys %{$auth{$t}}) {
|
||
if (!grep(/^$m$/, 'lbls','x_label','values')) {
|
||
$localauth{$t}{$m} += $auth{$t}{$m};
|
||
$localauth{$t}{values}{"$day"} += $auth{$t}{$m};
|
||
}
|
||
}
|
||
}
|
||
%auth = ();
|
||
|
||
foreach my $k (keys %spam) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localspam{$k} += $spam{$k};
|
||
}
|
||
}
|
||
$localspam{values} .= ($spam{total_inbound} || 0) . ':';
|
||
%spam = ();
|
||
foreach my $k (keys %reject) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localreject{$k} += $reject{$k};
|
||
}
|
||
}
|
||
%reject = ();
|
||
foreach my $k (keys %{$postgrey{reason}}) {
|
||
$localpostgrey{reason}{$k} += $postgrey{reason}{$k};
|
||
}
|
||
%postgrey = ();
|
||
|
||
foreach my $r (keys %{$spf_dkim{spf}}) {
|
||
foreach my $k (keys %{$spf_dkim{spf}{$r}{status}}) {
|
||
$localspf_dkim{spf}{$r}{status}{$k} += $spf_dkim{spf}{$r}{status}{$k};
|
||
}
|
||
foreach my $k (keys %{$spf_dkim{spf}{$r}{domain}}) {
|
||
$localspf_dkim{spf}{$r}{domain}{$k} += $spf_dkim{spf}{$r}{domain}{$k};
|
||
}
|
||
}
|
||
foreach my $r (keys %{$spf_dkim{dkim}{status}}) {
|
||
$localspf_dkim{dkim}{status}{$r} += $spf_dkim{dkim}{status}{$r};
|
||
}
|
||
%spf_dkim = ();
|
||
|
||
foreach my $k (keys %virus) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localvirus{$k} += $virus{$k};
|
||
}
|
||
}
|
||
$localvirus{values} .= ($virus{total_inbound} || 0) . ':';
|
||
%virus = ();
|
||
foreach my $k (keys %dsn) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localdsn{$k} += $dsn{$k};
|
||
}
|
||
}
|
||
$localdsn{values} .= ($dsn{total_outbound} || 0) . ':';
|
||
%dsn = ();
|
||
|
||
foreach my $k (keys %err) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localerr{$k} += $err{$k};
|
||
}
|
||
}
|
||
%err = ();
|
||
foreach my $k (keys %GLOBAL_STATUS) {
|
||
$localGLOBAL_STATUS{$k} += $GLOBAL_STATUS{$k};
|
||
}
|
||
%GLOBAL_STATUS = ();
|
||
foreach my $k (keys %delivery) {
|
||
if (!grep(/^$k$/, 'lbls','x_label')) {
|
||
$localdelivery{$k} += $delivery{$k};
|
||
}
|
||
}
|
||
|
||
foreach my $k (keys %topsender) {
|
||
foreach my $d (keys %{$topsender{$k}}) {
|
||
$localtopsender{$k}{$d} += $topsender{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topsender = ();
|
||
|
||
foreach my $k (keys %toprcpt) {
|
||
foreach my $d (keys %{$toprcpt{$k}}) {
|
||
$localtoprcpt{$k}{$d} += $toprcpt{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%toprcpt = ();
|
||
|
||
foreach my $k (keys %topreject) {
|
||
foreach my $d (keys %{$topreject{$k}}) {
|
||
$localtopreject{$k}{$d} += $topreject{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topreject = ();
|
||
|
||
foreach my $k (keys %topvirus) {
|
||
foreach my $d (keys %{$topvirus{$k}}) {
|
||
$localtopvirus{$k}{$d} += $topvirus{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topvirus = ();
|
||
|
||
foreach my $k (keys %topdsn) {
|
||
foreach my $d (keys %{$topdsn{$k}}) {
|
||
$localtopdsn{$k}{$d} += $topdsn{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topdsn = ();
|
||
|
||
foreach my $k (keys %topspam) {
|
||
foreach my $d (keys %{$topspam{$k}}) {
|
||
$localtopspam{$k}{$d} += $topspam{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topspam = ();
|
||
foreach my $k (keys %toperr) {
|
||
$localtoperr{$k} += $toperr{$k} || 0;
|
||
}
|
||
%toperr = ();
|
||
foreach my $k (keys %toppostgrey) {
|
||
foreach my $d (keys %{$toppostgrey{$k}}) {
|
||
$localtoppostgrey{$k}{$d} += $toppostgrey{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%toppostgrey = ();
|
||
foreach my $t (keys %topspamdetail) {
|
||
foreach my $k (keys %{$topspamdetail{$t}}) {
|
||
foreach my $d (keys %{$topspamdetail{$t}{$k}}) {
|
||
$localtopspamdetail{$t}{$k}{$d} += $topspamdetail{$t}{$k}{$d} || 0;
|
||
}
|
||
}
|
||
}
|
||
%topspamdetail = ();
|
||
|
||
foreach my $k (keys %topauth) {
|
||
foreach my $d (keys %{$topauth{$k}}) {
|
||
$localtopauth{$k}{$d} += $topauth{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topauth = ();
|
||
|
||
foreach my $k (keys %starttls) {
|
||
$localstarttls{$k} += $starttls{$k};
|
||
}
|
||
%starttls = ();
|
||
}
|
||
}
|
||
my %authval = ();
|
||
foreach my $day ("01" .. "31") {
|
||
foreach my $t (keys %localauth) {
|
||
$authval{$t} .= ($localauth{$t}{values}{"$day"} || 0) . ':';
|
||
}
|
||
}
|
||
foreach my $t (keys %localauth) {
|
||
delete $localauth{$t}{values};
|
||
$localauth{$t}{values} = $authval{$t};
|
||
$localauth{$t}{lbls} =~ s/:$//;
|
||
$localauth{$t}{values} =~ s/:$//;
|
||
}
|
||
|
||
$lbls =~ s/:$//;
|
||
$localmessaging{values} =~ s/:$//;
|
||
$localmessaging{values1} =~ s/:$//;
|
||
$localmessaging{values_bytes} =~ s/:$//;
|
||
$localmessaging{values1_bytes} =~ s/:$//;
|
||
$localspam{values} =~ s/:$//;
|
||
$localvirus{values} =~ s/:$//;
|
||
$localdsn{values} =~ s/:$//;
|
||
$localmessaging{nbrcpt} =~ s/:$//;
|
||
$localmessaging{nbsender} =~ s/:$//;
|
||
|
||
my $file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/cache.pm\U$DOMAIN\E";
|
||
|
||
print "Writing cache file: $file\n" if ($CONFIG{DEBUG});
|
||
|
||
if (open(OUT, ">$file")) {
|
||
print OUT "\%::auth = (\n";
|
||
foreach my $type (keys %localauth) {
|
||
print OUT "'$type' => {";
|
||
print OUT "'values' => '$localauth{$type}{values}',";
|
||
print OUT "'lbls' => '$lbls',";
|
||
print OUT "'x_label' => 'Month of the year',";
|
||
foreach my $mech (keys %{$localauth{$type}}) {
|
||
next if (grep(/^$mech$/,'lbls','x_label','values'));
|
||
print OUT "'$mech' => '$localauth{$type}{$mech}',";
|
||
}
|
||
print OUT "},\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localauth = ();
|
||
print OUT "\%::messaging = (\n";
|
||
print OUT "'inbound' => '$localmessaging{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localmessaging{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localmessaging{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localmessaging{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localmessaging{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localmessaging{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localmessaging{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localmessaging{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localmessaging{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localmessaging{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localmessaging{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localmessaging{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'values' => '$localmessaging{values}',\n";
|
||
print OUT "'values1' => '$localmessaging{values1}',\n";
|
||
print OUT "'values_bytes' => '$localmessaging{values_bytes}',\n";
|
||
print OUT "'values1_bytes' => '$localmessaging{values1_bytes}',\n";
|
||
print OUT "'nbsender' => '$localmessaging{nbsender}',\n";
|
||
print OUT "'nbrcpt' => '$localmessaging{nbrcpt}',\n";
|
||
print OUT ");\n\n";
|
||
%localmessaging = ();
|
||
|
||
print OUT "\%::spam = (\n";
|
||
print OUT "'inbound' => '$localspam{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localspam{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localspam{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localspam{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localspam{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localspam{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localspam{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localspam{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localspam{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localspam{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localspam{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localspam{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'values' => '$localspam{values}',\n";
|
||
print OUT "'Ext_Int' => '$localspam{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localspam{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localspam{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localspam{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localspam{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localspam{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localspam{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localspam{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localspam = ();
|
||
|
||
print OUT "\%::reject = (\n";
|
||
print OUT "'inbound' => '$localreject{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localreject{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localreject{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localreject{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localreject{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localreject{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localreject = ();
|
||
|
||
print OUT "\%::postgrey = (\n";
|
||
print OUT "'reason' => {";
|
||
foreach my $k (keys %{$localpostgrey{reason}}) {
|
||
print OUT "\t'$k' => '$localpostgrey{reason}{$k}',";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localpostgrey = ();
|
||
|
||
print OUT "\%::spf_dkim = (\n";
|
||
print OUT "'spf' => {\n";
|
||
foreach my $r (keys %{$localspf_dkim{spf}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$localspf_dkim{spf}{$r}}) {
|
||
print OUT "\t\t'$s' => { ";
|
||
foreach my $v (keys %{$localspf_dkim{spf}{$r}{$s}}) {
|
||
print OUT "'$v' => '$localspf_dkim{spf}{$r}{$s}{$v}',";
|
||
}
|
||
print OUT " },\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT "'dkim' => {\n";
|
||
foreach my $r (keys %{$localspf_dkim{dkim}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$localspf_dkim{dkim}{$r}}) {
|
||
print OUT "\t\t'$s' => '$localspf_dkim{dkim}{$r}{$s}',\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localspf_dkim = ();
|
||
|
||
print OUT "\%::virus = (\n";
|
||
print OUT "'inbound' => '$localvirus{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localvirus{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localvirus{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localvirus{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localvirus{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localvirus{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localvirus{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localvirus{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localvirus{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localvirus{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localvirus{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localvirus{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'values' => '$localvirus{values}',\n";
|
||
print OUT "'Ext_Int' => '$localvirus{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localvirus{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localvirus{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localvirus{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localvirus{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localvirus{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localvirus{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localvirus{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localvirus = ();
|
||
|
||
print OUT "\%::dsn = (\n";
|
||
print OUT "'outbound' => '$localdsn{outbound}',\n";
|
||
print OUT "'local_outbound' => '$localdsn{local_outbound}',\n";
|
||
print OUT "'total_outbound' => '$localdsn{total_outbound}',\n";
|
||
print OUT "'error' => '$localdsn{error}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'values' => '$localdsn{values}',\n";
|
||
print OUT "'Ext_Int' => '$localdsn{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localdsn{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localdsn{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localdsn{Ext_Ext}',\n";
|
||
print OUT ");\n\n";
|
||
%localdsn = ();
|
||
|
||
print OUT "\%::err = (\n";
|
||
print OUT "'inbound' => '$localerr{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localerr{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localerr{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localerr{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localerr{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localerr{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localerr = ();
|
||
|
||
print OUT "\%::GLOBAL_STATUS = (\n";
|
||
foreach my $k (keys %localGLOBAL_STATUS) {
|
||
my $slbl = $k;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "'$slbl' => '$localGLOBAL_STATUS{$k}',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localGLOBAL_STATUS = ();
|
||
|
||
print OUT "\%::starttls = (\n";
|
||
foreach my $v (sort keys %localstarttls) {
|
||
my $slbl = $v;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "'$slbl' => '$localstarttls{$v}',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localstarttls = ();
|
||
|
||
my $elbls = 'Ext -> Int:Ext -> Ext:Int -> Int:Int -> Ext';
|
||
print OUT "\%::delivery = (\n";
|
||
print OUT "'lbls' => '$elbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'Ext_Int' => '$localdelivery{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localdelivery{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localdelivery{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localdelivery{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localdelivery{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localdelivery{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localdelivery{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localdelivery{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localdelivery = ();
|
||
|
||
# Top SMTP Auth statistics
|
||
my $top = 0;
|
||
print OUT "\%::topauth = (\n";
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopauth{relay}{$b} <=> $localtopauth{relay}{$a} } keys %{$localtopauth{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopauth{relay};
|
||
$top = 0;
|
||
print OUT "'mech' => {";
|
||
foreach my $d (sort { $localtopauth{mech}{$b} <=> $localtopauth{mech}{$a} } keys %{$localtopauth{mech}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{mech}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopauth{mech};
|
||
$top = 0;
|
||
print OUT "'authid' => {";
|
||
foreach my $d (sort { $localtopauth{authid}{$b} <=> $localtopauth{authid}{$a} } keys %{$localtopauth{authid}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{authid}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopauth = ();
|
||
|
||
# Top sender statistics
|
||
$top = 0;
|
||
print OUT "\%::topsender = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopsender{domain}{$b} <=> $localtopsender{domain}{$a} } keys %{$localtopsender{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopsender{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopsender{relay}{$b} <=> $localtopsender{relay}{$a} } keys %{$localtopsender{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopsender{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $localtopsender{email}{$b} <=> $localtopsender{email}{$a} } keys %{$localtopsender{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopsender = ();
|
||
|
||
# Top recipient statistics
|
||
$top = 0;
|
||
print OUT "\%::toprcpt = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtoprcpt{domain}{$b} <=> $localtoprcpt{domain}{$a} } keys %{$localtoprcpt{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoprcpt{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtoprcpt{relay}{$b} <=> $localtoprcpt{relay}{$a} } keys %{$localtoprcpt{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoprcpt{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $localtoprcpt{email}{$b} <=> $localtoprcpt{email}{$a} } keys %{$localtoprcpt{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtoprcpt = ();
|
||
|
||
# Top rejection statistics
|
||
$top = 0;
|
||
print OUT "\%::topreject = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopreject{rule}{$b} <=> $localtopreject{rule}{$a} } keys %{$localtopreject{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopreject{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopreject{domain}{$b} <=> $localtopreject{domain}{$a} } keys %{$localtopreject{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopreject{relay}{$b} <=> $localtopreject{relay}{$a} } keys %{$localtopreject{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{relay};
|
||
$top = 0;
|
||
print OUT "'chck_status' => {";
|
||
foreach my $d (sort { $localtopreject{chck_status}{$b} <=> $localtopreject{chck_status}{$a} } keys %{$localtopreject{chck_status}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopreject{chck_status}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{chck_status};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopreject{sender}{$b} <=> $localtopreject{sender}{$a} } keys %{$localtopreject{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopreject = ();
|
||
|
||
# Top virus statistics
|
||
$top = 0;
|
||
print OUT "\%::topvirus = (\n";
|
||
print OUT "'virus' => {";
|
||
foreach my $d (sort { $localtopvirus{virus}{$b} <=> $localtopvirus{virus}{$a} } keys %{$localtopvirus{virus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopvirus{virus}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{virus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopvirus{sender}{$b} <=> $localtopvirus{sender}{$a} } keys %{$localtopvirus{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopvirus{relay}{$b} <=> $localtopvirus{relay}{$a} } keys %{$localtopvirus{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{relay};
|
||
$top = 0;
|
||
print OUT "'file' => {";
|
||
foreach my $d (sort { $localtopvirus{file}{$b} <=> $localtopvirus{file}{$a} } keys %{$localtopvirus{file}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{file}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{file};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopvirus{rcpt}{$b} <=> $localtopvirus{rcpt}{$a} } keys %{$localtopvirus{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopvirus = ();
|
||
|
||
# Top dsn statistics
|
||
$top = 0;
|
||
print OUT "\%::topdsn = (\n";
|
||
print OUT "'dsnstatus' => {";
|
||
foreach my $d (sort { $localtopdsn{dsnstatus}{$b} <=> $localtopdsn{dsnstatus}{$a} } keys %{$localtopdsn{dsnstatus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopdsn{dsnstatus}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{dsnstatus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopdsn{sender}{$b} <=> $localtopdsn{sender}{$a} } keys %{$localtopdsn{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopdsn{relay}{$b} <=> $localtopdsn{relay}{$a} } keys %{$localtopdsn{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{relay};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopdsn{rcpt}{$b} <=> $localtopdsn{rcpt}{$a} } keys %{$localtopdsn{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopdsn = ();
|
||
|
||
# Top spam statistics
|
||
$top = 0;
|
||
print OUT "\%::topspam = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopspam{rule}{$b} <=> $localtopspam{rule}{$a} } keys %{$localtopspam{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopspam{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopspam{domain}{$b} <=> $localtopspam{domain}{$a} } keys %{$localtopspam{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{domain};
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $localtopspam{sender_relay}{$b} <=> $localtopspam{sender_relay}{$a} } keys %{$localtopspam{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{sender_relay};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopspam{sender}{$b} <=> $localtopspam{sender}{$a} } keys %{$localtopspam{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{sender};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopspam{rcpt}{$b} <=> $localtopspam{rcpt}{$a} } keys %{$localtopspam{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
print OUT ");\n\n";
|
||
%localtopspam = ();
|
||
|
||
# Top system message statistics
|
||
$top = 0;
|
||
print OUT "\%::toperr = (\n";
|
||
foreach my $m (sort { $localtopspam{$b} <=> $localtopspam{$a} } keys %localtoperr) {
|
||
my $c = $localtoperr{$m};
|
||
$m =~ s/'/\\'/g;
|
||
print OUT "'$m' => $c,\n";
|
||
}
|
||
print OUT ");\n";
|
||
%localtoperr = ();
|
||
|
||
# Top postgrey statistics
|
||
$top = 0;
|
||
print OUT "\%::toppostgrey = (\n";
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtoppostgrey{sender}{$b} <=> $localtoppostgrey{sender}{$a} } keys %{$localtoppostgrey{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{sender};
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $localtoppostgrey{sender_relay}{$b} <=> $localtoppostgrey{sender_relay}{$a} } keys %{$localtoppostgrey{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{sender_relay};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtoppostgrey{domain}{$b} <=> $localtoppostgrey{domain}{$a} } keys %{$localtoppostgrey{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{domain};
|
||
$top = 0;
|
||
print OUT "'reason' => {";
|
||
foreach my $d (sort { $localtoppostgrey{reason}{$b} <=> $localtoppostgrey{reason}{$a} } keys %{$localtoppostgrey{reason}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{reason}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{reason};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtoppostgrey{rcpt}{$b} <=> $localtoppostgrey{rcpt}{$a} } keys %{$localtoppostgrey{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtoppostgrey = ();
|
||
|
||
# Top spam detail statistics
|
||
$top = 0;
|
||
print OUT "\%::topspamdetail = (\n";
|
||
foreach my $t (sort keys %localtopspamdetail) {
|
||
print OUT "'$t' => {";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{rule}{$b} <=> $localtopspamdetail{$t}{rule}{$a} } keys %{$localtopspamdetail{$t}{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopspamdetail{$t}{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{rule};
|
||
$top = 0;
|
||
print OUT "'score' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{score}{$b} <=> $localtopspamdetail{$t}{score}{$a} } keys %{$localtopspamdetail{$t}{score}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{score}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{score};
|
||
$top = 0;
|
||
print OUT "'cache' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{cache}{$b} <=> $localtopspamdetail{$t}{cache}{$a} } keys %{$localtopspamdetail{$t}{cache}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{cache}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{cache};
|
||
$top = 0;
|
||
print OUT "'autolearn' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{autolearn}{$b} <=> $localtopspamdetail{$t}{autolearn}{$a} } keys %{$localtopspamdetail{$t}{autolearn}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{autolearn}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{autolearn};
|
||
$top = 0;
|
||
print OUT "},";
|
||
}
|
||
print OUT ");\n";
|
||
close(OUT);
|
||
} else {
|
||
&logerror("can't write cache file $file: $!");
|
||
}
|
||
|
||
}
|
||
|
||
####
|
||
# Year cache statistics
|
||
####
|
||
sub do_year_cache
|
||
{
|
||
my ($hostname, $DOMAIN, $year, $curyear) = @_;
|
||
|
||
|
||
if (-e "$CONFIG{OUT_DIR}/$hostname/$year/cache.pm\U$DOMAIN\E" && ($year < $curyear)) {
|
||
return;
|
||
}
|
||
|
||
print "Reading statistics from $CONFIG{OUT_DIR}/$hostname/$year/\n" if ($CONFIG{DEBUG});
|
||
|
||
my %localtopsender = ();
|
||
my %localtoprcpt = ();
|
||
my %localtopspam = ();
|
||
my %localtopvirus = ();
|
||
my %localtopdsn = ();
|
||
my %localtopreject = ();
|
||
my %localtoperr = ();
|
||
my %localdelivery = ();
|
||
my %localmessaging = ();
|
||
my %localspam = ();
|
||
my %localvirus = ();
|
||
my %localdsn = ();
|
||
my %localreject = ();
|
||
my %localerr = ();
|
||
my %localGLOBAL_STATUS = ();
|
||
my %localtopspamdetail = ();
|
||
my %localauth = ();
|
||
my %localtopauth = ();
|
||
my %localpostgrey = ();
|
||
my %localtoppostgrey = ();
|
||
my %localstarttls = ();
|
||
my %localspf_dkim = ();
|
||
my $lbls = '';
|
||
|
||
foreach my $month ("01" .. "12") {
|
||
$lbls .= "$month:";
|
||
if (!-e "$CONFIG{OUT_DIR}/$hostname/$year/$month/cache.pm\U$DOMAIN\E") {
|
||
$localmessaging{values} .= '0:';
|
||
$localmessaging{values1} .= '0:';
|
||
$localmessaging{values_bytes} .= '0:';
|
||
$localmessaging{values1_bytes} .= '0:';
|
||
$localspam{values} .= '0:';
|
||
$localvirus{values} .= '0:';
|
||
$localdsn{values} .= '0:';
|
||
$localmessaging{nbsender} .= '0:';
|
||
$localmessaging{nbrcpt} .= '0:';
|
||
next;
|
||
} else {
|
||
&clean_globals();
|
||
my $file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/cache.pm\U$DOMAIN\E";
|
||
print "Loading cache statistics from $file\n" if ($CONFIG{DEBUG});
|
||
do "$file";
|
||
foreach my $k (keys %messaging) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values','values1','values_bytes','values1_bytes','nbsender','nbrcpt')) {
|
||
$localmessaging{$k} += $messaging{$k};
|
||
}
|
||
}
|
||
$localmessaging{values} .= ($messaging{inbound} || 0) . ':';
|
||
$localmessaging{values1} .= ($messaging{outbound} || 0) . ':';
|
||
$localmessaging{values_bytes} .= ($messaging{inbound_bytes} || 0) . ':';
|
||
$localmessaging{values1_bytes} .= ($messaging{outbound_bytes} || 0) . ':';
|
||
my $tmp = 0;
|
||
foreach (split(/:/, $messaging{nbsender})) {
|
||
$tmp += $_;
|
||
}
|
||
$localmessaging{nbsender} .= $tmp . ':';
|
||
$tmp = 0;
|
||
foreach (split(/:/, $messaging{nbrcpt})) {
|
||
$tmp += $_;
|
||
}
|
||
$localmessaging{nbrcpt} .= $tmp . ':';
|
||
%messaging = ();
|
||
|
||
foreach my $t (keys %auth) {
|
||
foreach my $m (keys %{$auth{$t}}) {
|
||
if (!grep(/^$m$/, 'lbls','x_label','values')) {
|
||
$localauth{$t}{$m} += $auth{$t}{$m};
|
||
$localauth{$t}{values}{"$month"} += $auth{$t}{$m};
|
||
}
|
||
}
|
||
}
|
||
%auth = ();
|
||
|
||
foreach my $k (keys %spam) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localspam{$k} += $spam{$k};
|
||
}
|
||
}
|
||
$localspam{values} .= ($spam{inbound} || 0) . ':';
|
||
%spam = ();
|
||
foreach my $k (keys %reject) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localreject{$k} += $reject{$k};
|
||
}
|
||
}
|
||
%reject = ();
|
||
foreach my $k (keys %{$postgrey{reason}}) {
|
||
$localpostgrey{reason}{$k} += $postgrey{reason}{$k};
|
||
}
|
||
%postgrey = ();
|
||
|
||
foreach my $r (keys %{$spf_dkim{spf}}) {
|
||
foreach my $k (keys %{$spf_dkim{spf}{$r}{status}}) {
|
||
$localspf_dkim{spf}{$r}{status}{$k} += $spf_dkim{spf}{$r}{status}{$k};
|
||
}
|
||
foreach my $k (keys %{$spf_dkim{spf}{$r}{domain}}) {
|
||
$localspf_dkim{spf}{$r}{domain}{$k} += $spf_dkim{spf}{$r}{domain}{$k};
|
||
}
|
||
}
|
||
foreach my $r (keys %{$spf_dkim{dkim}{status}}) {
|
||
$localspf_dkim{dkim}{status}{$r} += $spf_dkim{dkim}{status}{$r};
|
||
}
|
||
%spf_dkim = ();
|
||
|
||
foreach my $k (keys %virus) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localvirus{$k} += $virus{$k};
|
||
}
|
||
}
|
||
$localvirus{values} .= ($virus{inbound} || 0) . ':';
|
||
%virus = ();
|
||
foreach my $k (keys %dsn) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localdsn{$k} += $dsn{$k};
|
||
}
|
||
}
|
||
$localdsn{values} .= ($dsn{outbound} || 0) . ':';
|
||
%dsn = ();
|
||
foreach my $k (keys %err) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localerr{$k} += $err{$k};
|
||
}
|
||
}
|
||
%err = ();
|
||
foreach my $k (keys %GLOBAL_STATUS) {
|
||
$localGLOBAL_STATUS{$k} += $GLOBAL_STATUS{$k};
|
||
}
|
||
%GLOBAL_STATUS = ();
|
||
foreach my $k (keys %delivery) {
|
||
if (!grep(/^$k$/, 'lbls','x_label')) {
|
||
$localdelivery{$k} += $delivery{$k};
|
||
}
|
||
}
|
||
|
||
foreach my $k (keys %topsender) {
|
||
foreach my $d (keys %{$topsender{$k}}) {
|
||
$localtopsender{$k}{$d} += $topsender{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topsender = ();
|
||
|
||
foreach my $k (keys %toprcpt) {
|
||
foreach my $d (keys %{$toprcpt{$k}}) {
|
||
$localtoprcpt{$k}{$d} += $toprcpt{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%toprcpt = ();
|
||
|
||
foreach my $k (keys %topreject) {
|
||
foreach my $d (keys %{$topreject{$k}}) {
|
||
$localtopreject{$k}{$d} += $topreject{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topreject = ();
|
||
|
||
foreach my $k (keys %topvirus) {
|
||
foreach my $d (keys %{$topvirus{$k}}) {
|
||
$localtopvirus{$k}{$d} += $topvirus{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topvirus = ();
|
||
|
||
foreach my $k (keys %topdsn) {
|
||
foreach my $d (keys %{$topdsn{$k}}) {
|
||
$localtopdsn{$k}{$d} += $topdsn{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topdsn = ();
|
||
|
||
foreach my $k (keys %topspam) {
|
||
foreach my $d (keys %{$topspam{$k}}) {
|
||
$localtopspam{$k}{$d} += $topspam{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topspam = ();
|
||
|
||
foreach my $k (keys %toperr) {
|
||
$localtoperr{$k} += $toperr{$k} || 0;
|
||
}
|
||
%toperr = ();
|
||
foreach my $k (keys %toppostgrey) {
|
||
foreach my $d (keys %{$toppostgrey{$k}}) {
|
||
$localtoppostgrey{$k}{$d} += $toppostgrey{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%toppostgrey = ();
|
||
foreach my $t (keys %topspamdetail) {
|
||
foreach my $k (keys %{$topspamdetail{$t}}) {
|
||
foreach my $d (keys %{$topspamdetail{$t}{$k}}) {
|
||
$localtopspamdetail{$t}{$k}{$d} += $topspamdetail{$t}{$k}{$d} || 0;
|
||
}
|
||
}
|
||
}
|
||
%topspamdetail = ();
|
||
|
||
foreach my $k (keys %topauth) {
|
||
foreach my $d (keys %{$topauth{$k}}) {
|
||
$localtopauth{$k}{$d} += $topauth{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topauth = ();
|
||
|
||
foreach my $k (keys %starttls) {
|
||
$localstarttls{$k} += $starttls{$k};
|
||
}
|
||
%starttls = ();
|
||
}
|
||
}
|
||
|
||
my %authval = ();
|
||
foreach my $month ("01" .. "12") {
|
||
foreach my $t (keys %localauth) {
|
||
$authval{$t} .= ($localauth{$t}{values}{"$month"} || 0) . ':';
|
||
}
|
||
}
|
||
foreach my $t (keys %localauth) {
|
||
delete $localauth{$t}{values};
|
||
$localauth{$t}{values} = $authval{$t};
|
||
$localauth{$t}{lbls} =~ s/:$//;
|
||
$localauth{$t}{values} =~ s/:$//;
|
||
}
|
||
|
||
$lbls =~ s/:$//;
|
||
$localmessaging{values} =~ s/:$//;
|
||
$localmessaging{values1} =~ s/:$//;
|
||
$localmessaging{values_bytes} =~ s/:$//;
|
||
$localmessaging{values1_bytes} =~ s/:$//;
|
||
$localspam{values} =~ s/:$//;
|
||
$localvirus{values} =~ s/:$//;
|
||
$localdsn{values} =~ s/:$//;
|
||
$localmessaging{nbsender} =~ s/:$//;
|
||
$localmessaging{nbrcpt} =~ s/:$//;
|
||
|
||
|
||
|
||
my $file = "$CONFIG{OUT_DIR}/$hostname/$year/cache.pm\U$DOMAIN\E";
|
||
|
||
print "Writing cache file: $file\n" if ($CONFIG{DEBUG});
|
||
|
||
if (open(OUT, ">$file")) {
|
||
print OUT "\%::auth = (\n";
|
||
foreach my $type (keys %localauth) {
|
||
print OUT "'$type' => {\n";
|
||
print OUT "\t'values' => '$localauth{$type}{values}',\n";
|
||
print OUT "\t'lbls' => '$lbls',\n";
|
||
print OUT "\t'x_label' => 'Month of the year',\n";
|
||
foreach my $mech (keys %{$localauth{$type}}) {
|
||
next if (grep(/^$mech$/,'lbls','x_label','values'));
|
||
print OUT "\t'$mech' => '$localauth{$type}{$mech}',\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localauth = ();
|
||
print OUT "\%::messaging = (\n";
|
||
print OUT "'inbound' => '$localmessaging{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localmessaging{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localmessaging{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localmessaging{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localmessaging{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localmessaging{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localmessaging{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localmessaging{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localmessaging{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localmessaging{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localmessaging{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localmessaging{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'values' => '$localmessaging{values}',\n";
|
||
print OUT "'values1' => '$localmessaging{values1}',\n";
|
||
print OUT "'values_bytes' => '$localmessaging{values_bytes}',\n";
|
||
print OUT "'values1_bytes' => '$localmessaging{values1_bytes}',\n";
|
||
print OUT "'nbsender' => '$localmessaging{nbsender}',\n";
|
||
print OUT "'nbrcpt' => '$localmessaging{nbrcpt}',\n";
|
||
print OUT ");\n\n";
|
||
%localmessaging = ();
|
||
|
||
print OUT "\%::spam = (\n";
|
||
print OUT "'inbound' => '$localspam{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localspam{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localspam{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localspam{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localspam{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localspam{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localspam{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localspam{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localspam{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localspam{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localspam{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localspam{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'values' => '$localspam{values}',\n";
|
||
print OUT "'Ext_Int' => '$localspam{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localspam{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localspam{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localspam{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localspam{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localspam{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localspam{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localspam{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localspam = ();
|
||
|
||
print OUT "\%::reject = (\n";
|
||
print OUT "'inbound' => '$localreject{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localreject{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localreject{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localreject{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localreject{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localreject{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localreject = ();
|
||
|
||
print OUT "\%::postgrey = (\n";
|
||
print OUT "'reason' => {";
|
||
foreach my $k (keys %{$localpostgrey{reason}}) {
|
||
print OUT "\t'$k' => '$localpostgrey{reason}{$k}',";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localpostgrey = ();
|
||
|
||
print OUT "\%::spf_dkim = (\n";
|
||
print OUT "'spf' => {\n";
|
||
foreach my $r (keys %{$localspf_dkim{spf}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$localspf_dkim{spf}{$r}}) {
|
||
print OUT "\t\t'$s' => { ";
|
||
foreach my $v (keys %{$localspf_dkim{spf}{$r}{$s}}) {
|
||
print OUT "'$v' => '$localspf_dkim{spf}{$r}{$s}{$v}',";
|
||
}
|
||
print OUT " },\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT "'dkim' => {\n";
|
||
foreach my $r (keys %{$localspf_dkim{dkim}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$localspf_dkim{dkim}{$r}}) {
|
||
print OUT "\t\t'$s' => '$localspf_dkim{dkim}{$r}{$s}',\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localspf_dkim = ();
|
||
|
||
print OUT "\%::virus = (\n";
|
||
print OUT "'inbound' => '$localvirus{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localvirus{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localvirus{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localvirus{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localvirus{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localvirus{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localvirus{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localvirus{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localvirus{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localvirus{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localvirus{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localvirus{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'values' => '$localvirus{values}',\n";
|
||
print OUT "'Ext_Int' => '$localvirus{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localvirus{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localvirus{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localvirus{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localvirus{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localvirus{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localvirus{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localvirus{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localvirus = ();
|
||
|
||
print OUT "\%::dsn = (\n";
|
||
print OUT "'outbound' => '$localdsn{outbound}',\n";
|
||
print OUT "'local_outbound' => '$localdsn{local_outbound}',\n";
|
||
print OUT "'total_outbound' => '$localdsn{total_outbound}',\n";
|
||
print OUT "'error' => '$localdsn{error}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'values' => '$localdsn{values}',\n";
|
||
print OUT "'Ext_Int' => '$localdsn{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localdsn{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localdsn{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localdsn{Ext_Ext}',\n";
|
||
print OUT ");\n\n";
|
||
%localdsn = ();
|
||
|
||
print OUT "\%::err = (\n";
|
||
print OUT "'inbound' => '$localerr{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localerr{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localerr{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localerr{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localerr{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localerr{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localerr = ();
|
||
|
||
print OUT "\%::GLOBAL_STATUS = (\n";
|
||
foreach my $k (keys %localGLOBAL_STATUS) {
|
||
my $slbl = $k;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "'$k' => '$localGLOBAL_STATUS{$k}',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localGLOBAL_STATUS = ();
|
||
|
||
print OUT "\%::starttls = (\n";
|
||
foreach my $v (sort keys %localstarttls) {
|
||
my $slbl = $v;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "'$slbl' => '$localstarttls{$v}',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localstarttls = ();
|
||
|
||
my $elbls = 'Ext -> Int:Ext -> Ext:Int -> Int:Int -> Ext';
|
||
print OUT "\%::delivery = (\n";
|
||
print OUT "'lbls' => '$elbls',\n";
|
||
print OUT "'x_label' => 'Month of the year',\n";
|
||
print OUT "'Ext_Int' => '$localdelivery{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localdelivery{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localdelivery{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localdelivery{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localdelivery{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localdelivery{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localdelivery{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localdelivery{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localdelivery = ();
|
||
|
||
# Top SMTP Auth statistics
|
||
my $top = 0;
|
||
print OUT "\%::topauth = (\n";
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopauth{relay}{$b} <=> $localtopauth{relay}{$a} } keys %{$localtopauth{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopauth{relay};
|
||
$top = 0;
|
||
print OUT "'mech' => {";
|
||
foreach my $d (sort { $localtopauth{mech}{$b} <=> $localtopauth{mech}{$a} } keys %{$localtopauth{mech}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{mech}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopauth{mech};
|
||
$top = 0;
|
||
print OUT "'authid' => {";
|
||
foreach my $d (sort { $localtopauth{authid}{$b} <=> $localtopauth{authid}{$a} } keys %{$localtopauth{authid}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{authid}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopauth = ();
|
||
|
||
# Top sender statistics
|
||
$top = 0;
|
||
print OUT "\%::topsender = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopsender{domain}{$b} <=> $localtopsender{domain}{$a} } keys %{$localtopsender{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopsender{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopsender{relay}{$b} <=> $localtopsender{relay}{$a} } keys %{$localtopsender{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopsender{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $localtopsender{email}{$b} <=> $localtopsender{email}{$a} } keys %{$localtopsender{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopsender = ();
|
||
|
||
# Top recipient statistics
|
||
$top = 0;
|
||
print OUT "\%::toprcpt = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtoprcpt{domain}{$b} <=> $localtoprcpt{domain}{$a} } keys %{$localtoprcpt{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoprcpt{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtoprcpt{relay}{$b} <=> $localtoprcpt{relay}{$a} } keys %{$localtoprcpt{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoprcpt{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $localtoprcpt{email}{$b} <=> $localtoprcpt{email}{$a} } keys %{$localtoprcpt{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtoprcpt = ();
|
||
|
||
# Top rejection statistics
|
||
$top = 0;
|
||
print OUT "\%::topreject = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopreject{rule}{$b} <=> $localtopreject{rule}{$a} } keys %{$localtopreject{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopreject{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopreject{domain}{$b} <=> $localtopreject{domain}{$a} } keys %{$localtopreject{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopreject{relay}{$b} <=> $localtopreject{relay}{$a} } keys %{$localtopreject{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{relay};
|
||
$top = 0;
|
||
print OUT "'chck_status' => {";
|
||
foreach my $d (sort { $localtopreject{chck_status}{$b} <=> $localtopreject{chck_status}{$a} } keys %{$localtopreject{chck_status}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopreject{chck_status}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{chck_status};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopreject{sender}{$b} <=> $localtopreject{sender}{$a} } keys %{$localtopreject{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopreject = ();
|
||
|
||
# Top virus statistics
|
||
$top = 0;
|
||
print OUT "\%::topvirus = (\n";
|
||
print OUT "'virus' => {";
|
||
foreach my $d (sort { $localtopvirus{virus}{$b} <=> $localtopvirus{virus}{$a} } keys %{$localtopvirus{virus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{virus}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{virus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopvirus{sender}{$b} <=> $localtopvirus{sender}{$a} } keys %{$localtopvirus{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopvirus{relay}{$b} <=> $localtopvirus{relay}{$a} } keys %{$localtopvirus{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{relay};
|
||
$top = 0;
|
||
print OUT "'file' => {";
|
||
foreach my $d (sort { $localtopvirus{file}{$b} <=> $localtopvirus{file}{$a} } keys %{$localtopvirus{file}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{file}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{file};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopvirus{rcpt}{$b} <=> $localtopvirus{rcpt}{$a} } keys %{$localtopvirus{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopvirus = ();
|
||
|
||
# Top dsn statistics
|
||
$top = 0;
|
||
print OUT "\%::topdsn = (\n";
|
||
print OUT "'dsnstatus' => {";
|
||
foreach my $d (sort { $localtopdsn{dsnstatus}{$b} <=> $localtopdsn{dsnstatus}{$a} } keys %{$localtopdsn{dsnstatus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{dsnstatus}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{dsnstatus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopdsn{sender}{$b} <=> $localtopdsn{sender}{$a} } keys %{$localtopdsn{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopdsn{relay}{$b} <=> $localtopdsn{relay}{$a} } keys %{$localtopdsn{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{relay};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopdsn{rcpt}{$b} <=> $localtopdsn{rcpt}{$a} } keys %{$localtopdsn{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopdsn = ();
|
||
|
||
# Top spam statistics
|
||
$top = 0;
|
||
print OUT "\%::topspam = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopspam{rule}{$b} <=> $localtopspam{rule}{$a} } keys %{$localtopspam{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{rule}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopspam{domain}{$b} <=> $localtopspam{domain}{$a} } keys %{$localtopspam{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{domain};
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $localtopspam{sender_relay}{$b} <=> $localtopspam{sender_relay}{$a} } keys %{$localtopspam{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{sender_relay};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopspam{sender}{$b} <=> $localtopspam{sender}{$a} } keys %{$localtopspam{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{sender};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopspam{rcpt}{$b} <=> $localtopspam{rcpt}{$a} } keys %{$localtopspam{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
print OUT ");\n\n";
|
||
%localtopspam = ();
|
||
# Top system message statistics
|
||
$top = 0;
|
||
print OUT "\%::toperr = (\n";
|
||
foreach my $m ( keys %localtoperr) {
|
||
my $c = $localtoperr{$m};
|
||
$m =~ s/'/\\'/g;
|
||
print OUT "'$m' => '$c',\n";
|
||
}
|
||
print OUT ");\n";
|
||
%toperr = ();
|
||
|
||
# Top postgrey statistics
|
||
$top = 0;
|
||
print OUT "\%::toppostgrey = (\n";
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtoppostgrey{sender}{$b} <=> $localtoppostgrey{sender}{$a} } keys %{$localtoppostgrey{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{sender};
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $localtoppostgrey{sender_relay}{$b} <=> $localtoppostgrey{sender_relay}{$a} } keys %{$localtoppostgrey{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{sender_relay};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtoppostgrey{domain}{$b} <=> $localtoppostgrey{domain}{$a} } keys %{$localtoppostgrey{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{domain};
|
||
$top = 0;
|
||
print OUT "'reason' => {";
|
||
foreach my $d (sort { $localtoppostgrey{reason}{$b} <=> $localtoppostgrey{reason}{$a} } keys %{$localtoppostgrey{reason}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{reason}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{reason};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtoppostgrey{rcpt}{$b} <=> $localtoppostgrey{rcpt}{$a} } keys %{$localtoppostgrey{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtoppostgrey = ();
|
||
|
||
# Top spam detail statistics
|
||
$top = 0;
|
||
print OUT "\%::topspamdetail = (\n";
|
||
foreach my $t (sort keys %localtopspamdetail) {
|
||
print OUT "'$t' => {";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{rule}{$b} <=> $localtopspamdetail{$t}{rule}{$a} } keys %{$localtopspamdetail{$t}{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopspamdetail{$t}{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{rule};
|
||
$top = 0;
|
||
print OUT "'score' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{score}{$b} <=> $localtopspamdetail{$t}{score}{$a} } keys %{$localtopspamdetail{$t}{score}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{score}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{score};
|
||
$top = 0;
|
||
print OUT "'cache' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{cache}{$b} <=> $localtopspamdetail{$t}{cache}{$a} } keys %{$localtopspamdetail{$t}{cache}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{cache}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{cache};
|
||
$top = 0;
|
||
print OUT "'autolearn' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{autolearn}{$b} <=> $localtopspamdetail{$t}{autolearn}{$a} } keys %{$localtopspamdetail{$t}{autolearn}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{autolearn}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{autolearn};
|
||
$top = 0;
|
||
print OUT "},";
|
||
}
|
||
print OUT ");\n\n";
|
||
close(OUT);
|
||
} else {
|
||
&logerror("can't write cache file $file: $!");
|
||
}
|
||
|
||
}
|
||
|
||
sub set_direction
|
||
{
|
||
my ($sender_relay, $recipient_relay, $hostname) = @_;
|
||
|
||
# By default all mail are considered issued from local computer.
|
||
my $direction = 'Int_';
|
||
|
||
###### Check for sender origine
|
||
if ($sender_relay) {
|
||
# This host is a gateway and it forward mails to an internal hub or outside
|
||
if (!$CONFIG{MAIL_GW} && $CONFIG{MAIL_HUB}) {
|
||
if (!grep($sender_relay =~ /$_/i, split(/[\s\t,;]/, $CONFIG{MAIL_HUB}))) {
|
||
# if message doesn't come from localhost or user defined loca relay it comes from outside
|
||
if (exists $CONFIG{LOCAL_HOST_DOMAIN}{$hostname} && ($#{$CONFIG{LOCAL_HOST_DOMAIN}{$hostname}} > -1) ) {
|
||
$direction = 'Ext_' if (!grep($sender_relay =~ /\b$_$/, 'localhost', @{$CONFIG{LOCAL_HOST_DOMAIN}{$hostname}}));
|
||
} elsif (exists $CONFIG{LOCAL_DOMAIN} && ($#{$CONFIG{LOCAL_DOMAIN}} > -1)) {
|
||
$direction = 'Ext_' if (!grep($sender_relay =~ /\b$_$/, 'localhost', @{$CONFIG{LOCAL_DOMAIN}}));
|
||
}
|
||
}
|
||
# This host received all messages from a gateway
|
||
} elsif ($CONFIG{MAIL_GW} && !$CONFIG{MAIL_HUB}) {
|
||
# If sender relay is the gateway, it comes from outside
|
||
$direction = 'Ext_' if (grep($sender_relay =~ /$_/i, split(/[\s\t,;]/, $CONFIG{MAIL_GW}) ));
|
||
# This host is a hub, it received all messages from a gateway and forward them to other host
|
||
} elsif ($CONFIG{MAIL_GW} && $CONFIG{MAIL_HUB}) {
|
||
# If sender relay is the gateway, it comes from outside
|
||
$direction = 'Ext_' if (grep($sender_relay =~ /$_/i, split(/[\s\t,;]/, $CONFIG{MAIL_GW})));
|
||
} else {
|
||
# if message doesn't come from localhost or user defined loca relay it comes from outside
|
||
if (exists $CONFIG{LOCAL_HOST_DOMAIN}{$hostname} && ($#{$CONFIG{LOCAL_HOST_DOMAIN}{$hostname}} > -1) ) {
|
||
$direction = 'Ext_' if (!grep($sender_relay =~ /\b$_$/, 'localhost', @{$CONFIG{LOCAL_HOST_DOMAIN}{$hostname}}));
|
||
} elsif (exists $CONFIG{LOCAL_DOMAIN} && ($#{$CONFIG{LOCAL_DOMAIN}} > -1)) {
|
||
$direction = 'Ext_' if (!grep($sender_relay =~ /\b$_$/, 'localhost', @{$CONFIG{LOCAL_DOMAIN}}));
|
||
}
|
||
}
|
||
} else {
|
||
$direction = 'Unk_';
|
||
}
|
||
|
||
###### Now check for destination
|
||
if ($recipient_relay) {
|
||
# If the recipient relay is localhost, it should be distributed internally
|
||
if ($recipient_relay eq 'localhost') {
|
||
$direction .= 'Int';
|
||
# If this host is a mail gateway and the recipient relay match one of
|
||
# our destination hub lets say it should be distributed internally
|
||
} elsif ($CONFIG{MAIL_HUB} && (grep($recipient_relay =~ /$_/, split(/[\s\t,;]/, $CONFIG{MAIL_HUB}) )) ) {
|
||
$direction .= 'Int';
|
||
# If the recipient relay match any of our local domain
|
||
# lets say the mail should be distributed internally
|
||
} elsif (exists $CONFIG{LOCAL_HOST_DOMAIN}{$hostname} && ($#{$CONFIG{LOCAL_HOST_DOMAIN}{$hostname}} > -1) ){
|
||
if (grep($recipient_relay =~ /\b$_$/i, @{$CONFIG{LOCAL_HOST_DOMAIN}{$hostname}})) {
|
||
$direction .= 'Int';
|
||
} else {
|
||
$direction .= 'Ext';
|
||
}
|
||
} elsif (exists $CONFIG{LOCAL_DOMAIN} && ($#{$CONFIG{LOCAL_DOMAIN}} > -1)) {
|
||
if (grep($recipient_relay =~ /\b$_$/i, @{$CONFIG{LOCAL_DOMAIN}})) {
|
||
$direction .= 'Int';
|
||
} else {
|
||
$direction .= 'Ext';
|
||
}
|
||
# Finally his only way is to go outside
|
||
} else {
|
||
$direction .= 'Ext';
|
||
}
|
||
} else {
|
||
$direction .= 'Unk';
|
||
}
|
||
|
||
return $direction;
|
||
}
|
||
|
||
####
|
||
# Die cleanly on signal
|
||
####
|
||
sub terminate
|
||
{
|
||
&dprint("Received terminating signal.");
|
||
unlink("$CONFIG{PID_DIR}/$PID_FILE");
|
||
exit 0;
|
||
}
|
||
|
||
sub clear_postfix
|
||
{
|
||
my $str = shift;
|
||
|
||
# POSTFIX: Skip connect/disconnect message
|
||
if ($str =~ m#^(DIS)?CONNECT #i) {
|
||
return 1;
|
||
# POSTFIX temporary blacklist/whitelist messsage
|
||
} elsif ($str =~ m#^(PASS OLD|PASS NEW|WHITELISTED|BLACKLISTED)#i) {
|
||
return 1;
|
||
# POSTFIX pregreet test
|
||
} elsif ($str =~ m#^(PREGREET|HANGUP)#i) {
|
||
return 1;
|
||
# POSTFIX dnsbl message
|
||
} elsif ($str =~ m#^DNSBL rank#i) {
|
||
return 1;
|
||
# POSTFIX dnsbl message ???
|
||
} elsif ($str =~ m#addr \d+\.\d+\.\d+\.\d+ listed#i) {
|
||
return 1;
|
||
# POSTFIX postscreen error message: COMMAND (PIPELINING|COUNT LIMIT|TIME LIMIT)???
|
||
} elsif ($str =~ m#^COMMAND #i) {
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
|
||
####
|
||
# Weekly cache statistics
|
||
####
|
||
sub do_week_cache
|
||
{
|
||
my ($hostname, $DOMAIN, $year, $curyear, $week, $curweek) = @_;
|
||
|
||
if (!$DOMAIN && -e "$CONFIG{OUT_DIR}/$hostname/$year/weeks/$week/cache.pm" && ("$year$week" < "$curyear$curweek")) {
|
||
if ($CONFIG{WEEKLY_FREE_SPACE}) {
|
||
my @days = &get_week_boundaries($year, $week);
|
||
map { s/^/$CONFIG{OUT_DIR}\/$hostname\//; } @days;
|
||
# reduce disk space storage by deleting or archiving data file
|
||
&free_space_week("$CONFIG{OUT_DIR}/$hostname/$year/weeks/$week", @days);
|
||
return;
|
||
}
|
||
}
|
||
|
||
# This cache have been already build
|
||
if (-e "$CONFIG{OUT_DIR}/$hostname/$year/weeks/$week/cache.pm\U$DOMAIN\E" && ("$year$week" < "$curyear$curweek")) {
|
||
return;
|
||
}
|
||
|
||
print "Reading statistics from $CONFIG{OUT_DIR}/$hostname/$year/weeks/$week\n" if ($CONFIG{DEBUG});
|
||
|
||
my %localtopsender = ();
|
||
my %localtoprcpt = ();
|
||
my %localtopspam = ();
|
||
my %localtopvirus = ();
|
||
my %localtopdsn = ();
|
||
my %localtopreject = ();
|
||
my %localtoperr = ();
|
||
my %localdelivery = ();
|
||
my %localmessaging = ();
|
||
my %localspam = ();
|
||
my %localvirus = ();
|
||
my %localdsn = ();
|
||
my %localreject = ();
|
||
my %localerr = ();
|
||
my %localGLOBAL_STATUS = ();
|
||
my %localtopspamdetail = ();
|
||
my %localauth = ();
|
||
my %localtopauth = ();
|
||
my %localpostgrey = ();
|
||
my %localtoppostgrey = ();
|
||
my %localstarttls = ();
|
||
my %localspf_dkim = ();
|
||
my $lbls = '';
|
||
my %authval = ();
|
||
&clean_globals();
|
||
my @days = &get_week_boundaries($year, $week);
|
||
foreach my $path (@days) {
|
||
$path =~ /\/(\d+)$/;
|
||
my $day = "$1";
|
||
$lbls .= "$day:";
|
||
if (!-e "$CONFIG{OUT_DIR}/$hostname/$path/cache.pm\U$DOMAIN\E") {
|
||
$localmessaging{values} .= '0:';
|
||
$localmessaging{values1} .= '0:';
|
||
$localmessaging{values_bytes} .= '0:';
|
||
$localmessaging{values1_bytes} .= '0:';
|
||
$localspam{values} .= '0:';
|
||
$localvirus{values} .= '0:';
|
||
$localdsn{values} .= '0:';
|
||
$localmessaging{nbsender} .= '0:';
|
||
$localmessaging{nbrcpt} .= '0:';
|
||
next;
|
||
} else {
|
||
my $file = "$CONFIG{OUT_DIR}/$hostname/$path/cache.pm\U$DOMAIN\E";
|
||
print "Loading cache statistics from $file\n" if ($CONFIG{DEBUG});
|
||
do "$file";
|
||
foreach my $k (keys %messaging) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values','values1','values_bytes','values1_bytes','nbsender','nbrcpt')) {
|
||
$localmessaging{$k} += $messaging{$k};
|
||
}
|
||
}
|
||
|
||
$localmessaging{values} .= ($messaging{total_inbound} || 0) . ':';
|
||
$localmessaging{values1} .= ($messaging{total_outbound} || 0) . ':';
|
||
$localmessaging{values_bytes} .= ($messaging{total_inbound_bytes} || 0) . ':';
|
||
$localmessaging{values1_bytes} .= ($messaging{total_outbound_bytes} || 0) . ':';
|
||
my $tmp = 0;
|
||
foreach (split(/:/, $messaging{nbsender})) {
|
||
$tmp += $_;
|
||
}
|
||
$localmessaging{nbsender} .= $tmp . ':';
|
||
$tmp = 0;
|
||
foreach (split(/:/, $messaging{nbrcpt})) {
|
||
$tmp += $_;
|
||
}
|
||
$localmessaging{nbrcpt} .= $tmp . ':';
|
||
%messaging = ();
|
||
|
||
foreach my $t (keys %auth) {
|
||
foreach my $m (keys %{$auth{$t}}) {
|
||
if (!grep(/^$m$/, 'lbls','x_label','values')) {
|
||
$localauth{$t}{$m} += $auth{$t}{$m};
|
||
$localauth{$t}{values}{"$day"} += $auth{$t}{$m};
|
||
}
|
||
}
|
||
}
|
||
%auth = ();
|
||
|
||
foreach my $k (keys %spam) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localspam{$k} += $spam{$k};
|
||
}
|
||
}
|
||
$localspam{values} .= ($spam{total_inbound} || 0) . ':';
|
||
%spam = ();
|
||
foreach my $k (keys %reject) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localreject{$k} += $reject{$k};
|
||
}
|
||
}
|
||
%reject = ();
|
||
foreach my $k (keys %{$postgrey{reason}}) {
|
||
$localpostgrey{reason}{$k} += $postgrey{reason}{$k};
|
||
}
|
||
%postgrey = ();
|
||
|
||
foreach my $r (keys %{$spf_dkim{spf}}) {
|
||
foreach my $k (keys %{$spf_dkim{spf}{$r}{status}}) {
|
||
$localspf_dkim{spf}{$r}{status}{$k} += $spf_dkim{spf}{$r}{status}{$k};
|
||
}
|
||
foreach my $k (keys %{$spf_dkim{spf}{$r}{domain}}) {
|
||
$localspf_dkim{spf}{$r}{domain}{$k} += $spf_dkim{spf}{$r}{domain}{$k};
|
||
}
|
||
}
|
||
foreach my $r (keys %{$spf_dkim{dkim}{status}}) {
|
||
$localspf_dkim{dkim}{status}{$r} += $spf_dkim{dkim}{status}{$r};
|
||
}
|
||
%spf_dkim = ();
|
||
|
||
foreach my $k (keys %virus) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localvirus{$k} += $virus{$k};
|
||
}
|
||
}
|
||
$localvirus{values} .= ($virus{total_inbound} || 0) . ':';
|
||
%virus = ();
|
||
foreach my $k (keys %dsn) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localdsn{$k} += $dsn{$k};
|
||
}
|
||
}
|
||
$localdsn{values} .= ($dsn{total_outbound} || 0) . ':';
|
||
%dsn = ();
|
||
|
||
foreach my $k (keys %err) {
|
||
if (!grep(/^$k$/, 'lbls','x_label','values')) {
|
||
$localerr{$k} += $err{$k};
|
||
}
|
||
}
|
||
%err = ();
|
||
foreach my $k (keys %GLOBAL_STATUS) {
|
||
$localGLOBAL_STATUS{$k} += $GLOBAL_STATUS{$k};
|
||
}
|
||
%GLOBAL_STATUS = ();
|
||
foreach my $k (keys %starttls) {
|
||
$localstarttls{$k} += $starttls{$k};
|
||
}
|
||
%starttls = ();
|
||
|
||
foreach my $k (keys %delivery) {
|
||
if (!grep(/^$k$/, 'lbls','x_label')) {
|
||
$localdelivery{$k} += $delivery{$k};
|
||
}
|
||
}
|
||
|
||
foreach my $k (keys %topsender) {
|
||
foreach my $d (keys %{$topsender{$k}}) {
|
||
$localtopsender{$k}{$d} += $topsender{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topsender = ();
|
||
|
||
foreach my $k (keys %toprcpt) {
|
||
foreach my $d (keys %{$toprcpt{$k}}) {
|
||
$localtoprcpt{$k}{$d} += $toprcpt{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%toprcpt = ();
|
||
|
||
foreach my $k (keys %topreject) {
|
||
foreach my $d (keys %{$topreject{$k}}) {
|
||
$localtopreject{$k}{$d} += $topreject{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topreject = ();
|
||
|
||
foreach my $k (keys %toppostgrey) {
|
||
foreach my $d (keys %{$toppostgrey{$k}}) {
|
||
$localtoppostgrey{$k}{$d} += $toppostgrey{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%toppostgrey = ();
|
||
|
||
foreach my $k (keys %topvirus) {
|
||
foreach my $d (keys %{$topvirus{$k}}) {
|
||
$localtopvirus{$k}{$d} += $topvirus{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topvirus = ();
|
||
|
||
foreach my $k (keys %topdsn) {
|
||
foreach my $d (keys %{$topdsn{$k}}) {
|
||
$localtopdsn{$k}{$d} += $topdsn{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topdsn = ();
|
||
|
||
foreach my $k (keys %topspam) {
|
||
foreach my $d (keys %{$topspam{$k}}) {
|
||
$localtopspam{$k}{$d} += $topspam{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topspam = ();
|
||
foreach my $k (keys %toperr) {
|
||
$localtoperr{$k} += $toperr{$k} || 0;
|
||
}
|
||
%toperr = ();
|
||
|
||
foreach my $t (keys %topspamdetail) {
|
||
foreach my $k (keys %{$topspamdetail{$t}}) {
|
||
foreach my $d (keys %{$topspamdetail{$t}{$k}}) {
|
||
$localtopspamdetail{$t}{$k}{$d} += $topspamdetail{$t}{$k}{$d} || 0;
|
||
}
|
||
}
|
||
}
|
||
%topspamdetail = ();
|
||
|
||
foreach my $k (keys %topauth) {
|
||
foreach my $d (keys %{$topauth{$k}}) {
|
||
$localtopauth{$k}{$d} += $topauth{$k}{$d} || 0;
|
||
}
|
||
}
|
||
%topauth = ();
|
||
}
|
||
foreach my $t (keys %localauth) {
|
||
$authval{$t} .= ($localauth{$t}{values}{"$day"} || 0) . ':';
|
||
}
|
||
}
|
||
|
||
foreach my $t (keys %localauth) {
|
||
delete $localauth{$t}{values};
|
||
$localauth{$t}{values} = $authval{$t};
|
||
$localauth{$t}{lbls} =~ s/:$//;
|
||
$localauth{$t}{values} =~ s/:$//;
|
||
}
|
||
|
||
$lbls =~ s/:$//;
|
||
$localmessaging{values} =~ s/:$//;
|
||
$localmessaging{values1} =~ s/:$//;
|
||
$localmessaging{values_bytes} =~ s/:$//;
|
||
$localmessaging{values1_bytes} =~ s/:$//;
|
||
$localspam{values} =~ s/:$//;
|
||
$localvirus{values} =~ s/:$//;
|
||
$localdsn{values} =~ s/:$//;
|
||
$localmessaging{nbrcpt} =~ s/:$//;
|
||
$localmessaging{nbsender} =~ s/:$//;
|
||
|
||
# Create weeks directory if they do not exist yet
|
||
if (!-d "$CONFIG{OUT_DIR}/$hostname/$year/weeks") {
|
||
&create_directory("$hostname/$year/weeks");
|
||
}
|
||
if (!-d "$CONFIG{OUT_DIR}/$hostname/$year/weeks/$week") {
|
||
&create_directory("$hostname/$year/weeks/$week");
|
||
}
|
||
|
||
my $file = "$CONFIG{OUT_DIR}/$hostname/$year/weeks/$week/cache.pm\U$DOMAIN\E";
|
||
|
||
print "Writing cache file: $file\n" if ($CONFIG{DEBUG});
|
||
|
||
if (open(OUT, ">$file")) {
|
||
print OUT "\%::auth = (\n";
|
||
foreach my $type (keys %localauth) {
|
||
print OUT "'$type' => {";
|
||
print OUT "'values' => '$localauth{$type}{values}',";
|
||
print OUT "'lbls' => '$lbls',";
|
||
print OUT "'x_label' => 'Days of the week',";
|
||
foreach my $mech (keys %{$localauth{$type}}) {
|
||
next if (grep(/^$mech$/,'lbls','x_label','values'));
|
||
print OUT "'$mech' => '$localauth{$type}{$mech}',";
|
||
}
|
||
print OUT "},\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localauth = ();
|
||
print OUT "\%::messaging = (\n";
|
||
print OUT "'inbound' => '$localmessaging{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localmessaging{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localmessaging{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localmessaging{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localmessaging{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localmessaging{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localmessaging{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localmessaging{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localmessaging{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localmessaging{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localmessaging{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localmessaging{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Days of the week',\n";
|
||
print OUT "'values' => '$localmessaging{values}',\n";
|
||
print OUT "'values1' => '$localmessaging{values1}',\n";
|
||
print OUT "'values_bytes' => '$localmessaging{values_bytes}',\n";
|
||
print OUT "'values1_bytes' => '$localmessaging{values1_bytes}',\n";
|
||
print OUT "'nbsender' => '$localmessaging{nbsender}',\n";
|
||
print OUT "'nbrcpt' => '$localmessaging{nbrcpt}',\n";
|
||
print OUT ");\n\n";
|
||
%localmessaging = ();
|
||
|
||
print OUT "\%::spam = (\n";
|
||
print OUT "'inbound' => '$localspam{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localspam{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localspam{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localspam{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localspam{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localspam{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localspam{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localspam{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localspam{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localspam{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localspam{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localspam{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Days of the week',\n";
|
||
print OUT "'values' => '$localspam{values}',\n";
|
||
print OUT "'Ext_Int' => '$localspam{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localspam{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localspam{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localspam{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localspam{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localspam{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localspam{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localspam{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localspam = ();
|
||
|
||
print OUT "\%::reject = (\n";
|
||
print OUT "'inbound' => '$localreject{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localreject{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localreject{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localreject{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localreject{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localreject{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localreject = ();
|
||
|
||
print OUT "\%::postgrey = (\n";
|
||
print OUT "'reason' => {";
|
||
foreach my $k (keys %{$localpostgrey{reason}}) {
|
||
print OUT "\t'$k' => '$localpostgrey{reason}{$k}',";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localpostgrey = ();
|
||
|
||
print OUT "\%::spf_dkim = (\n";
|
||
print OUT "'spf' => {\n";
|
||
foreach my $r (keys %{$localspf_dkim{spf}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$localspf_dkim{spf}{$r}}) {
|
||
print OUT "\t\t'$s' => { ";
|
||
foreach my $v (keys %{$localspf_dkim{spf}{$r}{$s}}) {
|
||
print OUT "'$v' => '$localspf_dkim{spf}{$r}{$s}{$v}',";
|
||
}
|
||
print OUT " },\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT "'dkim' => {\n";
|
||
foreach my $r (keys %{$localspf_dkim{dkim}}) {
|
||
print OUT "\t'$r' => {\n";
|
||
foreach my $s (keys %{$localspf_dkim{dkim}{$r}}) {
|
||
print OUT "\t\t'$s' => '$localspf_dkim{dkim}{$r}{$s}',\n";
|
||
}
|
||
print OUT "\t},\n";
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localspf_dkim = ();
|
||
|
||
print OUT "\%::virus = (\n";
|
||
print OUT "'inbound' => '$localvirus{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localvirus{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localvirus{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localvirus{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localvirus{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localvirus{total_inbound_bytes}',\n";
|
||
print OUT "'outbound' => '$localvirus{outbound}',\n";
|
||
print OUT "'outbound_bytes' => '$localvirus{outbound_bytes}',\n";
|
||
print OUT "'local_outbound' => '$localvirus{local_outbound}',\n";
|
||
print OUT "'local_outbound_bytes' => '$localvirus{local_outbound_bytes}',\n";
|
||
print OUT "'total_outbound' => '$localvirus{total_outbound}',\n";
|
||
print OUT "'total_outbound_bytes' => '$localvirus{total_outbound_bytes}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Days of the week',\n";
|
||
print OUT "'values' => '$localvirus{values}',\n";
|
||
print OUT "'Ext_Int' => '$localvirus{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localvirus{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localvirus{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localvirus{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localvirus{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localvirus{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localvirus{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localvirus{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localvirus = ();
|
||
|
||
print OUT "\%::dsn = (\n";
|
||
print OUT "'outbound' => '$localdsn{outbound}',\n";
|
||
print OUT "'local_outbound' => '$localdsn{local_outbound}',\n";
|
||
print OUT "'total_outbound' => '$localdsn{total_outbound}',\n";
|
||
print OUT "'error' => '$localdsn{error}',\n";
|
||
print OUT "'lbls' => '$lbls',\n";
|
||
print OUT "'x_label' => 'Days of the week',\n";
|
||
print OUT "'values' => '$localdsn{values}',\n";
|
||
print OUT "'Ext_Int' => '$localdsn{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localdsn{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localdsn{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localdsn{Ext_Ext}',\n";
|
||
print OUT ");\n\n";
|
||
%localdsn = ();
|
||
|
||
print OUT "\%::err = (\n";
|
||
print OUT "'inbound' => '$localerr{inbound}',\n";
|
||
print OUT "'inbound_bytes' => '$localerr{inbound_bytes}',\n";
|
||
print OUT "'local_inbound' => '$localerr{local_inbound}',\n";
|
||
print OUT "'local_inbound_bytes' => '$localerr{local_inbound_bytes}',\n";
|
||
print OUT "'total_inbound' => '$localerr{total_inbound}',\n";
|
||
print OUT "'total_inbound_bytes' => '$localerr{total_inbound_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localerr = ();
|
||
|
||
print OUT "\%::GLOBAL_STATUS = (\n";
|
||
foreach my $k (keys %localGLOBAL_STATUS) {
|
||
my $slbl = $k;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "'$slbl' => '$localGLOBAL_STATUS{$k}',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localGLOBAL_STATUS = ();
|
||
|
||
print OUT "\%::starttls = (\n";
|
||
foreach my $k (keys %localstarttls) {
|
||
my $slbl = $k;
|
||
$slbl =~ s/'/\\'/g;
|
||
print OUT "'$slbl' => '$localstarttls{$k}',\n";
|
||
}
|
||
print OUT ");\n\n";
|
||
%localstarttls = ();
|
||
|
||
my $elbls = 'Ext -> Int:Ext -> Ext:Int -> Int:Int -> Ext';
|
||
print OUT "\%::delivery = (\n";
|
||
print OUT "'lbls' => '$elbls',\n";
|
||
print OUT "'x_label' => 'Days of the week',\n";
|
||
print OUT "'Ext_Int' => '$localdelivery{Ext_Int}',\n";
|
||
print OUT "'Int_Int' => '$localdelivery{Int_Int}',\n";
|
||
print OUT "'Int_Ext' => '$localdelivery{Int_Ext}',\n";
|
||
print OUT "'Ext_Ext' => '$localdelivery{Ext_Ext}',\n";
|
||
print OUT "'Ext_Int_bytes' => '$localdelivery{Ext_Int_bytes}',\n";
|
||
print OUT "'Int_Int_bytes' => '$localdelivery{Int_Int_bytes}',\n";
|
||
print OUT "'Int_Ext_bytes' => '$localdelivery{Int_Ext_bytes}',\n";
|
||
print OUT "'Ext_Ext_bytes' => '$localdelivery{Ext_Ext_bytes}',\n";
|
||
print OUT ");\n\n";
|
||
%localdelivery = ();
|
||
|
||
# Top SMTP Auth statistics
|
||
my $top = 0;
|
||
print OUT "\%::topauth = (\n";
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopauth{relay}{$b} <=> $localtopauth{relay}{$a} } keys %{$localtopauth{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopauth{relay};
|
||
$top = 0;
|
||
print OUT "'mech' => {";
|
||
foreach my $d (sort { $localtopauth{mech}{$b} <=> $localtopauth{mech}{$a} } keys %{$localtopauth{mech}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{mech}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopauth{mech};
|
||
$top = 0;
|
||
print OUT "'authid' => {";
|
||
foreach my $d (sort { $localtopauth{authid}{$b} <=> $localtopauth{authid}{$a} } keys %{$localtopauth{authid}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopauth{authid}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopauth = ();
|
||
|
||
# Top sender statistics
|
||
$top = 0;
|
||
print OUT "\%::topsender = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopsender{domain}{$b} <=> $localtopsender{domain}{$a} } keys %{$localtopsender{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopsender{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopsender{relay}{$b} <=> $localtopsender{relay}{$a} } keys %{$localtopsender{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopsender{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $localtopsender{email}{$b} <=> $localtopsender{email}{$a} } keys %{$localtopsender{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopsender{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopsender = ();
|
||
|
||
# Top recipient statistics
|
||
$top = 0;
|
||
print OUT "\%::toprcpt = (\n";
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtoprcpt{domain}{$b} <=> $localtoprcpt{domain}{$a} } keys %{$localtoprcpt{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoprcpt{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtoprcpt{relay}{$b} <=> $localtoprcpt{relay}{$a} } keys %{$localtoprcpt{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoprcpt{relay};
|
||
$top = 0;
|
||
print OUT "'email' => {";
|
||
foreach my $d (sort { $localtoprcpt{email}{$b} <=> $localtoprcpt{email}{$a} } keys %{$localtoprcpt{email}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoprcpt{email}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtoprcpt = ();
|
||
|
||
# Top rejection statistics
|
||
$top = 0;
|
||
print OUT "\%::topreject = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopreject{rule}{$b} <=> $localtopreject{rule}{$a} } keys %{$localtopreject{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopreject{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopreject{domain}{$b} <=> $localtopreject{domain}{$a} } keys %{$localtopreject{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{domain};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopreject{relay}{$b} <=> $localtopreject{relay}{$a} } keys %{$localtopreject{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{relay};
|
||
$top = 0;
|
||
print OUT "'chck_status' => {";
|
||
foreach my $d (sort { $localtopreject{chck_status}{$b} <=> $localtopreject{chck_status}{$a} } keys %{$localtopreject{chck_status}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopreject{chck_status}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopreject{chck_status};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopreject{sender}{$b} <=> $localtopreject{sender}{$a} } keys %{$localtopreject{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopreject{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopreject = ();
|
||
|
||
# Top postgrey statistics
|
||
$top = 0;
|
||
print OUT "\%::toppostgrey = (\n";
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtoppostgrey{sender}{$b} <=> $localtoppostgrey{sender}{$a} } keys %{$localtoppostgrey{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{sender};
|
||
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $localtoppostgrey{sender_relay}{$b} <=> $localtoppostgrey{sender_relay}{$a} } keys %{$localtoppostgrey{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{sender_relay};
|
||
$top= 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtoppostgrey{domain}{$b} <=> $localtoppostgrey{domain}{$a} } keys %{$localtoppostgrey{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{domain};
|
||
$top= 0;
|
||
print OUT "'reason' => {";
|
||
foreach my $d (sort { $localtoppostgrey{reason}{$b} <=> $localtoppostgrey{reason}{$a} } keys %{$localtoppostgrey{reason}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{reason}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtoppostgrey{reason};
|
||
$top= 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtoppostgrey{rcpt}{$b} <=> $localtoppostgrey{rcpt}{$a} } keys %{$localtoppostgrey{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtoppostgrey{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtoppostgrey = ();
|
||
|
||
# Top virus statistics
|
||
$top = 0;
|
||
print OUT "\%::topvirus = (\n";
|
||
print OUT "'virus' => {";
|
||
foreach my $d (sort { $localtopvirus{virus}{$b} <=> $localtopvirus{virus}{$a} } keys %{$localtopvirus{virus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopvirus{virus}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{virus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopvirus{sender}{$b} <=> $localtopvirus{sender}{$a} } keys %{$localtopvirus{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopvirus{relay}{$b} <=> $localtopvirus{relay}{$a} } keys %{$localtopvirus{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{relay};
|
||
$top = 0;
|
||
print OUT "'file' => {";
|
||
foreach my $d (sort { $localtopvirus{file}{$b} <=> $localtopvirus{file}{$a} } keys %{$localtopvirus{file}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{file}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopvirus{file};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopvirus{rcpt}{$b} <=> $localtopvirus{rcpt}{$a} } keys %{$localtopvirus{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopvirus{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopvirus = ();
|
||
|
||
# Top dsn statistics
|
||
$top = 0;
|
||
print OUT "\%::topdsn = (\n";
|
||
print OUT "'dsnstatus' => {";
|
||
foreach my $d (sort { $localtopdsn{dsnstatus}{$b} <=> $localtopdsn{dsnstatus}{$a} } keys %{$localtopdsn{dsnstatus}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopdsn{dsnstatus}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{dsnstatus};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopdsn{sender}{$b} <=> $localtopdsn{sender}{$a} } keys %{$localtopdsn{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{sender};
|
||
$top = 0;
|
||
print OUT "'relay' => {";
|
||
foreach my $d (sort { $localtopdsn{relay}{$b} <=> $localtopdsn{relay}{$a} } keys %{$localtopdsn{relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
delete $localtopdsn{relay};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopdsn{rcpt}{$b} <=> $localtopdsn{rcpt}{$a} } keys %{$localtopdsn{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopdsn{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},\n";
|
||
print OUT ");\n\n";
|
||
%localtopdsn = ();
|
||
|
||
# Top spam statistics
|
||
$top = 0;
|
||
print OUT "\%::topspam = (\n";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopspam{rule}{$b} <=> $localtopspam{rule}{$a} } keys %{$localtopspam{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopspam{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{rule};
|
||
$top = 0;
|
||
print OUT "'domain' => {";
|
||
foreach my $d (sort { $localtopspam{domain}{$b} <=> $localtopspam{domain}{$a} } keys %{$localtopspam{domain}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{domain}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{domain};
|
||
$top = 0;
|
||
print OUT "'sender_relay' => {";
|
||
foreach my $d (sort { $localtopspam{sender_relay}{$b} <=> $localtopspam{sender_relay}{$a} } keys %{$localtopspam{sender_relay}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{sender_relay}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{sender_relay};
|
||
$top = 0;
|
||
print OUT "'sender' => {";
|
||
foreach my $d (sort { $localtopspam{sender}{$b} <=> $localtopspam{sender}{$a} } keys %{$localtopspam{sender}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{sender}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspam{sender};
|
||
$top = 0;
|
||
print OUT "'rcpt' => {";
|
||
foreach my $d (sort { $localtopspam{rcpt}{$b} <=> $localtopspam{rcpt}{$a} } keys %{$localtopspam{rcpt}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspam{rcpt}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
print OUT ");\n\n";
|
||
%localtopspam = ();
|
||
|
||
# Top system message statistics
|
||
$top = 0;
|
||
print OUT "\%::toperr = (\n";
|
||
foreach my $m (sort { $localtopspam{$b} <=> $localtopspam{$a} } keys %localtoperr) {
|
||
my $c = $localtoperr{$m};
|
||
$m =~ s/'/\\'/g;
|
||
print OUT "'$m' => $c,\n";
|
||
}
|
||
print OUT ");\n";
|
||
%localtoperr = ();
|
||
|
||
# Top spam detail statistics
|
||
$top = 0;
|
||
print OUT "\%::topspamdetail = (\n";
|
||
foreach my $t (sort keys %localtopspamdetail) {
|
||
print OUT "'$t' => {";
|
||
print OUT "'rule' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{rule}{$b} <=> $localtopspamdetail{$t}{rule}{$a} } keys %{$localtopspamdetail{$t}{rule}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
my $c = $localtopspamdetail{$t}{rule}{$d};
|
||
$d =~ s/'/\\'/g;
|
||
print OUT "'$d' => '$c',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{rule};
|
||
$top = 0;
|
||
print OUT "'score' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{score}{$b} <=> $localtopspamdetail{$t}{score}{$a} } keys %{$localtopspamdetail{$t}{score}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{score}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{score};
|
||
$top = 0;
|
||
print OUT "'cache' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{cache}{$b} <=> $localtopspamdetail{$t}{cache}{$a} } keys %{$localtopspamdetail{$t}{cache}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{cache}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{cache};
|
||
$top = 0;
|
||
print OUT "'autolearn' => {";
|
||
foreach my $d (sort { $localtopspamdetail{$t}{autolearn}{$b} <=> $localtopspamdetail{$t}{autolearn}{$a} } keys %{$localtopspamdetail{$t}{autolearn}}) {
|
||
last if ($top == $CONFIG{TOP});
|
||
print OUT "'$d' => '$localtopspamdetail{$t}{autolearn}{$d}',";
|
||
$top++;
|
||
}
|
||
print OUT "},";
|
||
delete $localtopspamdetail{$t}{autolearn};
|
||
$top = 0;
|
||
print OUT "},";
|
||
}
|
||
print OUT ");\n";
|
||
close(OUT);
|
||
} else {
|
||
&logerror("can't write cache file $file: $!");
|
||
}
|
||
}
|
||
|
||
####
|
||
# Create output directory tree
|
||
####
|
||
sub create_directory
|
||
{
|
||
my $dest = shift;
|
||
|
||
my $curdir = '';
|
||
foreach my $d (split(/\//, $dest)) {
|
||
$curdir .= $d . '/';
|
||
if (!-d "$CONFIG{OUT_DIR}/$curdir") {
|
||
if (not mkdir("$CONFIG{OUT_DIR}/$curdir")) {
|
||
&logerror("Can't create directory $CONFIG{OUT_DIR}/$curdir: $!");
|
||
&logerror("Data will be lost.");
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
####
|
||
# Get all days of a week
|
||
####
|
||
sub get_week_boundaries
|
||
{
|
||
my ($year, $week) = @_;
|
||
|
||
my @days = ();
|
||
my $wn = 0;
|
||
for my $m ('01' .. '12') {
|
||
for my $d ('01' .. '31') {
|
||
$wn = &get_week_number($year,$m,$d);
|
||
next if ($wn == -1);
|
||
push(@days, "$year/$m/$d") if ($wn == $week);
|
||
}
|
||
}
|
||
|
||
return @days;
|
||
}
|
||
|
||
####
|
||
# Get the week day of a date
|
||
####
|
||
sub get_day_of_week
|
||
{
|
||
my ($year, $month, $day) = @_;
|
||
|
||
# %u The day of the week as a decimal, range 1 to 7, Monday being 1.
|
||
# %w The day of the week as a decimal, range 0 to 6, Sunday being 0.
|
||
|
||
#my $weekDay = POSIX::strftime("%u", gmtime timelocal_nocheck(0,0,0,$day,--$month,$year));
|
||
my $weekDay = POSIX::strftime("%u", 1,1,1,$day,--$month,$year-1900);
|
||
|
||
return $weekDay;
|
||
}
|
||
|
||
####
|
||
# Fix relay not sanityzed in sendmailanalyzer script
|
||
####
|
||
sub clean_relay
|
||
{
|
||
my $relay = shift;
|
||
|
||
if ( $relay =~ s/\(([a-fA-F0-9\.\:]+)\)// ) {
|
||
$relay = $1;
|
||
}
|
||
$relay =~ s/:/_/g; # fix ipv6 to remove data field separator
|
||
|
||
return $relay;
|
||
|
||
}
|