Parsing IMAP folders using Ruby

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’ ( 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 ='log.txt')

server = "MY SERVER NAME"
user = "MY LOGIN"
password = "MY PASSWORD"
folders = ["folder_name_1","folder_name_2","etc"]
target_domain = ""
since_date = "1-Jan-2007"

#login to the IMAP server
imap ="Logging in...")
imap.login(user, password)

#Iterate through each folder specified above
folders.each do |folder|"selecting folder #{folder}...")

  #Create a new array to hold the addresses
  addresses =["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) do |to|
      if"Matched #{target_domain}, writing #{to.mailbox}@#{}")
        addresses << to.mailbox + "@" +

  #open a file to writing (calling it something sensible)
  out ="#{folder.gsub(" ","_")}_uniques","w")
  #Weed out dupes
  #and stick the result into the file
  addresses.each { |a|
    out.puts a
  #close the file

#log out of the IMAP server

(Props to this Devdaily script for the initial idea)

Your comments on this article

Share your thoughts using the form below. I'd love to hear from you. Comments are hosted using Disqus.

(Alternatively, get in touch with me here)


Possibly Related

(Based on the tag(s) and programming)