Griddler is a tool that makes working with inbound emails in a Rails application very simple. Here are two helpful tutorials on how to configure and use it. There’s also quite a bit you’ll want to read up on regarding your transactional email service of choice; I use Postmark.

For the most part, grabbing an author and some content with Griddler is straightforward, and turning that into a content entry in Rails is a few controller lines away. However, I did find that parsing inbound data to do more complicated things—like assigning internal recipients and threading comments—was more of a challenge. Griddler gives access to all the usual email objects, like “to,” “from,” “subject,” “body,” etc. But that’s not exactly enough on its own to get really creative.

Email tokens are the key

In my case, I wanted to allow users to reply by email to task assignments and notes within a project management system. New notes on a task generated an email output along with a record of the note attached to the task itself. Users wanted to reply directly via email, instead of having to link into the application to respond.

For this, leveraging the email token was essential. The token is the part of an email address before the “@” symbol. It can be a hash or a custom string of hashes and terms, and if formatted properly can still be processed by a third-party transactional email service. In my example, Postmark uses a “+” sign to separate an assigned inbound email address from any custom data you want to pass to your application as an object.

My Rails mailer looked like this:

mail(:to => @recipients.join(", "),
     :reply_to => "[assigned_email_address]+#{@task.id}-#{@user.id}@inbound.postmarkapp.com",
     :subject => "New Note on: #{@object_name}",
     :template_path => 'notes_mailer',
     :template_name => 'note_notification_email')

The [assigned_email_address] value was a long string provided by Postmark. Using Griddler, I was able to parse the “reply_to” field to get everything I needed for threading and assigning notes:

/app/models/email_processor.rb

class EmailProcessor
  def initialize(email)
    @email = email
  end

  def process
    # all of your application-specific code here - creating models,
    # processing reports, etc

    author = User.find_by_email(@email.from[:email])

    token_items = @email.to.first[:token].match(/\+(.*)-(.*)/i)
    token_task_id, token_recipient_id = token_items.captures

    note = Note.create!({ content: @email.body, author_id: author.id, ts: DateTime.now, task_id: token_task_id })
    UserNote.create!({ note_id: note.id, user_id: token_recipient_id })
  end
end

There’s more you can do to conditionalize and check during the token captures, which I’d recommend. This thread was helpful to me in formatting the match expression. And this handy regex tester saved me a big headache. (Since passing items to email and back into the app involves quite a few points of failure, ruling out regex formatting separately is an important step.)