Parsing IMAP folders using Ruby

27 March 2008 (07.27 PM)

Output from a ruby appOne of the advantages of running my own mail server for me and Kate to use is that I can create custom email address schemes to thwart the attempts of heinous spammers.

Without divulging our strategy (for fear—perhaps rather self-aggrandisingly—of immediately being swamped with a deluge of unwanted mail) , it means that Kate and I have a larger-than-normal number of incoming addresses to contend with. Some of these are single-use, so I can’t always remember every address I’ve used.

I’m still trying to decide how best to manage our emails when we’re in Uganda. The most likely solution will be to use my hosting at Joyent, maybe in conjunction with some pre-delivery spam scanning from Postini (now part of Google). Whatever the solution, it won’t involve using our home server running Postfix, so I thought it would be useful to see just how many addresses I’ve used in the last year or so.

I’m a bit of a Ruby fan, so I’ve written a quick script to go through a variable number of IMAP folders, looking for a ‘target domain’ (edjones.org in my case) in the ‘to’ address field. When it finds that address, it’ll store it, de-duplicate the resulting list and stick them in a sensibly-named folder.

I’ve used this on Dovecot IMAP, my server of choice. YMMV, as they say. Feel free to do whatever you like with this script.



require ‘net/imap’
require ‘logger’

log = Logger.new(‘log.txt’)

#settings
server = “MY SERVER NAME
user = “MY LOGIN
password = “MY PASSWORD
folders = [“folder_name_1”,“folder_name_2”,“etc”]
target_domain = “edjones.org”
since_date = “1-Jan-2007”

#login to the IMAP server
imap = Net::IMAP.new(server)
log.info(“Logging in…”)
imap.login(user, password)

#Iterate through each folder specified above
folders.each do |folder| log.info(“selecting folder #{folder}…”) imap.select(folder)

#Create a new array to hold the addresses addresses = Array.new imap.search([“SINCE”, since_date]).each do |msg_id| env = imap.fetch(msg_id, “ENVELOPE”).first.attr[“ENVELOPE”] # Iterate through each to address to find mine (the target domain) env.to.each do |to| if to.host.match(target_domain) log.info(“Matched #{target_domain}, writing #{to.mailbox}@#{to.host}”) addresses << to.mailbox + “@” + to.host end end end #open a file to writing (calling it something sensible) out = File.open(”#{folder.gsub(” “,”_”)}_uniques”,“w”) #Weed out dupes addresses.uniq! #and stick the result into the file addresses.each { |a| out.puts a } #close the file out.close end

#log out of the IMAP server
imap.logout
imap.disconnect

(Props to this Devdaily script for the initial idea)

PHOTOS

A bontebok Me Rocks Windpump Our house Fynbos Rolling Farmland The valley of Kisiizi Walking in the Yorkshire Dales Girl with bronze statue, Singapore

More photos at Flickr