#!/usr/bin/perl -w
#
#	mboxfull
#
#	Monitor mailboxes that are almost full.
#
#	You can change any of the values in the argument list
#	on the command line with:
#		--arg=value
#
#	The mbox name has some substitution on it.  USER is replaced
#	with the current user, and HOME is replaced with the user's
#	home directory.  For Cooper's application, it would look like:
#		--mbox=HOME/mbox
#
#	The msgfile must be a complete message, including the header
#	lines.  A sample is embedded in the code.  There is substitution
#	done here as well.  All values in the Args array can be used
#	with underscores on either side (e.g. "_maxsize_" will get replaced
#	with the current value of maxsize).  The symbol "_user_" and
#	"_size_" are also available.
#
#	Copyright 2004 by Dave Regan.
#	Distributed under GPL.
#

use strict;
use Getopt::Long;

use vars qw(%Args $Message $Version);

%Args =
    (
    	'maxsize'	=> 1000000,		# Max size of mailbox
	'msgfile'	=> '/etc/mboxfull',	# Message to send out
	'database'	=> '/tmp/mboxfull',	# Database of previous use
	'mbox'		=> '/var/spool/mail/USER', # Prototype of mbox
	'sendmail'	=> '/usr/sbin/sendmail',# Sendmail
	'interval'	=> 2,			# Time, in days, beween warnings
    );

$Version = 'mboxfull  v0.00  regan@armoredpenguin.com';

###
###	Main program
###

    my(@fields, %lastwarn, $mbox, $percent, $size, $user);

    GetOptions(\%Args, "maxsize=i", "msgfile=s", "database=s",
    		"mbox=s", "interval=i", "sendmail=s");

    # Read the prototype message
    if (!open(MSG, "<$Args{'msgfile'}"))
    	{
	$Message = << "EOF";
From: root
To: _user_
Subject: Mailbox getting full

Your mailbox is currently _size_ of the allowed _maxsize_ bytes.
Please trim your mailbox accordingly.
EOF
	}
    else
    	{
	while (<MSG>)
	    {
	    $Message .= $_;
	    }
	close MSG;
	}
    
    # Read the old database
    if (open(DATABASE, "<$Args{'database'}"))
    	{
	while (<DATABASE>)
	    {
	    chomp;
	    @fields = split(/:/, $_);
	    $lastwarn{$fields[0]} = $fields[1];
	    }
	}

    # Sequence through the users
    open(PASSWD, "</etc/passwd") || die "Cannot open /etc/passwd: $!";
    while (<PASSWD>)
    	{
	chomp;
	@fields = split(/:/, $_);
	next if ($fields[2] < 100);	# Ignore system UIDs
	$mbox = $Args{'mbox'};
	$mbox =~ s/USER/$fields[0]/;
	$mbox =~ s/HOME/$fields[5]/;
	$size = -s $mbox;
	next unless (defined $size);
	$user = $fields[0];
	if ($size < $Args{'maxsize'} / 2)
	    {
	    delete $lastwarn{$user}
	    }
	else
	    {
	    $percent = int($size / $Args{'maxsize'} * 100);
	    print "$user is $percent% of maximum size\n";

	    if (!defined($lastwarn{$user}) ||
	        $lastwarn{$user} + $Args{'interval'} * 86400 < time())
	    	{
		print "   Mail sent to $user\n";
		Warn($user, $size);
		$lastwarn{$user} = time();
		}
	    }
	}
    close PASSWD;

    # Write out the database
    if (open(DATABASE, ">$Args{'database'}"))
    	{
	for $user (sort keys %lastwarn)
	    {
	    print DATABASE "$user:$lastwarn{$user}\n";
	    }
	}
    close DATABASE;


###
###	Warn
###
###	Send email to a specific user.
###
sub Warn
    {
    my($user, $size) = @_;
    my($key, $msg);

    $msg = $Message;
    $Args{'user'} = $user;
    $Args{'size'} = $size;
    for $key (keys %Args)
    	{
	$msg =~ s/_${key}_/$Args{$key}/msg;
	}

    open(EMAIL, "| $Args{'sendmail'} -t") || die "Cannot open sendmail: $!";
    print EMAIL $msg;
    close EMAIL;
    }
