Send in your Unix questions today! |
See additional Unix tips and tricks
Have you ever come across one of those Unix servers that has been
running for years with hardly a blip of downtime and noticed that
root's mailbox still contains mail that was sent several years
ago? While messages sent to root often provide important messages
from applications and processes running on the system, mail that
has been sitting around for years is rarely of any current interest.
If you want to remove mail that arrived in previous years from
root's inbox or the inbox of a user who doesn't want to clean up
years' worth of mail himself, here's a simple Perl script to help
you do just that. I call it "trimbox".
The trimbox script will look for the inbox to be trimmed down on the
command line or will prompt the user to supply the file name. It
makes no difference if the user types in a full path, such as
/var/mail/jdoe, or just the username. The script should be
customized with the location of the inboxes (in this case, /var/mail)
and strips this path from the information provided by the user to
derive the username as needed with this line:
$inbox=~s/$MBOXDIR\///; # strips off path
To identify each piece of mail and its date of origin, the trimbox
script looks for lines that begin with "From ". That extra blank
inside the quotes is important as this marks the beginning of a
new message. For example, the beginning of a new piece of email
might look like this:
From eric Sun Mar 18 17:18:31 2001
Of course, Perl's way of representing these lines is /^From /. Yes,
there's certainly a lot more text on the line, but the existence
of the word "From" followed by a blank should be all we need to
determine that we are looking at a new message, so this is all we
will look for. Just to be on the safe side, however, a subsequent
line is going to verify that a year was also found on the end of the
line.
When trimbox finds the beginning of a new message, it grabs the
year from the end of the line and stores it in $year. It can then
determine whether or not this message is one we want to save or one
we want to discard. If $year has no content, we assume that the
"From" line was bogus and move on. I have seen lines in mailboxes
that begin with "From " and are not the beginnings of new messages,
so we have to be a little careful. If we encounter one of these
lines, we want to continue whatever we were doing, whether we were
copying the current message or skipping over it.
This trimbox script looks at the beginning of every message, even
though the messages should be in date order inside the mail file,
just in case the inbox has been corrupted in some way. Any messages
that have arrived during or later than the year of interest are then
written to a temporary file. It does this by toggling the $copying
variable on and off.
By the time the script has reached the end of the original inbox,
it has built a temporary inbox containing only the messages that
should be retained and stored that file in /tmp. It then displays a
listing of the current and new files and asks the user whether the
current file should be overwritten with the new one. If the user
responds by typing "yes", the script overwrites the original file.
If the user responds in any other way, the script asks whether the
new file should be deleted and does so if the user types "yes".
Here's an example of running the script.
boson> trimbox
inbox> jdoe
current file:
-rw-r----- 1 jdoe mail 29532928 Jun 22 15:34 /var/mail/jdoe
temporary file:
-rw-rw-r-- 1 jdoe staff 1173110 Jun 22 15:51 /tmp/jdoe17355
Want to overwrite the current file?> yes
new file:
-rw-r----- 1 jdoe mail 1173110 Jun 22 15:51 /var/mail/jdoe
The trimbox script should run fairly quickly and create a trimmed
inbox for any selected user. Possible enhancements to this script
might involve writing the older messages to an archive file rather
than deleting them entirely.
Here's trimbox:
#!/usr/bin/perl -w
# where are inboxes?
$MBOXDIR="/var/mail"; # change as needed
# remove mail prior to year
$KEEPYEAR=2007; # change as needed
# get inbox name
if ( $#ARGV == 0 ) {
$inbox=$ARGV[0];
} else {
print "inbox> ";
$inbox=<STDIN>;
chomp($inbox);
}
$inbox=~s/$MBOXDIR\///; # strips off path if included
$tmpbox="/tmp/$inbox$$";
$copying="off";
# open files and verify
open(INBOX, "<$MBOXDIR/$inbox") || die("Could not open $inbox");
open(TMPBOX, ">$tmpbox") || die("Could not open $tmpbox");
while (<INBOX>) {
# Look for lines like this: From eric Sun Mar 18 23:45:01 2001
if ( /^From / ) {
($year)=/(\d{4}$)/;
if ( $year ) { # if a year is present
if ( $year >= $KEEPYEAR ) {
$copying="on";
} else {
$copying="off";
}
}
}
if ( $copying eq "on" ) {
print TMPBOX $_;
}
}
close(INBOX);
close(TMPBOX);
print "current file:\n";
system("ls -l $MBOXDIR/$inbox");
print "temporary file:\n";
system("ls -l $tmpbox");
print "Want to overwrite the current file?> ";
$ans=<STDIN>;
chomp($ans);
if ( $ans eq "yes" ) {
system("cp $tmpbox $MBOXDIR/$inbox");
print "new file:\n";
system("ls -l $MBOXDIR/$inbox");
} else {
print "Do you want to remove the temporary file?> ";
$ans=<STDIN>;
chomp($ans);
if ( $ans eq "yes" ) {
system("rm $tmpbox");
}
}
|