procmail
[Top] [All Lists]

Re: Deleting 30 day old messages

1996-09-16 16:10:40
Hi there,

I have a question on sendmail.  The mailbox on some of the accounts
is growing at an exponential scale.  I want to be able to delete
30 day old messages from the mailbox.

Any suggestions on how to do it

With procmail, formail, lockfile, a small shell script, and a fairly
small procmail recipe file, you can accomplish this.  

The shell script, which I'll call "expiremail", you run against each
maildrop in /var/mail (or wherever the mail get's dropped).

The procmail recipe file will simply file the incoming mail, but will
also set the mtime of the filed message to match its date (from either
"From " or "Date:").

Hope this helps.
___________________________________________________________
Alan Stebbens <aks(_at_)sgi(_dot_)com>      http://reality.sgi.com/aks

*** Warning -- all this is untested; you must test and debug it yourself 

I'm using "sh" syntax; here's a command to expire mail older than 30
days in /var/mail:

    for drop in /var/mail/* ; do expiremail $drop 30  ; done

The "expiremail" shell script follows:

    #!/bin/sh
    # expiremail DROP DAYS
    # Expiremail frop DROP which is older than DAYS
    MAILDROP=${1:?'Missing maildrop name'}
    DAYS=${2:'Missing number of days'}
    TMPDIR=/tmp/expiremail.$$           # a temporary directory
    lockfile $MAILDROP.lock             # Lock the maildrop
    rm -rf $TMPDIR                      # in case it log left around
    mkdir $TMPDIR

    # The following command splits inthe mail in $MAILDROP into
    # its individual pieces, and runs the procmail filter "datemail"
    # on each piece.  As each mail is filed by "datemail", it also
    # has its mtime set to the date information in the message.
    formail -s procmail -m datemail $TMPDIR <$MAILDROP

    # Using the date information left by "datemail", we can now run
    # a find command against the mail in the temporary folder.
    # Any mail older than $DAYS, we remove.
    find $TMPDIR -mtime +$DAYS -exec rm -f {} \;

    # Okay, let's put the remaining mail back into the system maildrop
    trap '' 1 2 3                       # don't interrupt me
    cat /dev/null >$MAILDROP            # empty the maildrop

    # Warning!!! The following command will fail if there are too many 
    # pieces of mail, so it is commented out, but left for education
    #cat $TMPDIR/* >$MAILDROP           # put remaining mail back

    # The following is a little slower, but will work regardless of
    # how many pieces of mail there are
    ls $TMPDIR | xargs -i% cat $TMPDIR/% >>$MAILDROP

    # We're done mucking with the mail; release the lock
    rm -f $MAILDROP.lock
    rm -rf $TMPDIR                      # release our tmp directory
    exit

The procmail script "datemail" looks like this:

    #!procmail -m
    # Accept a mail oi STDIN, drop it into a FOLDER, and date the file
    # according to the date info in the message

    FOLDER=$1                   # where to drop the mail

    # The "From " header line looks like
    #
    #   From EMAILADDRESS(_at_)HOST Day Mmm DD hh:mm:ss YYYY
    #
    # The "Date:" header line looks like
    #
    #   Date: Day, DD Mmm YYYY HH:MM:SS ZONESHIFT

    DAY='(Mon|Tue|Wed|Thu|Fri|Sat|Sun)'
    MONTH='(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)'

    # Is there a "From " line?
    :0
    * ^From [^  ]+ *$DAY \/$MONTH [0-9]+ [0-9:]+ [0-9]+
    { 
        DATE = $MATCH
        MMM  = `echo $DATE | awk '{print $1}'`
        DD   = `echo $DATE | awk '{print $2}'`
        TIME = `echo $DATE | awk '{print $3}'`
        hh   = `echo $TIME | cut -d: -f1`
        mm   = `echo $TIME | cut -d: -f2`
        YYYY = `echo $DATE | awk '{print $4}'`
    }
    # If there is no "From " line, try using the "Date:" line.
    :0 E
    * ^Date: $DAY, \/[0-9]+ $MONTH [0-9]+ [0-9:]+
    {
        DATE = $MATCH
        DD   = `echo $DATE | awk '{print $1}'`
        MMM  = `echo $DATE | awk '{print $2}'`
        YYYY = `echo $DATE | awk '{print $3}'`
        TIME = `echo $DATE | awk '{print $4}'`
        hh   = `echo $TIME | cut -d: -f1`
        mm   = `echo $TIME | cut -d: -f2`
    }
    # If no From or Date, just drop the mail and be done with it
    :0 E
    $FOLDER/.
        
    # Okay, we have setup the date variables, let's convert the
    # month name into a number.
    :0
    * MMM ?? Jan
    { MM=01 }
    :0E
    * MMM ?? Feb
    { MM=02 }
    :0E
    * MMM ?? Mar
    { MM=03 }
    :0E
    * MMM ?? Apr
    { MM=04 }
    :0E
    * MMM ?? May
    { MM=05 }
    :0E
    * MMM ?? Jun
    { MM=06 }
    :0E
    * MMM ?? Jul
    { MM=07 }
    :0E
    * MMM ?? Aug
    { MM=08 }
    :0E
    * MMM ?? Sep
    { MM=09 }
    :0E
    * MMM ?? Oct
    { MM=10 }
    :0E
    * MMM ?? Nov
    { MM=11 }
    :0E
    * MMM ?? Dec
    { MM=12 }

    # Copy the mail to the named folder, using mh-style 
    :0c
    $FOLDER/.

    # Get the exact filename of the newly dropped mail
    FILE=$LASTFOLDER

    # Set the mtime on the file to match the mail's date
    JUNK=`touch -m $MM$DD$hh$mm $FILE`

    # We're all done!
    HOST

<Prev in Thread] Current Thread [Next in Thread>