From: chip@eniac.seas.upenn.edu (Charles H. Buchholtz)
Newsgroups: comp.unix.admin
Subject: Re: mail expiration program
Date: 24 Jul 92 12:59:56 GMT
Organization: University of Pennsylvania

wey@convex.cl.msu.edu (Lih-Er Wey) writes:
>I am looking for a program which will ckeck every user's system mail
>box and expires the mail which is older than some certain number of
>days. Any help will be appreciated.

[Reformatted to <80 columns, and removed bogus "comp" distribution]

We run such a script monthly, and it is a teriffic help in managing
our systems.  It takes 5 parameters:

WarnSize
MaxSize
MungeSize
WarnLetter
MungeLetter

It checks every file in /usr/spool/mail.  If the file is less than
WarnSize, it does nothing.  If the letter is larger than WarnSize and
less than MaxSize, it send WarnLetter to the owner.  

If the file is larger than MaxSize, it splits it into two parts.
The "new" part contains the most recent "MungeSize" messages, or all
messages received during the last month, whichever is larger.  This
part stays in /usr/spool/mail.  The older part (all the rest) is
placed in the owners home directory named "mbox.month-year".  Finally,
MungeLetter is sent to the owner.

MungeLetter explains how to read the mail which was shifted to the
home directory.

No mail is ever deleted.

Scripts to follow signature.

Charles H. Buchholtz       Systems Programmer     chip@seas.upenn.edu
	      School of Engineering and Applied Science
		      University of Pennsylvania

This is called "mailcop"

