Email on my Phone

I recently got myself a phone with a data plan (a Treo 700p to be exact), so that I can check my email when I am laptop-less and/or wifi-less.

Living in Canada, I’m subjected to absurdly expensive mobile data rates, so every byte is precious. My solution to this is to limit the amount of email data that goes to my phone as much as possible.

Here’s what I decided my email-to-phone system needed to do:

Filter out the bacn and spam

I only want to receive important personal mail on my phone - no bulk mail, no low-signal-to-noise mailing lists.

Remove HTML, attachments, images

Modern mail user agents make it possible to increase email size by a factor of 10 without adding any more relevant information. I want to be able to slim my email down to just the facts.

How it works

At the end of my Procmail script, I have a recipe that forwards any mail that has gotten by all the filters to a different account from which my phone is set to get mail.

:0c
| awk 'NR > 2' | ~/bin/plaintextforward.pl keith.grennan@example.com

That awk bit there strips out the extra header (From line) and sends the rest to my email-slimming script, ‘plaintextforward.pl’, which looks like this:

#!/usr/bin/perl
use strict;
use warnings;
use Mail::Message;
use IO::File;

die "usage: $0 to-address < msg" unless @ARGV;
my $to = shift @ARGV;

# flatten, and create alternative text/plain parts for any HTML parts
my $msg = Mail::Message->read(\*STDIN)->rebuild(
  extra_rules => ['flattenNesting', 'removeEmptyMultiparts','textAlternativeForHtml']);

# join all text/plain parts into one string, and discard the rest
my $body = join("\n", map($_->decoded, 
  grep(lc $_->get('Content-Type') eq 'text/plain', $msg->parts('RECURSE'))));

# make this string the body of the message
$body  = Mail::Message::Body->new(mime_type => 'text/plain', data => $body);
$msg->body($body);

# forward the message
$msg->head->set(To => $to);
my $out = IO::File->new("$ENV{HOME}/last-msg", 'w');
my $bounce = $msg->bounce(To => $to);
$bounce->print($out);
$bounce->send;

I use the Perl module Mail::Message to do all the processing. It creates plain text alternates to all HTML parts, if they don’t already exist, and then I gather up all the plain text parts and join them together, discarding everything else - this becomes the new message. Then it gets forwarded on to the phone account.

So that works pretty well, but I still have a problem - the backlog of mail building up in the phone mailbox. If I don’t check my phone mail for a while, I don’t want to get a flood of already-read messages. And I don’t want to have to log in to that other account and clean it up all the time. Solution - make a mail box emptying script that uses the POP3 protocol, ‘clearmail.pl’:

#!/usr/bin/perl
use strict;
use Mail::Box::POP3;
my $p = Mail::Box::POP3->new(username=>"keith.grennan", password=>"XXXXX", server_name=>"pop.example.com"); 
$_->delete for $p->messages;
$p->close(write => 'MODIFIED', force => 1);

I hook this script up to a shell script called ‘m’ that i use to invoke my mail reader so it gets run in the background whenever I open my mail client:

#!/bin/bash
clearmail.pl &
mutt

So I know that when I check my main mail account, I am clearing out my phone mail account.

Hope this helps my fellow Canadians, until we see some actually competitive mobile data rates.