#!/bin/sh # # Read Mail Archiver # # This utility is used to move, by means of ProcMail, "read mail" from user's # inbox to his/her Mail folder (and subfolders). # # Usually this is achieved directly via ProcMail but, as we want to keep some # mail into inbox itself, we need a bit of additional scripting (also to avoid # mail loss while handling the "read" one). # # We use a "procmailrc" file put into the user's home (but made root-readable # only, to avoid ProcMail complains): there one can put his filters to archive # all the mail he wants, making the read of inbox much more speedy. # ### # # The procedure: # # 1) we'll move the user's inbox into a temporary file, suddenly recreating the # inbox to make sure new mail is not lost while we handle the archiving one. # # 2) then we launch ProcMail which filters the (stable/temp) inbox applying the # user-defined filter set (~/procmailrc) and creates two files: # $username.new: the unread mail to keep into inbox # $username.other: the read "unmatched" mail to keep into inbox also # # Other "mached" mails will be stored into user's Mail folder(s), depending to # the rules written into his ~/procmailrc file. # # 3) after filtering we re-create the inbox appending: # a) the current inbox (usually /var/mail/$username) # b) the "new" (unread) file # c) the "other" (read but unmatched) file # # 4) last but not least we make a bit of housecleaning, removing all temporary # files and setting the right permissions to the permanent ones. # # 20090307=LC # to log results using syslog. #LOGRESULTS="no" LOGRESULTS="yes" # if you want visual debug message fill the following var with something (like "true") DEBUG="" #------------------------------------------------------------------------------- # a couple of useful debugging functions # debugmsg() { if [ "$DEBUG" != "" ]; then echo "DBG> $1" fi } debugenter() { if [ "$DEBUG" != "" ]; then echo -e "DBG> [enter] " read fi } #------------------------------------------------------------------------------- # Check for input parameter: userid of the user which the inbox will be archived if [ "$1" == "" ]; then echo "Usage: ${0##*/} " exit 1 else USER=$1 PROCMAILRC="/home/$USER/procmailrc" INBOX="/var/mail/$USER" fi # Check for utilities are present in the system if [ ! -f $PROCMAILRC ]; then echo "Error: filter(s) file ($PROCMAILRC) not found!" exit 2 fi if [ ! -f $INBOX ]; then echo "Error: INBOX file ($INBOX) not found!" exit 2 fi if [ "$(type -p formail)" == "" ]; then echo "Error: 'formail' utility not found." exit 3 fi if [ "$(type -p procmail)" == "" ]; then echo "Error: 'procmail' utility not found." exit 3 fi # Check for optional utilities and get the mailcount before archiving (only if we want to log the results) if [ "$LOGRESULTS" == "yes" ]; then if [ "$(type -p logger)" == "" ]; then echo "Warning: 'logger' utility not found: continuing without logging results" LOGRESULTS="no" fi if [ "$(type -p from)" == "" ]; then echo "Warning: 'from' utility not found: continuing without logging results" LOGRESULTS="no" fi if [ "$(type -p wc)" == "" ]; then echo "Warning: 'wc' utility not found: continuing without logging results" LOGRESULTS="no" fi if [ "$LOGRESULTS" == "yes" ]; then MAILPRE=$(from $1 | wc -l) fi fi # 1) Move the user's inbox into a temporary file, suddenly recreating the # inbox to make sure new mail is not lost while we handle the archiving one. debugmsg "1.1 move the user's inbox into a temporary file" mv $INBOX $INBOX.tmp debugmsg "1.2 re-create it empty" touch $INBOX debugmsg "1.3 make sure owner and perms are correct" chown --reference=$INBOX.tmp $INBOX chmod --reference=$INBOX.tmp $INBOX debugenter debugmsg "2.1 offline process the inbox file..." formail -s procmail -m $PROCMAILRC < $INBOX.tmp debugmsg "3.1 move any new mail (arrived while we was archiving) into $username.new2" mv $INBOX $INBOX.new2 debugmsg "3.2 re-build INBOX file appending .new2, .new and .other files" if [ -f $INBOX.new ]; then cat $INBOX.new > $INBOX else touch $INBOX fi cat $INBOX.new2 >> $INBOX if [ -f $INBOX.other ]; then cat $INBOX.other >> $INBOX else debugmsg "Warning: no '.other' file ($INBOX.other) created (that may be strange), check!" fi debugenter debugmsg "4.1 remove .new, .new2 and .other temporary files" rm $INBOX.new* if [ -f $INBOX.other ]; then rm $INBOX.other fi debugmsg "4.2 make sure owner and perms are correct" chown --reference=$INBOX.tmp $INBOX chmod --reference=$INBOX.tmp $INBOX debugmsg "4.3 remove the (temporary) 'offline' inbox file (temporary disabled: check and do it by hand!)" if [ "$DEBUG" == "" ]; then rm $INBOX.tmp fi # Get the mailcount after archiving (only if we want to log the results) if [ "$LOGRESULTS" == "yes" ]; then MAILAFT=$(from $1 | wc -l) MAILARC=$(($MAILPRE - $MAILAFT)) logger -t ${0##*/} "archiving process results: $MAILPRE initial, $MAILAFT current, $MAILARC archived" fi