--- mxgraphs.cgi 2014-05-15 15:48:24.628000137 +0200 +++ mxgraphs.cgi 2014-05-15 15:31:10.293000217 +0200 @@ -5,12 +5,14 @@ # copyright (c) 2000-2007 David Schweikert # modifed 2011 for grey Markus Neubauer # modified 2013 for mxgraphs by Django +# modified 2014 for mxgraphs (v2) by Django based on +# patches from Sebastian van de Meer # released under the GNU General Public License use RRDs; use POSIX qw(uname); -my $VERSION = "0.02"; +my $VERSION = "0.03"; my $host = (POSIX::uname())[1]; my $scriptname = 'mxgraphs.cgi'; @@ -21,6 +23,9 @@ my $ypoints_grey = 160; my $ypoints_greydetail = 160; my $ypoints_queue = 160; +my $ypoints_spf = 160; +my $ypoints_dkim = 160; +my $ypoints_dmarc = 160; my $rrd = '/var/lib/mailgraph/mailgraph.rrd'; # path to where the Mailgraph RRD database is my $rrd_virus = '/var/lib/mailgraph/mailgraph_virus.rrd'; # path to where the Virus RRD database is my $rrd_queue = '/var/lib/queuegraph/mailqueues.rrd'; # path to where the Mailqueue RRD database is @@ -39,17 +44,26 @@ sent => '000099', # rrggbb in hex received => '009900', whitelist => '999999', - new => 'C1C1C1', + new => 'FF77EE', early => 'AA0000', qspam => '000000', awl => 'DDBB00', - reconnectok => '88FF00', + reconnectok => '7700DD', rejected => 'AA0000', bounced => '000000', virus => 'DDBB00', spam => '999999', active => 'EFEF00', deferred => 'DD8800', + spfnone => '12FF0A', + spffail => 'f80b6f', + spfpass => '2E5fEC', + dkimnone => 'E6E27A', + dkimfail => 'FF6600', + dkimpass => '3013EC', + dmarcnone => 'F0B166', + dmarcfail => 'f11717', + dmarcpass => '00FFD5', ); sub rrd_graph(@) @@ -276,6 +290,128 @@ } +sub graph_spf($$) +{ + my ($range, $file) = @_; + my $step = $range*$points_per_sample/$xpoints; + rrd_graph($range, $file, $ypoints_spf, + "DEF:spfpass=$rrd:spfpass:AVERAGE", + "DEF:mspfpass=$rrd:spfpass:MAX", + "CDEF:rspfpass=spfpass,60,*", + "CDEF:dspfpass=spfpass,UN,0,spfpass,IF,$step,*", + "CDEF:sspfpass=PREV,UN,dspfpass,PREV,IF,dspfpass,+", + "CDEF:rmspfpass=mspfpass,60,*", + "AREA:rspfpass#$color{spfpass}:SPF pass", + 'GPRINT:sspfpass:MAX:total\: %8.0lf msgs', + 'GPRINT:rspfpass:AVERAGE:avg\: %5.2lf msgs/min', + 'GPRINT:rmspfpass:MAX:max\: %4.0lf msgs/min\l', + + "DEF:spfnone=$rrd:spfnone:AVERAGE", + "DEF:mspfnone=$rrd:spfnone:MAX", + "CDEF:rspfnone=spfnone,60,*", + "CDEF:dspfnone=spfnone,UN,0,spfnone,IF,$step,*", + "CDEF:sspfnone=PREV,UN,dspfnone,PREV,IF,dspfnone,+", + "CDEF:rmspfnone=mspfnone,60,*", + "LINE2:rspfnone#$color{spfnone}:SPF none", + 'GPRINT:sspfnone:MAX:total\: %8.0lf msgs', + 'GPRINT:rspfnone:AVERAGE:avg\: %5.2lf msgs/min', + 'GPRINT:rmspfnone:MAX:max\: %4.0lf msgs/min\l', + + "DEF:spffail=$rrd:spffail:AVERAGE", + "DEF:mspffail=$rrd:spffail:MAX", + "CDEF:rspffail=spffail,60,*", + "CDEF:dspffail=spffail,UN,0,spffail,IF,$step,*", + "CDEF:sspffail=PREV,UN,dspffail,PREV,IF,dspffail,+", + "CDEF:rmspffail=mspffail,60,*", + "LINE2:rspffail#$color{spffail}:SPF fail", + 'GPRINT:sspffail:MAX:total\: %8.0lf msgs', + 'GPRINT:rspffail:AVERAGE:avg\: %5.2lf msgs/min', + 'GPRINT:rmspffail:MAX:max\: %4.0lf msgs/min\l', + ); +} + + +sub graph_dkim($$) +{ + my ($range, $file) = @_; + my $step = $range*$points_per_sample/$xpoints; + rrd_graph($range, $file, $ypoints_dkim, + "DEF:dkimpass=$rrd:dkimpass:AVERAGE", + "DEF:mdkimpass=$rrd:dkimpass:MAX", + "CDEF:rdkimpass=dkimpass,60,*", + "CDEF:ddkimpass=dkimpass,UN,0,dkimpass,IF,$step,*", + "CDEF:sdkimpass=PREV,UN,ddkimpass,PREV,IF,ddkimpass,+", + "CDEF:rmdkimpass=mdkimpass,60,*", + "AREA:rdkimpass#$color{dkimpass}:DKIM pass", + 'GPRINT:sdkimpass:MAX:total\: %8.0lf msgs', + 'GPRINT:rdkimpass:AVERAGE:avg\: %5.2lf msgs/min', + 'GPRINT:rmdkimpass:MAX:max\: %4.0lf msgs/min\l', + + "DEF:dkimnone=$rrd:dkimnone:AVERAGE", + "DEF:mdkimnone=$rrd:dkimnone:MAX", + "CDEF:rdkimnone=dkimnone,60,*", + "CDEF:ddkimnone=dkimnone,UN,0,dkimnone,IF,$step,*", + "CDEF:sdkimnone=PREV,UN,ddkimnone,PREV,IF,ddkimnone,+", + "CDEF:rmdkimnone=mdkimnone,60,*", + "LINE2:rdkimnone#$color{dkimnone}:DKIM none", + 'GPRINT:sdkimnone:MAX:total\: %8.0lf msgs', + 'GPRINT:rdkimnone:AVERAGE:avg\: %5.2lf msgs/min', + 'GPRINT:rmdkimnone:MAX:max\: %4.0lf msgs/min\l', + + "DEF:dkimfail=$rrd:dkimfail:AVERAGE", + "DEF:mdkimfail=$rrd:dkimfail:MAX", + "CDEF:rdkimfail=dkimfail,60,*", + "CDEF:ddkimfail=dkimfail,UN,0,dkimfail,IF,$step,*", + "CDEF:sdkimfail=PREV,UN,ddkimfail,PREV,IF,ddkimfail,+", + "CDEF:rmdkimfail=mdkimfail,60,*", + "LINE2:rdkimfail#$color{dkimfail}:DKIM fail", + 'GPRINT:sdkimfail:MAX:total\: %8.0lf msgs', + 'GPRINT:rdkimfail:AVERAGE:avg\: %5.2lf msgs/min', + 'GPRINT:rmdkimfail:MAX:max\: %4.0lf msgs/min\l', + ); +} + + +sub graph_dmarc($$) +{ + my ($range, $file) = @_; + my $step = $range*$points_per_sample/$xpoints; + rrd_graph($range, $file, $ypoints_dmarc, + "DEF:dmarcpass=$rrd:dmarcpass:AVERAGE", + "DEF:mdmarcpass=$rrd:dmarcpass:MAX", + "CDEF:rdmarcpass=dmarcpass,60,*", + "CDEF:ddmarcpass=dmarcpass,UN,0,dmarcpass,IF,$step,*", + "CDEF:sdmarcpass=PREV,UN,ddmarcpass,PREV,IF,ddmarcpass,+", + "CDEF:rmdmarcpass=mdmarcpass,60,*", + "AREA:rdmarcpass#$color{dmarcpass}:DMARC pass", + 'GPRINT:sdmarcpass:MAX:total\: %8.0lf msgs', + 'GPRINT:rdmarcpass:AVERAGE:avg\: %5.2lf msgs/min', + 'GPRINT:rmdmarcpass:MAX:max\: %4.0lf msgs/min\l', + + "DEF:dmarcnone=$rrd:dmarcnone:AVERAGE", + "DEF:mdmarcnone=$rrd:dmarcnone:MAX", + "CDEF:rdmarcnone=dmarcnone,60,*", + "CDEF:ddmarcnone=dmarcnone,UN,0,dmarcnone,IF,$step,*", + "CDEF:sdmarcnone=PREV,UN,ddmarcnone,PREV,IF,ddmarcnone,+", + "CDEF:rmdmarcnone=mdmarcnone,60,*", + "LINE2:rdmarcnone#$color{dmarcnone}:DMARC none", + 'GPRINT:sdmarcnone:MAX:total\: %8.0lf msgs', + 'GPRINT:rdmarcnone:AVERAGE:avg\: %5.2lf msgs/min', + 'GPRINT:rmdmarcnone:MAX:max\: %4.0lf msgs/min\l', + + "DEF:dmarcfail=$rrd:dmarcfail:AVERAGE", + "DEF:mdmarcfail=$rrd:dmarcfail:MAX", + "CDEF:rdmarcfail=dmarcfail,60,*", + "CDEF:ddmarcfail=dmarcfail,UN,0,dmarcfail,IF,$step,*", + "CDEF:sdmarcfail=PREV,UN,ddmarcfail,PREV,IF,ddmarcfail,+", + "CDEF:rmdmarcfail=mdmarcfail,60,*", + "LINE2:rdmarcfail#$color{dmarcfail}:DMARC fail", + 'GPRINT:sdmarcfail:MAX:total\: %8.0lf msgs', + 'GPRINT:rdmarcfail:AVERAGE:avg\: %5.2lf msgs/min', + 'GPRINT:rmdmarcfail:MAX:max\: %4.0lf msgs/min\l', + ); +} + sub print_html() { print "Content-Type: text/html\n\n"; @@ -293,7 +429,7 @@ HEADER - print "

