?

Log in

No account? Create an account

Mon, Jan. 17th, 2005, 12:00 pm
Transferring mail to GMail

Someone on channel was muttering about transferring all their mail from where it currently was to Gmail and that they didn't want to use Mark Lyon's GML which is, shock horror, in Python.

Usually I'm against not using something just because it's not in your language of choice unless you've got a damn good reason. However when I realised that GML just used SMTP isntead of some proprietary GMail transport protocol I whipped this up.

    #!perl -w
    use strict;
    use Email::Folder;
    use Email::Send qw[MySendmail]; # preload mailer(s)
    my $gmail =   shift           || die "You must pass a gmail address\n";
    $gmail    =~  /\@gmail\.com/i || die "$gmail is not a gmail address\n";
    @ARGV                         || die "You must pass at least one mailbox\n";
    foreach my $mbox (@ARGV) {
        # open the folder
        my $folder = Email::Folder->new($mbox);
        unless ($folder) {
                print STDERR "Couldn't open $folder\n";
                next;
        }
        # attempt deliver each mail
        my $success = 0;
        my $fail    = 0;
        foreach my $mail ($folder->messages) {
            my $rv = send MySendmail => $mail, $gmail;
            if ($rv) {
                $success++;
            } else {
                $fail++;
            } 
        }
        # print some stats
        if ($success == 0 && $fail == 0) {
            print STDERR "$folder had no mails!\n";
        } else if ($success == 0) {
            print STDERR "We couldn't transfer any mails to Gmail - aborting :(\n";
            last;
        } else if ($fail == 0) {
            print STDERR "Transferred all $success mail(s) successfully\n"; 
        } else {
            print STDERR "Transferred $success mail(s) successfully ".
                         "but failed to transfer $fail mails :(\n";
        }
    }
    # custom Sendmail package to fake To: address
    package Email::Send::MySendmail;
    use strict;
    use vars qw[$SENDMAIL];
    $SENDMAIL ||= q[sendmail];
    sub send {
        my ($message, $address, @args) = @_;
    
        open SENDMAIL, "| $SENDMAIL -oi @args $address" or return undef;
        print SENDMAIL $message->as_string;
        close SENDMAIL;
    }
    1;

Which is hella ugly but for a 5 minute proof of concept it's not bad. As someone pointed out it be smarter about delivering mails - perhaps keeping a failure or success log when things fail to avoid duped or perhaps even checking at start up time what message-ids are already present. Meh. I don't even have a GMail account (which means this isn't even tested) - my Yahoo! brain-implant hasn't been removed yet.