#!/bin/sh
#
# Check to see if a user has too much mail - if so, send her/him mail
# written by James F. Kennedy - jfk@ee.upenn.edu, jfk@seas.upenn.edu
# revised by J. Eric Fosler - fosler@seas.upenn.edu
#
# Last revision: Apr 2nd, 1991
# Revised: v2.0 June 13th, 1991 - jfk
#          v2.1 5 Dec 1991 - fosler
#          v2.2 25 Dec 1991 - chip
#             handle mailmunger errors better
#
# Usage: mailcop warnsize maxsize mungesize [warnletter [mungeletter]]
#
# warnsize is the size at which a user is sent a warning letter.  maxsize
# is the size at which the file is munged and mungesize is the size to munge
# the file to.  filename is optional filename of the letter to warn people.
#
# warnsize and maxsize are in blocks while mungesize is in bytes
#
# The default letter
#     default munger letter
#     mail backup file
#
TMUCHL=/usr/local/lib/mailcop/mailcop.letter
MUNGERMAIL=/usr/local/lib/mailcop/mailmunger.letter
MAILBACKUP=/home2/tar/mail.tar
MONTH=`date '+%h-%y'`
#
# our temporary files
#
TMPDIR=/tmp
TLIST=$TMPDIR/mailcop.list.$$
MLIST=$TMPDIR/mailmunger.list.$$
TMPNULL=$TMPDIR/mailcop.null.$$
#
# the mail directory to scan
#
MAILDIR=/var/spool/mail
#
# various commands
#
SORT=/bin/sort
LS="/bin/ls -s"
MAIL=/usr/ucb/mail
MUNGER=/usr/local/etc/mailmunger
RM=/bin/rm
COMPRESS=/usr/ucb/compress
TARADD="/bin/tar -uf"
TARCREATE="/bin/tar -cf"
CAT=/bin/cat
#
# usage statement
#
USAGE="Usage: mailcop warnsize maxsize mungesize [warnletter [mungeletter]]"
#
# other miscellaneous things
#
SUBJECT="Your mail file"
MSUBJECT="Mail File Munged"
#
# set our umask to 600 so no one else can bother us
#
umask 077
#
# make sure that the core file doesn't exist (mailer will barf this one back
# and also emacs backup (*~) files as these aren't valid userids either.
#
rm -f $MAILDIR/core $MAILDIR/*~
#
# Let's see if there's at least one argument, if not - display USAGE statement
# otherwise, set maxsize to be the first argument.
#
if [ $1 ]; then
	WARNSIZE=$1
else
	echo $USAGE
	exit 1
fi
#
# get second argument - maxsize and third arg - mungesize to determine
# at what size and to what size we munge a file.
#
#
if [ $2 ]; then
	MAXSIZE=$2
else
	echo $USAGE
	exit 1
fi

if [ $3 ]; then
	MUNGESIZE=$3
else
	echo $USAGE
	exit 1
fi
#
# now for the optional arguments
#
if [ $4 ]; then
	TMUCHL=$4
fi
if [ $5 ]; then
	MUNGERMAIL=$5
fi
#
# Now make sure the files exist
#
if [ -f $TMUCHL ]; then
	:
else
	echo "$0: Warning letter does not exist."
 	exit 1
fi
if [ -f $MUNGERMAIL ]; then
	:
else
	echo "$0:Munging letter does not exist."
 	exit 1
fi
#
# AWKSCRIPT is an awk program to process "ls -s" listings.  It ignores
# popper files (.*.pop) and the total line, and only prints files
# larger than MAXSIZE - chip@seas
#
AWKSCRIPT='$1 > '$WARNSIZE' && $1 != "total" && $2 !~ /\..*\.pop/ { print $2 }'
MUNGESCRIPT='$1 > '$MAXSIZE' && $1 != "total" && $2 !~ /\..*\.pop/ { print $2 }'
#
# First check for people who should be munged
#
$LS $MAILDIR | awk "$MUNGESCRIPT" > $MLIST
#
# and now munge them and let them know
#
if [ -f "$MAILBACKUP.Z" ]; then
	$RM "$MAILBACKUP.Z"
fi
if [ -f $MLIST ]; then
	export RCPT MONTH
	$CAT /dev/null > $TMPNULL
	$TARCREATE $MAILBACKUP $TMPNULL
	$RM $TMPNULL
	$CAT $MLIST | 
	  (while read RCPT; do
	    if $TARADD $MAILBACKUP $MAILDIR/$RCPT
	    then
	      if $MUNGER $MAILDIR/$RCPT $MAILDIR/$RCPT $RCPT $MUNGESIZE
	      then
	        $MAIL -s "$MSUBJECT" $RCPT < $MUNGERMAIL
	        #output from cron jobs will be mailed
	        echo "$RCPT: mail file munged."
	      fi
	    fi
	  done)
	$COMPRESS $MAILBACKUP
fi
#
# Do a directory listing of the mail directory and pipe the output
# to awk which will check for all files greater than WARNSIZE blocks
# This awk program will eliminate the "total" line and popper files.
#
$LS $MAILDIR | awk "$AWKSCRIPT" > $TLIST
#
# Now read each line of the temp file and mail the user the letter.
#
if [ -f $TLIST ]; then
	cat $TLIST | (while read RCPT; do
			$MAIL -s "$SUBJECT" $RCPT < $TMUCHL
			# output from cron jobs will be mailed
			echo "$RCPT: warned."
		     done)
fi
#
#cleanup
#
rm -f $TLIST $MLIST
exit 0


This is called "mailmunger":

#!/bin/sh
#
# mailmunger - created and written by James F. Kennedy jfk@ee.upenn.edu
#            - revised by J. Eric Fosler - fosler@seas.upenn.edu
#
# Revised: v1.0 June 12th, 1991 -jfk
#          v1.1 5 Dec 1991 - fosler
#	   v1.2 25 Dec 1991 - chip
#              correctly determine home directory on any system
#
# mailmunger-
#    truncates <srcfile> to specified <targetsize> and puts the older
#    part of the file in <targetdirectory> and the newer part in <targetfile>
#
# since this is called from tmuch..we assume that RCPT, MUNGERMAIL, MONTH and
# SUBJECT are set in the environment!
#
# define where the binaries are
#
MAIL=/usr/ucb/mail
MV=/bin/mv
CP=/bin/cp
CAT=/bin/cat
COMPRESS=/usr/ucb/compress
WC=/usr/ucb/wc
SPLIT=/bin/csplit
TAIL=/usr/ucb/tail
AWK=/bin/awk
RM=/bin/rm
TOUCH=/bin/touch
CUT=/bin/cut
CHOWN=/etc/chown
CHMOD=/bin/chmod
#
#
# default targetsize is 20000 bytes
#
TARGETSIZE=20000
#
# define a usage string
#
USAGE="Usage: mailmunger <sourcefile> <targetfile> <targetdirectory> <targetsize>"
#
#
# temporary files and other things
#
TMPDIR=/tmp
TMPSRCFILE=$TMPDIR/mungersrc.$$
TMPPREFIX=$TMPDIR/munger$$
PERMS=600
#
# argument one should be the source file
#
if [ $1 ]; then
	if [ -r $1 ]; then
		SRCFILE=$1
	else
		echo "$0: Source file $1 does not exist"
		exit 1
	fi
else
	echo $USAGE
	exit 1
fi
#
# argument 2 is the target file
#
if [ $2 ]; then
	TARGETFILE=$2
else
	echo $USAGE
	exit 1
fi
#
# Find the  target directory and  make sure that this exists
#

if [ $3 ]; then
	USER=$3
	TARGETDIR=`egrep "^$3:" /etc/passwd | cut -d: -f6`
	if [ -d $TARGETDIR ]; then
		:
	else
		echo $USAGE
		echo "$0: Target directory $TARGETDIR not a directory"
		exit 1
	fi
else
	echo $USAGE
	exit 1
fi

#
# argument 4 is the targetsize
#
if [ $4 ]; then
	TARGETSIZE=$4
fi

#
# see if the source file exists and that it is mungable
#
if [ -s $SRCFILE ]; then
	X=`$WC -c $SRCFILE | $CUT -c-8`
	if [ $TARGETSIZE -gt $X ]; then
		echo "$0: File already at or below desired size."
		exit 0
	fi
else
	echo "$0: Cannot munge zero-length file."
	exit 1
fi
#
# now, determine about what line number will be our cut-off point.
#
# first, mv srcfile to tmpsrcfile
#

$MV $SRCFILE $TMPSRCFILE
#
# make a backup of the mail file - just in case...
#
$CP $TMPSRCFILE $TMPDIR/mungerback.$$
#
# now, using awk - we will calculate the approximate area of demarcation
#
Y=`$WC $TMPSRCFILE | $AWK '{ N1=($3-'$TARGETSIZE')/$3;N2=N1*$1;printf("%d\n", N2) }'`
#
# once we have the approximate area...we now must find the exact area by 
# looking for the next "From_" (where _ is a space)
#
X=`$TAIL +$Y"l" $TMPSRCFILE | $AWK 'BEGIN {LINES = '$Y'} /^From\ /{ printf("%d\n", LINES); exit } { LINES=LINES+1 }'`
#
# just in case the file can't be munged period we check to see if X contains
# a valid field - if so, we split it using System V csplit (useful utility:)
# otherwise, we simply mv the original mail file back
# after we check for new mail and append that to the mail file.
#
if [ "$X" ]; then
	$SPLIT -f$TMPPREFIX $TMPSRCFILE $X > /dev/null
else
#
# check to see if it's busy
#
	while [ -f "$TARGETFILE.lock" ];
        do
	  sleep 1
	done
	$TOUCH "$TARGETFILE.lock"

	if [ -f $TARGETFILE ]; then
		$CAT $TARGETFILE >> $TMPSRCFILE
	fi
	$MV $TMPSRCFILE $TARGETFILE
	$CHOWN $RCPT $TARGETFILE
	$CHMOD $PERMS $TARGETFILE
	$RM "$TARGETFILE.lock"
#
# we don't need to notify anyone, so we simply exit
#
	exit 0
fi
#
# otherwise, we take the second file created by csplit and move it to
# the original file, provided we save any new file by appending it
# to the old
#
#
# check to see if it's busy
#
while [ -f "$TARGETFILE.lock" ];
do
  sleep 1
done
$TOUCH "$TARGETFILE.lock"

if [ -f $TARGETFILE ]; then
	$CAT $TARGETFILE >> $TMPPREFIX"01"
	$MV $TMPPREFIX"01" $TARGETFILE
else
	$MV $TMPPREFIX"01" $TARGETFILE
fi

$RM "$TARGETFILE.lock"
#
# now we compress the munged part and put it in the target directory
#
# $COMPRESS $TMPPREFIX"00"
$MV $TMPPREFIX"00" "$TARGETDIR/mbox-$MONTH"
$CHOWN $RCPT "$TARGETDIR/mbox-$MONTH"
$CHOWN $RCPT $TARGETFILE
$CHMOD $PERMS "$TARGETDIR/mbox-$MONTH" $TARGETFILE
#
# if we've gotten this far, it should be safe to remove all of our
# temps and backups
#
rm -f $TEMPPREFIX"*" $TMPSRCFILE $TMPDIR/mungerback.$$