mirror of
https://github.com/darold/sendmailanalyzer.git
synced 2026-05-25 22:03:32 -06:00
following mail header score. Thanks to Hans Mayer,for the report. Add report of all recipients addresses for spam with multiple recipients as when messages are discarded they all have the same ID. This was resulting in the right count of senders but wrong count of recipients. Note that in this case the spam received counter is still related to senders count as they are not sent. Thanks to Hans Mayer for the report.
5469 lines
184 KiB
Perl
Executable file
5469 lines
184 KiB
Perl
Executable file
#!/usr/bin/perl
|
||
#
|
||
# SendmailAnalyzer: maillog parser and statistics reports tool for Sendmail
|
||
# Copyright (C) 2002-2018 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.2';
|
||
$AUTHOR = "Gilles Darold <gilles\@darold.net>";
|
||
$COPYRIGHT = "(c) 2002-2018 - 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);
|
||
if ($#data > 6) {
|
||
@data = $l =~ m/^([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):([a-zA-Z0-9\-\.]+|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\)|[0-9a-fA-F:\(\)]+)?:([^:]+)$/;
|
||
}
|
||
$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];
|
||
}
|
||
if ($#data >= 6) {
|
||
$localstat{$data[1]}{subject} = $data[6];
|
||
}
|
||
}
|
||
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);
|
||
if ($#data > 4) {
|
||
@data = $l =~ m/^([^:]+):([^:]+):([^:]+):([a-zA-Z0-9\-\.]+|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\)|[0-9a-fA-F:\(\)]+)?:([^:]+)$/;
|
||
}
|
||
$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);
|
||
if ($#data > 5) {
|
||
@data = $l =~ m/^([^:]+):([^:]+):([^:]+):([a-zA-Z0-9\-\.]+|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\)|[0-9a-fA-F:\(\)]+)?:([^:]+):([^:]+)$/;
|
||
}
|
||
$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]);
|
||
} 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);
|
||
if ($#data > 6) {
|
||
@data = $l =~ m/^([^:]+):([^:]+):([a-zA-Z0-9\-\.]+|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\)|[0-9a-fA-F:\(\)]+)?:([^:]+):([^:]*):([^:]+):([^:]+)$/;
|
||
# Fix a possible bug corruption of the data files
|
||
$data[3] =~ s/(.*\@.*)\@localhost/$1/;
|
||
$data[4] =~ s/(.*\@.*)\@localhost/$1/;
|
||
}
|
||
$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);
|
||
if ($#data > 4) {
|
||
@data = $l =~ m/^([^:]+):([^:]+):([a-zA-Z0-9\-\.]+|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\)|[0-9a-fA-F:\(\)]+)?:([^:]+):([^:]+)$/;
|
||
}
|
||
$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;
|
||
|
||
}
|