#!/usr/bin/perl
#
###############################################################################
#
# MAIL Q-TIP: Lets you get a better idea for what your mail statistics
# are for your site, if you get a lot of mail.
# Uses the "mailq" program of Sendmail.
#
# Written by Jason Scott. Version 1.0. Released June 9, 2000.
#
###############################################################################
##
## SETTINGS FOR THIS SCRIPT FOR YOUR SPECIFIC SITE
## Modify them for your stuff.
# Set the least amount of mail queued you want on the top list.
$lowerlimit=20;
# Where do all the HTML files go?
$outputdirect="/var/website";
# What name do you want to report all your mail as coming from?
$mailhost="SMTP.COW.NET";
# Set the color scheme to be different if you don't dig my choices.
$text="#FFFFFF"; # The foreground text (default white)
$back="#550000"; # The document backgrounds (default red)
$head="#000000"; # The header background (default black)
$info="#440000"; # The error backgrounds (default dark red)
$name="#220000"; # The hostname backgrounds (default darker red)
# What font would you like to be the font everything is in?
$font="Arial";
## END OF SETTINGS
## No modifications should be necessary for this script to function below.
###############################################################################
## Shave and a Haircut
## This subroutine takes a typical recipient line and turns it into a host.
## It gets called tons.
sub shave {
$recipient =~ s/\>//g;
$recipient =~ s/\/g;
$recipient =~ s/ //g;
@host=split(/@/,$recipient);
$mailhosts{$host[1]}++;
}
## Attempt to open the mailq program and invoke it with -v.
$? = 0;
open MAILQ,"mailq -v|"
or die "$!";
$date=`date`;
## Open up an HTML file for index.html, and then hosts.html.
open (INDEX,">$outputdirect/index.html");
print INDEX "
\n";
print INDEX "\n";
print INDEX "\n";
print INDEX "\n";
print INDEX "Mail Queue Statistics for $mailhost \n";
print INDEX " |
\n";
print INDEX "Top Problem Hosts\n";
print INDEX " Last Updated on $date\n";
print INDEX " \n";
print INDEX "Click Here for a Complete List\n";
print INDEX "\n";
open (HOSTS,">$outputdirect/hosts.html");
print HOSTS "\n";
print HOSTS "\n";
print HOSTS "\n";
print HOSTS "\n";
print HOSTS "Mail Queue Statistics for $mailhost \n";
print HOSTS " | \n";
print HOSTS "Top Problem Hosts\n";
print HOSTS " Last Updated on $date\n";
print HOSTS "\n";
print HOSTS "\n";
## Read in the MailQ results.
while() {
if(/^[a-zA-Z0-9]/) {
$holder=0;
@line = split();
$recipient=$line[6];
if ("$recipient" eq "" ) {
$holder=1;
}
# Do something here where you count the messages.
$messages++;
}
#elsif($holder) {
# This routine is designed so that if the recipient is null, then
# mark a "HOLDER" and the next time an address goes by, snag it. Unless
# of course the next major mail line goes through.
# The problem rests in somehow making the setup such that it will only do
# the additions to the totals once a mail recipient is discovered.
# Not there yet, but at least the info is being grabbed.
# if (/@/) {
# @host=split(/@/);
# $host[1]=~ s/\>//g;
# print "OTHER RECIPIENT: $host[1]\n";
# $holder=0;
# }
# }
elsif(/\(*\)/) {
# Lose the requests lines
if (/requests/) {
}
# Do something here where you keep track of what the reason for dying is.
elsif (/onnection timed out with/) {
$cto++;
@host=split(/with/);
$host[1] =~ s/\)//;
$host[1] =~ s/ //g;
chomp($host[1]);
$mailhosts{$host[1]}++;
$timeouts{$host[1]}++;
}
elsif (/onnection reset/) {
$cr++;
@host=split(/by/);
$host[1] =~ s/\)//;
$host[1] =~ s/ //g;
chomp($host[1]);
$mailhosts{$host[1]}++;
$connectionreset{$host[1]}++;
}
elsif (/onnection refused/) {
$crf++;
@host=split(/by/);
$host[1] =~ s/\)//;
$host[1] =~ s/ //g;
chomp($host[1]);
$mailhosts{$host[1]}++;
$connectionrefused{$host[1]}++;
}
elsif (/host map/) {
$hm++;
@check=split(/\(/);
$check[2] =~ s/\)//;
@host=split(/:/,$check[2]);
$host[0] =~ s/ //g;
chomp($host[0]);
$mailhosts{$host[0]}++;
$domainlookup{$host[0]}++;
}
elsif (/host name lookup/) {
$hm++;
@check=split(/\(/);
$check[2] =~ s/\)//;
@host=split(/:/,$check[2]);
$host[0] =~ s/ //g;
chomp($host[2]);
$mailhosts{$host[0]}++;
$domainlookup{$host[0]}++;
}
# These errors have to use the most recently sent recipient to figure
# out what the host was.
elsif (/not send/) {
$nb++;
shave();
$unsent{$host[1]}++;
}
elsif (/I\/O/) {
$io++;
shave();
$ioerror{$host[1]}++
}
elsif (/[Ii]nsufficient/) {
$ds++;
shave();
$outofdisk{$host[1]}++;
}
elsif (/[Nn]ot [Ee]nough [Ss]pace/) {
$ds++;
shave();
$outofdisk{$host[1]}++;
}
elsif (/oute to ho/) {
$ho++;
shave();
$noroute{$host[1]}++;
}
elsif (/roken pip/) {
$bp++;
shave();
$brokenpipe{$host[1]}++;
}
elsif (/read error/) {
$re++;
shave();
$readerrors{$host[1]}++;
}
elsif (/[Ii]llegal [Ss]eek/) {
$re++;
shave();
$readerrors{$host[1]}++;
}
else {
$weird++;
print "Unknown Error: $_\n";
}
}
}
close(MAILQ);
print "\n";
print "==============================\n";
print "TOP LIST OF HOSTS AND MESSAGES\n";
print "==============================\n";
foreach $hosts(sort{$mailhosts{$b} <=> $mailhosts{$a} } keys %mailhosts ) {
$totalhosts++; # Sorry, forgot the right way to do this
if($mailhosts{$hosts} > $lowerlimit) {
## Put it in the INDEX.HTML file... Start it here so optional lines get added.
print INDEX "$hosts\n";
if ("$hosts" eq "" ) {
print INDEX "(unknown host)\n";
}
print INDEX " | $mailhosts{$hosts}\n";
print "$hosts..";
print "($mailhosts{$hosts} messages).\n";
if ($timeouts{$hosts}) {
print " Timeouts: $timeouts{$hosts}\n";
print INDEX " | \n";
print INDEX "Host Timeouts\n";
print INDEX " | \n";
print INDEX "$timeouts{$hosts}\n";
}
if ($connectionreset{$hosts}) {
print " Reset Connections: $connectionreset{$hosts}\n";
print INDEX " | \n";
print INDEX "Reset Connections\n";
print INDEX " | \n";
print INDEX "$connectionreset{$hosts}\n";
}
if ($connectionrefused{$hosts}) {
print " Refused Connections: $connectionrefused{$hosts}\n";
print INDEX " | \n";
print INDEX "Refused Connections\n";
print INDEX " | \n";
print INDEX "$connectionrefused{$hosts}\n";
}
if ($domainlookup{$hosts}) {
print " Domain Lookup Failure: $domainlookup{$hosts}\n";
print INDEX " | \n";
print INDEX "Domain Lookup Failure\n";
print INDEX " | \n";
print INDEX "$domainlookup{$hosts}\n";
}
if ($ioerror{$hosts}) {
print " Host I/O Failure: $ioerror{$hosts}\n";
print INDEX " | \n";
print INDEX "Host I/O Failure\n";
print INDEX " | \n";
print INDEX "$ioerror{$hosts}\n";
}
if ($noroute{$hosts}) {
print " No Route to Host: $noroute{$hosts}\n";
print INDEX " | \n";
print INDEX "No Route to Host\n";
print INDEX " | \n";
print INDEX "$noroute{$hosts}\n";
}
if ($brokenpipe{$hosts}) {
print " Broken Pipe: $brokenpipe{$hosts}\n";
print INDEX " | \n";
print INDEX "Broken Pipe to Host\n";
print INDEX " | \n";
print INDEX "$brokenpipe{$hosts}\n";
}
if ($readerrors{$hosts}) {
print " Read Error: $readerrors{$hosts}\n";
print INDEX " | \n";
print INDEX "Network Read Errors\n";
print INDEX " | \n";
print INDEX "$readerrors{$hosts}\n";
}
if ($unsent{$hosts}) {
print " Waiting to Resend: $unsent{$hosts}\n";
print INDEX " | \n";
print INDEX "Waiting 4 Hours to Resend\n";
print INDEX " | \n";
print INDEX "$unsent{$hosts}\n";
}
if ($outofdisk{$hosts}) {
print " Out of Storage Space: $outofdisk{$hosts}\n";
print INDEX " | \n";
print INDEX "Out of Storage Space\n";
print INDEX " | \n";
print INDEX "$outofdisk{$hosts}\n";
}
}
}
print "\n";
print "===============================\n";
print "FULL LIST OF HOSTS AND MESSAGES\n";
print "===============================\n";
foreach $hosts(sort(keys(%mailhosts))) {
print HOSTS "$hosts\n";
if ("$hosts" eq "" ) {
print HOSTS "(unknown host)\n";
}
print HOSTS " | $mailhosts{$hosts}\n";
print "$hosts..";
print "($mailhosts{$hosts} messages).\n";
}
print "\n";
print "===================================\n";
print "Total Different Hosts: $totalhosts\n";
print "===================================\n";
print "Total Reset Connections: $cr\n";
print "Total Timeouts: $cto\n";
print "Total Refused connections: $crf\n";
print "Total Hostname Lookup Failures: $hm\n";
print "Total Still Unsent: $nb\n";
print "Input/Output Errors: $io\n";
print "Out of Disk Space: $ds\n";
print "No Route to Host: $ho\n";
print "Broken Pipe: $bp\n";
print "Read Errors: $re\n";
print "Stuff I didn't figure out: $weird\n\n";
$total=$cr+$cto+$crf+$hm+$nb+$io+$ds+$ho+$bp+$re+$weird;
print "Total Screwups Figured Out:";
print $total;
print "\nTotal Messages: $messages\n";
## Do it again, now for Index.HTML.
print INDEX " | | | | | | | | | | | | | | \n";
print INDEX "\n";
print INDEX " \n";
print INDEX "\n";
print INDEX "General Mail Queue Statistics for $mailhost \n";
print INDEX " | \n";
print INDEX "Total Different Hosts | $totalhosts\n";
print INDEX "\n";
print INDEX "Total Reset Connections: | $cr\n";
print INDEX "\n";
print INDEX "Total Timeouts: | $cto\n";
print INDEX "\n";
print INDEX "Total Refused connections: | $crf\n";
print INDEX "\n";
print INDEX "Total Hostname Lookup Failures: | $hm\n";
print INDEX "\n";
print INDEX "Total Still Unsent: | $nb\n";
print INDEX "\n";
print INDEX "Input/Output Errors: | $io\n";
print INDEX "\n";
print INDEX "Out of Disk Space: | $ds\n";
print INDEX "\n";
print INDEX "No Route to Host: | $ho\n";
print INDEX "\n";
print INDEX "Broken Pipe: | $bp\n";
print INDEX "\n";
print INDEX "Read Errors: | $re\n";
print INDEX "\n";
print INDEX "Stuff I didn't figure out: | $weird\n\n";
print INDEX "\n";
print INDEX "Total Screwups Figured Out:";
print INDEX " | $total\n";
print INDEX "\n";
print INDEX "Total Queued Messages: | $messages\n";
print INDEX " | | | | | | | | | | | | | | \n";
## Close out the INDEX.HTML file.
print INDEX " |
\n";
print INDEX "\n";
print HOSTS "\n";
print HOSTS "\n";