#!/usr/bin/perl
# ----------------------------------------------------------------------
# nightly_spamkill.pl - nuke old spam files from spammy Maildir folders
# Sun Oct 13 18:17:53 PDT 2002, Rudy Rucker, rruckerBLAHBLAH@monkeybrains.net
# Version 0.1 (not planning on another...)
# Feel free to use this ASIS and at your own risk.  
# ----------------------------------------------------------------------
# This is run nightly as a cron job.
# here is a good line for your crontab:
#  9 0 * * * /root/bin/nightly_spamkill.pl | /usr/bin/mail -E -s "Spam nuke stats" you@email.com
#
# Here is an excerpt from my procmailrc file which activates the spamassassian:
#
# procmailrc: SPAMFOLDER=${HOME}/Maildir/.spam/
# procmailrc: # send to the ninja spam assassin
# procmailrc: :0fw
# procmailrc: * < 256000
# procmailrc: | /usr/local/bin/spamc
# procmailrc: 
# procmailrc: :0:
# procmailrc: *^Subject:.*--SPAM--
# procmailrc: ${SPAMFOLDER}
#
# N.B. you may have something other than --SPAM--, like <SPAM> or ***SPAM*** in your procmailrc
#
# ----------------------------------------------------------------------
# configure this script be editing these variables.
# ----------------------------------------------------------------------
my $MIN_UID = 1000; # uid's less than $MIN_UID are not affected.
my $SPAM_FOLDER = "Maildir/.spam/"; # relative to users HOME (HOME is pulled from /etc/passwd)
my $MAX_SPAM_FILES = 50; # set to undef or 0 to skip this limit
my $MAX_DAYS = 7; # erase all spams MAX_DAYS old; set this to 0 to nuke all!
my $VERBOSE = 0; # turn on for a bunch of output.
my $PRINT_SPAM_COUNT_AT_END = 1; #leave this on to get an email from this cronjob, fun!

# ----------------------------------------------------------------------
# Don't need to change much below here.
# ----------------------------------------------------------------------

# redirect STDERR... ls complains when a user has no spam. (eg they erase it themselves)
open STDERR, ">/dev/null" or die "Redirect STDERR failed, $!"; 

my $count = 0;

while (my ($name,$uid,$dir) = (getpwent)[0,2,7]) {
	# ------------------------------------------------------------------
	# Check to see if we want to do this user
	# ------------------------------------------------------------------
	print "\n" if $VERBOSE;
	print "$name" if $VERBOSE;
	$uid < $MIN_UID and next;
	print " (uid:$uid)" if $VERBOSE;
	-d $dir or next;
	print "\t$dir" if $VERBOSE;
	unless (chdir "$dir/$SPAM_FOLDER") {
		print "\tNo spam folder!" if $VERBOSE;
		next;
	}

	# ------------------------------------------------------------------
	# okay, get list and see if there are mmore than MAX_SPAM_FILES
	# ------------------------------------------------------------------
	my $this_user_count;
	open KILL_LIST, "/bin/ls -t cur/* new/* |" or die "no /bin/ls in $0, $!";
	if ($MAX_SPAM_FILES and $MAX_SPAM_FILES > 0) {
		$this_user_count = 0;
		for (1..$MAX_SPAM_FILES) { <KILL_LIST> }; #skip these files...
		while ( my $file = <KILL_LIST>) {
			chomp($file);
			$count++;
			$this_user_count++;
			unlink $file or (print "failed to unlink $file");
		}
		print "\t$this_user_count spams overlimit" if $VERBOSE;
	}
	close KILL_LIST;
	# ------------------------------------------------------------------
	# Now nuke any spams older than MAX_DAYS
	# ------------------------------------------------------------------
	open KILL_LIST, "/bin/ls -t cur/* new/* |" or die "no /bin/ls in $0, $!";
	$this_user_count = 0;
	while ( my $file = <KILL_LIST>) {
		chomp($file);
		-M $file < $MAX_DAYS and next;
		print "$name nuking $file\n";
		unlink $file or (print "failed to unlink $file");
		$count++;
		$this_user_count++;
	}
	print "\t$this_user_count old spams" if $VERBOSE;
	close KILL_LIST;
}
print "\n" if $VERBOSE; #clean up line endings...

# ------------------------------------------------------------------
# print out some stats for the cronjob to mail you@email.com
# ------------------------------------------------------------------
if ($PRINT_SPAM_COUNT_AT_END or $VERBOSE) {
	$count > 1 and (print "$count spam files nuked.\n");
	$count == 1 and (print "only one lonely spam file nuked.\n");
	$count == 0 and (print "No spams eliminated.  You are lucky to not get any!\n");
}

exit;

__END__

 After thought:
 
 You could do most of this from procmail itself with a line something 
 like this:
   cd ${SPAMFOLDER} && rm -f dummy `ls -t */*mail* | sed -e 1,50d`
 BUT, I wanted age control, number control, a report emailed to me, and
 to speed the server up by only running this once per day for each user
 instead of once per incoming email.