Mailserver Statistiken für
$host

\n"; + print "

Mailserver Statistiken für mx01.nausch.org

\n"; print "
    \n"; for my $n (0..$#graphs) { @@ -308,6 +444,9 @@ print "

    \"mxgraphs

    \n"; print "

    \"mxgraphs

    \n"; print "

    \"mxgraphs

    \n"; + print "

    \"mxgraphs

    \n"; + print "

    \"mxgraphs

    \n"; + print "

    \"mxgraphs

    \n"; } print < MX-Graphs $VERSION by - Django based on + Django based on David Schweikert's Mailgraph, + Markus Neubauer's + Greygraph, @@ -334,15 +475,9 @@ - Markus Neubauer's - Greygraph and - - - - - - - Ralf Hildebrandt's Queuegraph. + Ralf Hildebrandt's Queuegraph and + Sebastian van de Meer's + mailgraphpatches. @@ -404,6 +539,21 @@ graph_queue($graphs[$1]{seconds}, $file); send_image($file); } + elsif($img =~ /^(\d+)-f$/) { + my $file = "$tmp_dir/$uri/mailgraph_$1_spf.png"; + graph_spf($graphs[$1]{seconds}, $file); + send_image($file); + } + elsif($img =~ /^(\d+)-m$/) { + my $file = "$tmp_dir/$uri/mailgraph_$1_dkim.png"; + graph_dkim($graphs[$1]{seconds}, $file); + send_image($file); + } + elsif($img =~ /^(\d+)-c$/) { + my $file = "$tmp_dir/$uri/mailgraph_$1_dmarc.png"; + graph_dmarc($graphs[$1]{seconds}, $file); + send_image($file); + } else { die "ERROR: invalid argument\n"; }