Goodbye OtherInbox, hello Gmail IMAP via Ruby

For a while now, I’ve used (and, for the most part, loved) OtherInbox. It’s a really handy service – just create a new email address for each site instead of giving out your main address for those sites to sell and then spam. But I’ve been using it since the beta, and have been increasingly annoyed by certain features that have been removed or withheld from the free account. For example, IMAP access is only available to pay accounts, as is the ability to read any message you received more than 30 days ago.

I’m not faulting OtherInbox for this – I get it, they need to make a profit. Heck, I would probably take the same approach they have. But, I finally decided there was a better solution for me. So goodbye OtherInbox, hello to the exact same functionality (and then some) via Gmail. Let me explain…

EDITS: 18 July 2009 – I’ve made some changes to the script to cover some edge case errors.

So, I thought about my approach for a few minutes and decided that I ought to be able to do the same thing OtherInbox does by using Google Apps for my domain and a simple IMAP poller. The first step was simple: just signup for Google Apps (which I had already done some time ago) and setup a catch-all email address (see this page for details). So, with that done, it was on to some scripting.

I have to be honest: I thought this was going to be harder than it was. But, as it turns out, Ruby already offers a really simple way to interact with an IMAP server (Net::IMAP). After a little digging through the Net::IMAP documentation, I was off and running.

All I needed to do was write a script that would poll the IMAP server every so often checking for new messages. When the script noticed that there were new messages, it then just needed to move each of those messages to the proper mailbox (i.e. apply the proper label in Gmail).

And here’s the end result:


#!/usr/bin/env ruby

require 'rubygems'
require 'net/imap'

CONFIG = {
  :host     => 'imap.gmail.com',
  :username => 'catch.all@domain.com',
  :password => 'my-pa55word',
  :port     => 993,
  :ssl      => true
}

$imap = Net::IMAP.new( CONFIG[:host], CONFIG[:port], CONFIG[:ssl] )
$imap.login( CONFIG[:username], CONFIG[:password] )

# select the INBOX as the mailbox to work on
$imap.select('INBOX')

messages_to_archive = []

# retrieve all messages in the INBOX that
# are not marked as DELETED (archived in Gmail-speak)
$imap.search(["NOT", "DELETED"]).each do |message_id|
  # the mailbox the message was sent to
  # addresses take the form of {mailbox}@{host}
  mailbox = $imap.fetch(message_id, 'ENVELOPE')[0].attr['ENVELOPE'].to[0].mailbox

  # give us a prettier mailbox name -
  # this is the label we'll apply to the message
  mailbox = mailbox.gsub(/([_\-\.])+/, ' ').downcase
  mailbox.gsub!(/\b([a-z])/) { $1.capitalize }

  begin
    # create the mailbox, unless it already exists
    $imap.create(mailbox) unless $imap.list('', mailbox)
  rescue Net::IMAP::NoResponseError => error
  end

  # copy the message to the proper mailbox/label
  $imap.copy(message_id, mailbox)

  messages_to_archive << message_id
end

# archive the original messages
$imap.store(messages_to_archive, "+FLAGS", [:Deleted]) unless messages_to_archive.empty?

$imap.logout

After setting this up as a simple cron task to poll the server and cleanup my inbox periodically, I can get the exact same functionality as OtherInbox. Plus, I can access the account via IMAP through something like Mail.app, and I can read all my messages regardless of how old they are. Not only that, but I can use the great Gmail web UI (which is much better than the one offered by OtherInbox).

With that script setup to poll the gmail IMAP server, there was only one obstacle left: responding to email from each of the different addresses. Fortunately, Gmail makes this super easy as well. While logged in to Gmail, just go to “Settings” > ”Accounts” > ”Add another email address you own” — it couldn’t be easier.

Posted by Phil Burrows on Jul 17, 2009

Comments

  1. Alex Judge Monday, July 20, 2009

    Hi Phil,

    This is a great setup! With your experience and knowledge of Ruby on Rails, this seems like a good solution for your email integration needs. If you can write your own code, run your own server, the world is your oyster!

    My two biggest concerns with that setup would be having to run your own server (it's nice to let someone else worry about it) and having to manually add additional sending addresses for each different address you use. I believe Gmail has a limit on how many it will let you set up so at some point you're stuck.

    We've got some other features that you might find helpful over Gmail as well - automatically managing mailing lists, sorting Craigslist postings and synchronizing important dates in your email with your calendar are just a few examples. We've got more coming down the pipe!

    As Josh told you on Twitter, we gave you a Premium subscription just to try and tempt you to give OIB another try!

    Sincerely,

    Alex Judge
    OtherInbox

Post a comment