diff --git a/plugins/other/qpsmtpd_mailstats b/plugins/other/qpsmtpd_mailstats new file mode 100755 index 00000000..0077b917 --- /dev/null +++ b/plugins/other/qpsmtpd_mailstats @@ -0,0 +1,120 @@ +#!/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 +graph_category QPSMTPD +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