#!/usr/bin/perl -s

# mailqto - summarize hosts for which there is undeliverable mail
# Steve Kinzler, steve@kinzler.com, Oct 91
# https://kinzler.com/me/home.html#unixadm

$usage = "usage: $0 [ -l ] [ -s ]
	-l	include mailq output after the summary
	-s	read mailq output from stdin instead of mailq command\n";
die $usage if $h || @ARGV;

%cal = ('Jan',   0, 'Feb',  31, 'Mar',  59, 'Apr',  90, 'May', 120,
	'Jun', 151, 'Jul', 181, 'Aug', 212, 'Sep', 243, 'Oct', 273,
	'Nov', 304, 'Dec', 334);

($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime time;
$now = $yday + ($hour * 60 + $min) / 1440;

$localhost = $ENV{'HOST'} || $ENV{'HOSTNAME'};
chop($localhost = `(hostname) 2> /dev/null`) unless $localhost;
chop($localhost = `uname -n`)		     unless $localhost;
$localhost =~ s/\..*//;
$localhost = 'localhost'		     unless $localhost;

open(MAILQ, ($s) ? '< -' : 'mailq |');
@mailq = <MAILQ>;
close(MAILQ);
@items = split(/\n ?[^-\s]/, join('', (@mailq, " A\n")));
shift @items; pop @items;

foreach (@items) {
	@__ = split(/\n/);
	next unless $__[1] =~
	    s/^\s{2,}\(((Deferred|reply):?\s*)?(.*)\)\s*$/$3/i;
	$age = &age(split(/\s+/, $__[0]));
	foreach $i (2 .. $#__) {
		$host = &hostname($__[$i]);
		$count{$host}++;
		$ages{$host} = $age
		    if ! defined $ages{$host} || $ages{$host} < $age;
	}
	$reasons{$host} = (($__[1] =~ /^(\s|$)/) ? '' : ' ') . $__[1];
}

foreach (sort byage keys %count) {
	$out = sprintf("%2d %s %s%s\n", $count{$_}, &prage($ages{$_}),
					$_, $reasons{$_});
	$out =~ s/^(.{0,79}).*/$1/;
	push(@output, $out);
}
print((@output) ? @output : "Undeliverable mail queue is empty\n");

print "\n", @mailq if $l;

sub byage {
	($ages{$a} == $ages{$b}) ? $a gt $b : $ages{$a} < $ages{$b};
}

sub age {
	$year-- if $mon == 0 && $_[3] eq 'Dec';
	$day = $cal{$_[3]};
	$day++ if $year % 4 == 0 && $_[3] ne 'Jan' && $_[3] ne 'Feb';
	$_[5] =~ /(.*):(.*)/;
	$then = $day + $_[4] - 1 + ($1 * 60 + $2) / 1440;

	$age = $now - $then;
	$age = (($year % 4 == 0) ? 366 : 365) - $then + $now if $age < 0;
	return $age;
}

sub prage {
	$days = int($_[0]);
	$hrs  = ($_[0] - $days) * 24;
	$mins = int(($hrs - int($hrs)) * 60);
	$hrs  = int($hrs);

	$hrs  = "0$hrs"  if  $hrs < 10;
	$mins = "0$mins" if $mins < 10;

	return "$days,$hrs:$mins";
}

sub hostname {
	local($_) = $_[0];

	s/^\s*//;
	s/.*<//;
	s/>.*$//;
	s/\s.*//;

	s/"(.*)::.*"/$1/;

	s/^\@?$localhost(|\.[^:@%!]*)://io ||
	s/\@$localhost(|\.[^:@%!]*)$//io   ||
	s/%$localhost(|\.[^:@%!]*)$//io   ||
	s/^$localhost(|\.[^:@%!]*)!//io;

	return $localhost unless /[:@%!]/;

	s/:.*//;
	s/.*\@//;
	s/.*%//;
	s/!.*// && (/\./ || s/$/.uucp/);

	y/A-Z/a-z/;

	$_ = 'UNKNOWN' if /^$/ || /[^+-\.0-9_a-z]/;

	return $_;
}
