January 17th, 2005

diesel, learning, evil, sweeti

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.

diesel, learning, evil, sweeti

Bot::Infobot

Will hit CPAN sometime, err, real soon now. It's done. Apart from the Todo plugin because I really just couldn't be bothered. All I need to do is package various bit seperately and feed some patches back to Tom.

It features a pretty nifty brane slurper that extracts stuff from an infobot db and turns it into the form we expect.

Once the modules are installed (cue bitching about Perl being too library centric) you create a new directory and do something similar to

    % infobot-import dbi:mysql:dipsy  myuser mypasswd
    ************************************************************************
    
       Infobot brain slurper  
       - convert an Infobot brain to Bot::BasicBot::Pluggable
    
    ************************************************************************
    reticulating splines......................injoke successfully propagated
    extracting factoids..............found 115342 factoids with 203899 atoms
    extracting last seen........................................did 0 people
    extracting positive karma......................inserted 26031 real items
    extracting negative karma......................inserted 19892 real items
    fudging non explained karma.......................................fudged
    storing karma.......................................................done
    setting ignore list......................................adding 7 people
         
    Completed - have a nice day!

(For something as large as dipsy this might take up around 5 minutes.)

The drawback is that Bot::BasicBot::Pluggable uses Storable which can bloat up memory usage. I may have a look at pluggable backends for storage based on a tie interface.

Then you just run

    % infobot

and it looks in the current directory for an infobot.config file which should have variables set for

    nick
    server
    channels 

although all 3 have defaults et voila.

The config file is .ini style. Main bot variables are in the root whereas config values for plugins are in their own space

    nick     = dipsy2
    server   = london.irc.perl.org
    channels = #muttbot    
    [ Google ]
    key = mykey
    [ Aviation ] 
    taf_highlight_bold = on