MailArchiveScript

From Hinterlands

Jump to: navigation, search

An automatic email archiving script

I get a lot of email. Much of that comes from the various mailing lists I am on for various projects and LUGs that I'm involved with. I also like to keep mail around for later reference as searching my IMAP folder is generally easier than searching mailman archives online. I structure my mailing list mail and mail archives like this:


  • INBOX
    • lists
      • foolist
      • otherlist
      • thislist
      • thatlist
    • Archive
      • 2009
        • foolist
        • otherlist
        • thislist
        • thatlist
      • 2010
        • foolist
        • otherlist
        • thislist
        • thatlist


I thought it would be useful to write a script to automatically handle transferring mail from the main list folder into the Archive folder. Doing so manually is a bit tedious given the number of lists I have to deal with. Here's a bit of perl that does just this.


#!/usr/bin/perl

use strict;
use warnings;
use Mail::IMAPClient;
use IO::File;
use IO::Socket::SSL;
use DateTime;
use DateTime::Format::Mail;


my $imap = Mail::IMAPClient->new(
        Server=> 'localhost',
        User => '<username>',
        Password => '<password>',
        Authmechanism  => 'LOGIN',
        Socket   => IO::Socket::SSL->new(
                Proto    => 'tcp',
                PeerAddr => 'localhost',
                PeerPort => 993, 
        ),
);

if (!defined($imap)) { die "IMAP Login Failed"; }

my $sourcefolder="INBOX.lists.";
my $archivefolder="Archive";
my $archivedays=30;


my @folders = $imap->folders;
@folders = grep /^$sourcefolder/,@folders;


foreach my $folder (@folders){
        $imap->expunge;
        print "$folder: ";
        $imap->select($folder);
        my @messages=$imap->search('ALL');
        print scalar @messages . "\n";

        foreach my $i (@messages){
                my $msgdate = $imap->get_header($i,"Date");
                $msgdate=~s/\(.*\)//;
                $msgdate=~s/\s+/ /g;
                my $dtfm=DateTime::Format::Mail->new->loose;
                my $msgdatetime = $dtfm->parse_datetime($msgdate);
                my $year=$msgdatetime->year;
                my $destfolder=$folder;
                $destfolder=~s/.*\.//;
                $destfolder="$archivefolder.$year.$destfolder";
                if (!$imap->exists($destfolder)) { 
                        $imap->create($destfolder);
                        $imap->subscribe($destfolder);
                }
                if ($msgdatetime < DateTime->now->subtract( days => $archivedays ) ) {
                        $imap->move($destfolder, $i) || die "Could not move: $@\n";
                }
        }
        $imap->expunge;
}

You can download this script here. Hope it's of use to someone.

Thanks to James Laver, Peter Corlett and Adrian Lai who all helped me understand the DateTime module better.

Personal tools