Fri Jan 18 15:13:02 IST 2008

mutt addressbook collector

I have a tiny helper script to collect addresses from my outgoing emails, and add them to my .aliases file. I only care about people who I send out email to, and I've noticed that collecting addresses from incoming emails leads to too much noise. Although I could set it up to *not* pick up addresses from spam and mails which have my firstname (ecommerce stuff which is NOT spam). But that's for later.

Here's the helper (I use msmtp for sending out email as evindent in my mutt config) :

#!/usr/bin/perl -w
use strict;

my $home = "/home/gera";
my $msmtp = "/usr/bin/msmtp";
my $aliasfile = "/home/gera/.aliases";

open ALIASES, "<$aliasfile" or quit("cannot open $aliasfile : $!");
my %aliases = ();
my %collected = ();
while() {
	s/#.*$//;
	chomp;
	next unless $_;
	my ($nick, $name, $email) = ($_ =~ /^alias\t+(\S+)\t+(.+?)\t+<(\S+)>/);
	quit("cannot parse $_") unless ($nick && $name && $email);
	$aliases{$email} = {
		"nick"	=> $nick,
		"name"	=> $name,
	};
}
close ALIASES;

# now read the email contents and try to figure out the addresses
local $/ = undef;	# slurp mode

my $email = ;
my ($to) = ($email =~ /^To:(.*)$/m);
my ($cc) = ($email =~ /^Cc:(.*)$/m);
my @addresses = split( /,/, "$to,$cc");
foreach my $address (@addresses) {
	chomp;
	next unless $address;
	# the address is of the form of "Firstname Lastname "
	# or "" or "email@address"
	my ($name, undef, $email) = ($address =~ /^(.*?)\s*(<|)([^<>]*?)(>|)$/);
	quit("cannot parse $address") unless $email;
	next if exists $aliases{$email};
	# else, add it to the aliases.
	# See if everything is populated. We'll have to invent a nickname here
	if(! $name) {
		($name = $email) =~ s/\@.*//;
	}
	my $nick;
	($nick = lc $name) =~ tr/ //d;
	$collected{$email} = {
		"nick"	=> $nick,
		"name"	=> $name,
	};
}

if(scalar(keys %collected) != 0) {
	# save to tmp file
	open ALIASES, ">$aliasfile.new.$$" or quit("cannot open $aliasfile.new.$$ : $!");
	foreach my $email (sort keys %aliases) {
		my $nick = $aliases{$email}->{nick};
		my $name = $aliases{$email}->{name};
		print ALIASES "alias	$nick	$name	<$email>\n";
	}
	print ALIASES "\n\n#collected email addresses\n\n";
	foreach my $email (sort keys %collected) {
		my $nick = $collected{$email}->{nick};
		my $name = $collected{$email}->{name};
		print ALIASES "alias	$nick	$name	<$email>\n";
	}
	close ALIASES;

	# move tmp file to $aliasfile
	rename("$aliasfile.new.$$", $aliasfile);
}

# send mail onward
open(MSMTP, "|$msmtp @ARGV") or quit("cannot open pipe to $msmtp @ARGV : $!");
print MSMTP $email;
close(MSMTP) or quit("cannot close pipe to MSMTP : $!");

exit(0);


sub quit
{
	my $msg = shift;
	open LOGFILE, ">$home/.msmtp_helper.log" || die "cannot open log file : $!";
	print LOGFILE "$msg\n";
	close LOGFILE;
	exit(127);
}

Edit : fixed formatting.


Posted by gera | Permanent Link | Categories: tricks, perl, code, hacks | [ 0 ]