summaryrefslogtreecommitdiff
path: root/statistics
diff options
context:
space:
mode:
authorhorus_arch2015-03-29 20:52:16 +0200
committerhorus_arch2015-03-29 20:52:16 +0200
commit050315fd4253a962a5a2fa7fc69eb712bbf0ecdc (patch)
treee4e86aba3c27ab7749c6f97c9d1895024292eccc /statistics
parentde06b66b52c2e269bab93022f2fe46c7e02133f6 (diff)
downloadfreemail-050315fd4253a962a5a2fa7fc69eb712bbf0ecdc.tar.gz
Add modified mailgraph.cgi. Update style.css. Complete test suite, every function should be tested.
Diffstat (limited to 'statistics')
-rw-r--r--statistics/mailgraph.cgi380
1 files changed, 380 insertions, 0 deletions
diff --git a/statistics/mailgraph.cgi b/statistics/mailgraph.cgi
new file mode 100644
index 0000000..69d539a
--- /dev/null
+++ b/statistics/mailgraph.cgi
@@ -0,0 +1,380 @@
+#!/usr/bin/perl -w
+
+# mailgraph -- postfix mail traffic statistics
+# copyright (c) 2000-2007 ETH Zurich
+# copyright (c) 2000-2007 David Schweikert <david@schweikert.ch>
+# released under the GNU General Public License
+
+use RRDs;
+use POSIX qw(uname);
+
+my $VERSION = "1.14";
+
+my $host = (POSIX::uname())[1];
+my $scriptname = $ENV{"SCRIPT_NAME"};
+my $xpoints = 540;
+my $points_per_sample = 3;
+my $ypoints = 160;
+my $ypoints_err = 96;
+my $ypoints_grey = 96;
+my $rrd = '/var/lib/mailgraph/mailgraph.rrd'; # path to where the RRD database is
+my $rrd_virus = '/var/lib/mailgraph/mailgraph_virus.rrd'; # path to where the Virus RRD database is
+my $rrd_greylist = '/var/lib/mailgraph/mailgraph_greylist.rrd'; # path to where the Greylist RRD database is
+my $tmp_dir = '/var/lib/mailgraph'; # temporary directory where to store the images
+my @graphs = (
+ { title => 'Last Day', seconds => 3600*24, },
+ { title => 'Last Week', seconds => 3600*24*7, },
+ { title => 'Last Month', seconds => 3600*24*31, },
+ { title => 'Last Year', seconds => 3600*24*365, },
+);
+
+my %color = (
+ sent => '000099', # rrggbb in hex
+ received => '009900',
+ rejected => 'AA0000',
+ bounced => '000000',
+ virus => 'DDBB00',
+ spam => '999999',
+ greylisted => '999999',
+ delayed => '006400',
+);
+
+sub rrd_graph(@)
+{
+ my ($range, $file, $ypoints, @rrdargs) = @_;
+ my $step = $range*$points_per_sample/$xpoints;
+ # choose carefully the end otherwise rrd will maybe pick the wrong RRA:
+ my $end = time; $end -= $end % $step;
+ my $date = localtime(time);
+ $date =~ s|:|\\:|g unless $RRDs::VERSION < 1.199908;
+
+ my ($graphret,$xs,$ys) = RRDs::graph($file,
+ '--imgformat', 'PNG',
+ '--width', $xpoints,
+ '--height', $ypoints,
+ '--start', "-$range",
+ '--end', $end,
+ '--vertical-label', 'msgs/min',
+ '--lower-limit', 0,
+ '--units-exponent', 0, # don't show milli-messages/s
+ '--lazy',
+ '--color', 'SHADEA#ffffff',
+ '--color', 'SHADEB#ffffff',
+ '--color', 'BACK#ffffff',
+
+ $RRDs::VERSION < 1.2002 ? () : ( '--slope-mode'),
+
+ @rrdargs,
+
+ 'COMMENT:['.$date.']\r',
+ );
+
+ my $ERR=RRDs::error;
+ die "ERROR: $ERR\n" if $ERR;
+}
+
+sub graph($$)
+{
+ my ($range, $file) = @_;
+ my $step = $range*$points_per_sample/$xpoints;
+ rrd_graph($range, $file, $ypoints,
+ "DEF:sent=$rrd:sent:AVERAGE",
+ "DEF:msent=$rrd:sent:MAX",
+ "CDEF:rsent=sent,60,*",
+ "CDEF:rmsent=msent,60,*",
+ "CDEF:dsent=sent,UN,0,sent,IF,$step,*",
+ "CDEF:ssent=PREV,UN,dsent,PREV,IF,dsent,+",
+ "AREA:rsent#$color{sent}:Sent ",
+ 'GPRINT:ssent:MAX:total\: %8.0lf msgs',
+ 'GPRINT:rsent:AVERAGE:avg\: %5.2lf msgs/min',
+ 'GPRINT:rmsent:MAX:max\: %4.0lf msgs/min\l',
+
+ "DEF:recv=$rrd:recv:AVERAGE",
+ "DEF:mrecv=$rrd:recv:MAX",
+ "CDEF:rrecv=recv,60,*",
+ "CDEF:rmrecv=mrecv,60,*",
+ "CDEF:drecv=recv,UN,0,recv,IF,$step,*",
+ "CDEF:srecv=PREV,UN,drecv,PREV,IF,drecv,+",
+ "LINE2:rrecv#$color{received}:Received",
+ 'GPRINT:srecv:MAX:total\: %8.0lf msgs',
+ 'GPRINT:rrecv:AVERAGE:avg\: %5.2lf msgs/min',
+ 'GPRINT:rmrecv:MAX:max\: %4.0lf msgs/min\l',
+ );
+}
+
+sub graph_err($$)
+{
+ my ($range, $file) = @_;
+ my $step = $range*$points_per_sample/$xpoints;
+ rrd_graph($range, $file, $ypoints_err,
+ "DEF:bounced=$rrd:bounced:AVERAGE",
+ "DEF:mbounced=$rrd:bounced:MAX",
+ "CDEF:rbounced=bounced,60,*",
+ "CDEF:dbounced=bounced,UN,0,bounced,IF,$step,*",
+ "CDEF:sbounced=PREV,UN,dbounced,PREV,IF,dbounced,+",
+ "CDEF:rmbounced=mbounced,60,*",
+ "AREA:rbounced#$color{bounced}:Bounced ",
+ 'GPRINT:sbounced:MAX:total\: %8.0lf msgs',
+ 'GPRINT:rbounced:AVERAGE:avg\: %5.2lf msgs/min',
+ 'GPRINT:rmbounced:MAX:max\: %4.0lf msgs/min\l',
+
+ "DEF:virus=$rrd_virus:virus:AVERAGE",
+ "DEF:mvirus=$rrd_virus:virus:MAX",
+ "CDEF:rvirus=virus,60,*",
+ "CDEF:dvirus=virus,UN,0,virus,IF,$step,*",
+ "CDEF:svirus=PREV,UN,dvirus,PREV,IF,dvirus,+",
+ "CDEF:rmvirus=mvirus,60,*",
+ "STACK:rvirus#$color{virus}:Viruses ",
+ 'GPRINT:svirus:MAX:total\: %8.0lf msgs',
+ 'GPRINT:rvirus:AVERAGE:avg\: %5.2lf msgs/min',
+ 'GPRINT:rmvirus:MAX:max\: %4.0lf msgs/min\l',
+
+ "DEF:spam=$rrd_virus:spam:AVERAGE",
+ "DEF:mspam=$rrd_virus:spam:MAX",
+ "CDEF:rspam=spam,60,*",
+ "CDEF:dspam=spam,UN,0,spam,IF,$step,*",
+ "CDEF:sspam=PREV,UN,dspam,PREV,IF,dspam,+",
+ "CDEF:rmspam=mspam,60,*",
+ "STACK:rspam#$color{spam}:Spam ",
+ 'GPRINT:sspam:MAX:total\: %8.0lf msgs',
+ 'GPRINT:rspam:AVERAGE:avg\: %5.2lf msgs/min',
+ 'GPRINT:rmspam:MAX:max\: %4.0lf msgs/min\l',
+
+ "DEF:rejected=$rrd:rejected:AVERAGE",
+ "DEF:mrejected=$rrd:rejected:MAX",
+ "CDEF:rrejected=rejected,60,*",
+ "CDEF:drejected=rejected,UN,0,rejected,IF,$step,*",
+ "CDEF:srejected=PREV,UN,drejected,PREV,IF,drejected,+",
+ "CDEF:rmrejected=mrejected,60,*",
+ "LINE2:rrejected#$color{rejected}:Rejected",
+ 'GPRINT:srejected:MAX:total\: %8.0lf msgs',
+ 'GPRINT:rrejected:AVERAGE:avg\: %5.2lf msgs/min',
+ 'GPRINT:rmrejected:MAX:max\: %4.0lf msgs/min\l',
+
+ );
+}
+
+sub graph_grey($$)
+{
+ my ($range, $file) = @_;
+ my $step = $range*$points_per_sample/$xpoints;
+ rrd_graph($range, $file, $ypoints_grey,
+ "DEF:greylisted=$rrd_greylist:greylisted:AVERAGE",
+ "DEF:mgreylisted=$rrd_greylist:greylisted:MAX",
+ "CDEF:rgreylisted=greylisted,60,*",
+ "CDEF:dgreylisted=greylisted,UN,0,greylisted,IF,$step,*",
+ "CDEF:sgreylisted=PREV,UN,dgreylisted,PREV,IF,dgreylisted,+",
+ "CDEF:rmgreylisted=mgreylisted,60,*",
+ "AREA:rgreylisted#$color{greylisted}:Greylisted",
+ 'GPRINT:sgreylisted:MAX:total\: %8.0lf msgs',
+ 'GPRINT:rgreylisted:AVERAGE:avg\: %5.2lf msgs/min',
+ 'GPRINT:rmgreylisted:MAX:max\: %4.0lf msgs/min\l',
+
+ "DEF:delayed=$rrd_greylist:delayed:AVERAGE",
+ "DEF:mdelayed=$rrd_greylist:delayed:MAX",
+ "CDEF:rdelayed=delayed,60,*",
+ "CDEF:ddelayed=delayed,UN,0,delayed,IF,$step,*",
+ "CDEF:sdelayed=PREV,UN,ddelayed,PREV,IF,ddelayed,+",
+ "CDEF:rmdelayed=mdelayed,60,*",
+ "LINE2:rdelayed#$color{delayed}:Delayed ",
+ 'GPRINT:sdelayed:MAX:total\: %8.0lf msgs',
+ 'GPRINT:rdelayed:AVERAGE:avg\: %5.2lf msgs/min',
+ 'GPRINT:rmdelayed:MAX:max\: %4.0lf msgs/min\l',
+ );
+}
+
+
+sub print_html()
+{
+ print "Content-Type: text/html\n\n";
+
+ print <<HEADER;
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>Mail statistics for Libremail</title>
+<meta http-equiv="Refresh" content="300" />
+<meta http-equiv="Pragma" content="no-cache" />
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name='viewport' content='width=device-width, initial-scale=1.0'>
+ <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css'>
+ <link rel='stylesheet' type='text/css' href='/static/css/material-wfont.min.css'>
+ <link rel='stylesheet' type='text/css' href='/static/css/material.min.css'>
+ <link rel='stylesheet' type='text/css' href='/static/css/ripples.min.css'>
+ <link rel='stylesheet' type='text/css' href='/static/css/style.css'>
+ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
+ <link rel='shortcut icon' type='image/png' href='/static/img/favicon.ico'>
+<style type="text/css">
+* { margin: 0; padding: 0 }
+/*
+body { width: 630px; background-color: white;
+ font-family: sans-serif;
+ font-size: 12pt;
+ margin: 5px }
+*/
+h1 { margin-top: 20px; margin-bottom: 30px;
+ text-align: center }
+h2 { background-color: #ddd;
+ padding: 2px 0 2px 4px }
+hr { height: 1px;
+ border: 0;
+ border-top: 1px solid #aaa }
+table { border: 0px; width: 100% }
+img { border: 0 }
+a { text-decoration: none; color: #00e }
+a:hover { text-decoration: underline; }
+#jump { margin: 0 0 10px 4px }
+#jump li { list-style: none; display: inline;
+ font-size: 90%; }
+#jump li:after { content: "|"; }
+#jump li:last-child:after { content: ""; }
+</style>
+</head>
+<body>
+<nav class='navbar navbar-default navbar-custom shadow-z-2' role='navigation'>
+<div class='container'>
+<div class='navbar-header'>
+<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbarCollapse" aria-expanded="false" aria-controls="navbar">
+<span class="sr-only">Toggle navigation</span>
+<span class="icon-bar"></span>
+<span class="icon-bar"></span>
+<span class="icon-bar"></span>
+</button>
+<a class='navbar-brand' href='/'><span class='glyphicon glyphicon-home'></span> Home</a>
+</div>
+<div class="collapse navbar-collapse" id="navbarCollapse">
+<ul class="nav navbar-nav navbar-left">
+<li>
+<a class="" href="/about" title="About us"><span class="glyphicon glyphicon-file"></span> About</a>
+</li>
+<li>
+<a class="" href="/howto" title="How to"><span class="glyphicon glyphicon-star"></span> How to</a>
+</li>
+<li>
+<a class="" href="/server" title="Server"><span class="glyphicon glyphicon-cog"></span> Server</a>
+</li>
+<li>
+<a class="" href="https://iamfabulous.de/contact/" title="Contact" target="_blank"><span class="glyphicon glyphicon-phone-alt"></span> Contact</a>
+</li>
+</ul>
+<ul class="nav navbar-nav navbar-right">
+<li>
+<a class="" href="https://iamfabulous.de/webmail" title="Webmail"><span class="glyphicon glyphicon-envelope"></span> Webmail</a>
+</li>
+<li class="dropdown">
+<a class="" href="/register" title="Sign Up" data-target="#" data-toggle="dropdown"><span class="glyphicon glyphicon-user"></span> User <span class="caret"></span></a>
+<ul class="dropdown-menu" role="menu">
+<li><a class="" href="/register" title="Sign Up"><span class="fa fa-user-plus"></span> Create New</a></li>
+<li><a class="" href="/password" title="Change Password"><span class="fa fa-lock"></span> Change Password</a></li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+</nav>
+<div class="container">
+ <div class="row">
+ <div class="cold-md-12">
+ <h1>Mail statistics for Libremail</h1>
+ <div class="well">
+HEADER
+
+ #print "<h1>Mail statistics for Libremail</h1>\n";
+
+ print "<ul id=\"jump\">\n";
+ for my $n (0..$#graphs) {
+ print " <li><a href=\"#G$n\">$graphs[$n]{title}</a>&nbsp;</li>\n";
+ }
+ print "</ul>\n";
+
+ for my $n (0..$#graphs) {
+ print "<h2 id=\"G$n\">$graphs[$n]{title}</h2>\n";
+ print "<p><img class=\"img-responsive\" src=\"$scriptname?${n}-n\" alt=\"mailgraph\"/><br/>\n";
+ print "<img class=\"img-responsive\" src=\"$scriptname?${n}-e\" alt=\"mailgraph\"/>\n";
+ print "<img class=\"img-responsive\" src=\"$scriptname?${n}-g\" alt=\"mailgraph\"/></p>\n";
+ }
+
+ print <<FOOTER;
+<hr/>
+ </div>
+ </div>
+ </div>
+</div>
+<footer class="footer shadow-y-2">
+ <div class="container">
+ <div class="col-md-12">
+ <p class="sticky-footer">
+ Provided by <a class="footer-a" href="http://mailgraph.schweikert.ch/">Mailgraph <span class="fa fa-external-link"></span></a>
+ &#160; | &#160;
+ Libremail <span class="fa fa-copyright"></span> <a class='footer-a' href='//www.iamfabulous.de' title='Maximilian Möhring'>Maximilian M&ouml;hring <span class="fa fa-external-link"></span></a>
+ </p>
+ </div>
+ </div>
+</footer>
+<script src='//code.jquery.com/jquery-1.11.2.min.js'></script>
+<script src='//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js'></script>
+<script src='/static/js/material.min.js'></script>
+<script src='/static/js/ripples.min.js'></script>
+<script>
+ \$(document).ready(function(){
+ \$('.dropdown-toggle').dropdown();
+ })
+</script>
+</body></html>
+FOOTER
+}
+
+sub send_image($)
+{
+ my ($file)= @_;
+
+ -r $file or do {
+ print "Content-type: text/plain\n\nERROR: can't find $file\n";
+ exit 1;
+ };
+
+ print "Content-type: image/png\n";
+ print "Content-length: ".((stat($file))[7])."\n";
+ print "\n";
+ open(IMG, $file) or die;
+ my $data;
+ print $data while read(IMG, $data, 16384)>0;
+}
+
+sub main()
+{
+ my $uri = $ENV{REQUEST_URI} || '';
+ $uri =~ s/\/[^\/]+$//;
+ $uri =~ s/\//,/g;
+ $uri =~ s/(\~|\%7E)/tilde,/g;
+ mkdir $tmp_dir, 0777 unless -d $tmp_dir;
+ mkdir "$tmp_dir/$uri", 0777 unless -d "$tmp_dir/$uri";
+
+ my $img = $ENV{QUERY_STRING};
+ if(defined $img and $img =~ /\S/) {
+ if($img =~ /^(\d+)-n$/) {
+ my $file = "$tmp_dir/$uri/mailgraph_$1.png";
+ graph($graphs[$1]{seconds}, $file);
+ send_image($file);
+ }
+ elsif($img =~ /^(\d+)-e$/) {
+ my $file = "$tmp_dir/$uri/mailgraph_$1_err.png";
+ graph_err($graphs[$1]{seconds}, $file);
+ send_image($file);
+ }
+ elsif($img =~ /^(\d+)-g$/) {
+ my $file = "$tmp_dir/$uri/mailgraph_$1_grey.png";
+ graph_grey($graphs[$1]{seconds}, $file);
+ send_image($file);
+ }
+ else {
+ die "ERROR: invalid argument\n";
+ }
+ }
+ else {
+ print_html;
+ }
+}
+
+main;