Ruby / Gems / Incoming!



Introduction

Receive email in your Rack apps.

Incoming! receives a Rack::Request and hands you a Mail::Message, much like ActionMailer::Base.receive does with a raw email.

We currently support the following services:

  • SendGrid
  • Mailgun
  • Postmark
  • CloudMailin
  • Mandrill
  • Any mail server capable of routing messages to a system command

Brought to you by :zap: Honeybadger.io, painless Rails exception tracking.


Installation

  1. Add Incoming! to your Gemfile and run bundle install:
gem 'incoming'
  1. Create a new class to receive emails (see examples below)

  2. Implement an HTTP endpoint to receive HTTP post hooks, and pass the request to your receiver. (see examples below)


SendGrid example

class EmailReceiver < Incoming::Strategies::SendGrid
  def receive(mail)
    %(Got message from #{mail.to.first} with subject "#{mail.subject}")
  end
end

req = Rack::Request.new(env)
result = EmailReceiver.receive(req) # => Got message from whoever@wherever.com with subject "hello world"

Sendgrid API reference


Mailgun example

class EmailReceiver < Incoming::Strategies::Mailgun
  setup :api_key => 'asdf'

  def receive(mail)
    %(Got message from #{mail.to.first} with subject "#{mail.subject}")
  end
end

req = Rack::Request.new(env)
result = EmailReceiver.receive(req) # => Got message from whoever@wherever.com with subject "hello world"

Mailgun API reference


Postmark example

class EmailReceiver < Incoming::Strategies::Postmark
  def receive(mail)
    %(Got message from #{mail.to.first} with subject "#{mail.subject}")
  end
end

req = Rack::Request.new(env)
result = EmailReceiver.receive(req) # => Got message from whoever@wherever.com with subject "hello world"

Postmark API reference


CloudMailin example

Use the Raw Format when setting up your address target.

class EmailReceiver < Incoming::Strategies::CloudMailin
  def receive(mail)
    %(Got message from #{mail.to.first} with subject "#{mail.subject}")
  end
end

req = Rack::Request.new(env)
result = EmailReceiver.receive(req) # => Got message from whoever@wherever.com with subject "hello world"

CloudMailin API reference


Mandrill example

Mandrill is capable of sending multiple events in a single webhook, so the Mandrill strategy works a bit differently than the others.

Namely, the .receive method returns an Array of return values from your #receive method for each inbound event in the payload. Otherwise, the implementation is the same:

class EmailReceiver < Incoming::Strategies::Mandrill
  def receive(mail)
    %(Got message from #{mail.to.first} with subject "#{mail.subject}")
  end
end

req = Rack::Request.new(env)
result = EmailReceiver.receive(req) # => ['Got message from whoever@wherever.com with subject "hello world"', '...']

Mandrill API reference


Postfix example

class EmailReceiver < Incoming::Strategies::HTTPPost
  setup :secret => '6d7e5337a0cd69f52c3fcf9f5af438b1'

  def receive(mail)
    %(Got message from #{mail.to.first} with subject "#{mail.subject}")
  end
end

req = Rack::Request.new(env)
result = EmailReceiver.receive(req) # => Got message from whoever@wherever.com with subject "hello world"
# /etc/postfix/virtual
  @example.com http_post

  # /etc/mail/aliases
  http_post: "|http_post -s 6d7e5337a0cd69f52c3fcf9f5af438b1 http://www.example.com/emails"

Qmail example:

class EmailReceiver < Incoming::Strategies::HTTPPost
  setup :secret => '6d7e5337a0cd69f52c3fcf9f5af438b1'

  def receive(mail)
    %(Got message from #{mail.to.first} with subject "#{mail.subject}")
  end
end

req = Rack::Request.new(env)
result = EmailReceiver.receive(req) # => Got message from whoever@wherever.com with subject "hello world"

To setup a global incoming email alias:

# /var/qmail/alias/.qmail-whoever - mails to whoever@ will be delivered to this alias.
 |http_post -s 6d7e5337a0cd69f52c3fcf9f5af438b1 http://www.example.com/emails

Domain-specific incoming aliases can be set as follows:

#/var/qmail/control/virtualdomains
 example.com:example

 #~example/.qmail-whoever
 |http_post -s 6d7e5337a0cd69f52c3fcf9f5af438b1 http://www.example.com/emails

Now mails to whoever@example.com will be posted to the corresponding URL above. To post all mails for example.com, just add the above line to ~example/.qmail-default.


Example Rails controller

# app/controllers/emails_controller.rb
 class EmailsController < ActionController::Base
   def create
     if EmailReceiver.receive(request)
       render :json => { :status => 'ok' }
     else
       render :json => { :status => 'rejected' }, :status => 403
     end
   end
 end
# config/routes.rb
 Rails.application.routes.draw do
   post '/emails' => 'emails#create'
 end
# spec/controllers/emails_controller_spec.rb
 require 'spec_helper'
 
 describe EmailsController, '#create' do
   it 'responds with success when request is valid' do
     EmailReceiver.should_receive(:receive).and_return(true)
     post :create
     response.should be_success
     response.body.should eq '{"status":"ok"}'
   end
 
   it 'responds with 403 when request is invalid' do
     EmailReceiver.should_receive(:receive).and_return(false)
     post :create
     response.status.should eq 403
     response.body.should eq '{"status":"rejected"}'
   end
 end

TODO

  1. Provide authentication for all strategies where possible (currently only Mailgun requests are authenticated.)

License

Incoming! is Copyright 2013 © Joshua Wood and Honeybadger Industries LLC. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.