2011-03-31 21:39:48 +02:00
|
|
|
#!/usr/bin/perl
|
|
|
|
#
|
|
|
|
# Written by Gene Cutler, February 2011
|
|
|
|
# Loosely based on postfix_mailstats
|
|
|
|
# Graphs various qpsmtpd responses (greylisting, bad recipient, bad sender, etc.)
|
|
|
|
#
|
|
|
|
# config:
|
|
|
|
# [qpsmtpd_mailstats]
|
|
|
|
# env.logfile - Full path to qpsmtpd logfile, default = '/var/log/qpsmtpd/qpsmtpd.log'
|
|
|
|
#
|
|
|
|
# Parameters understood:
|
|
|
|
#
|
|
|
|
# config (required)
|
|
|
|
# autoconf (optional - used by munin-config)
|
|
|
|
#
|
|
|
|
#
|
|
|
|
#%# family=auto
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
my $LOGFILE = $ENV{'logfile'} || '/var/log/qpsmtpd/qpsmtpd.log';
|
|
|
|
my $STATEFILE= $ENV{MUNIN_PLUGSTATE} . '/qpsmtpd_mailstats.state';
|
|
|
|
my $LINE_N = 0;
|
|
|
|
my %REJECT_CODES = (
|
|
|
|
250 => '250 queued',
|
|
|
|
450 => '450 greylisted',
|
|
|
|
451 => '451 bad recipient',
|
|
|
|
501 => '501 bad sender',
|
|
|
|
503 => '503 MAIL first',
|
|
|
|
550 => '550 bad dnsbl',
|
|
|
|
554 => '554 spamtrap',
|
|
|
|
);
|
|
|
|
|
|
|
|
if (defined($ARGV[0]) and ($ARGV[0] eq 'config')) {
|
|
|
|
do_config();
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
$LINE_N = get_state();
|
|
|
|
$LINE_N ||= 0;
|
|
|
|
|
|
|
|
sub get_state {
|
|
|
|
my $fh;
|
|
|
|
open $fh,$STATEFILE;
|
|
|
|
$_ = <$fh>;
|
|
|
|
close $fh;
|
|
|
|
/^(\d+)$/;
|
|
|
|
return $1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub save_state {
|
|
|
|
my $n = shift;
|
|
|
|
my $fh;
|
|
|
|
open $fh, ">$STATEFILE";
|
|
|
|
print $fh "$n\n";
|
|
|
|
close $fh;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
do_stats($LINE_N);
|
|
|
|
|
|
|
|
|
|
|
|
sub do_stats {
|
|
|
|
my $start_at = shift;
|
|
|
|
my $fh;
|
|
|
|
my $stop_at = (stat $LOGFILE)[7];
|
|
|
|
$start_at = 0 if $stop_at < $start_at;
|
|
|
|
|
|
|
|
my %counts = ();
|
|
|
|
|
|
|
|
open $fh, $LOGFILE or die "$!: $LOGFILE";
|
|
|
|
|
|
|
|
seek $fh, $start_at, 0 if $start_at > 0;
|
|
|
|
|
|
|
|
my $where;
|
|
|
|
while (($where = tell $fh) < $stop_at) {
|
|
|
|
my $line = <$fh>;
|
|
|
|
if ($line =~ /: 250 Queued!/) {
|
|
|
|
$counts{'250'}++;
|
|
|
|
} elsif ($line =~ /: (\d+)/ and defined $REJECT_CODES{$1}) {
|
|
|
|
$counts{$1}++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $fh;
|
|
|
|
|
|
|
|
save_state($stop_at);
|
|
|
|
|
|
|
|
foreach my $rc (sort {$a<=>$b} keys %REJECT_CODES) {
|
|
|
|
$counts{$rc} ||= 0;
|
|
|
|
print "r$rc.value $counts{$rc}\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub do_config {
|
|
|
|
my $k;
|
|
|
|
|
|
|
|
print "graph_title QPSMTPD Responses
|
2017-02-22 23:20:56 +01:00
|
|
|
graph_category mail
|
2011-03-31 21:39:48 +02:00
|
|
|
graph_args --base 1000 -l 0
|
|
|
|
graph_vlabel responses / \${graph_period}
|
|
|
|
graph_scale no
|
|
|
|
graph_period minute
|
|
|
|
graph_total Total
|
|
|
|
";
|
|
|
|
|
|
|
|
get_state();
|
|
|
|
|
|
|
|
my $type;
|
|
|
|
foreach $k (sort {$a<=>$b} keys %REJECT_CODES) {
|
|
|
|
print
|
|
|
|
"r$k.label $REJECT_CODES{$k}
|
|
|
|
r$k.type ABSOLUTE
|
|
|
|
r$k.min 0
|
|
|
|
r$k.draw AREASTACK
|
|
|
|
";
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
# vim:syntax=perl
|