#!/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
