Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/honeybadger-io/incoming

Incoming! helps you receive email in your Rack apps.
https://github.com/honeybadger-io/incoming

Last synced: about 2 months ago
JSON representation

Incoming! helps you receive email in your Rack apps.

Awesome Lists containing this project

README

        

Incoming!
-----------

### Receive email in your Rack apps.

Incoming! receives a `Rack::Request` and hands you a [`Mail::Message`](https://github.com/mikel/mail/), 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](https://www.honeybadger.io/).

[![Build Status](https://travis-ci.org/honeybadger-io/incoming.png)](https://travis-ci.org/honeybadger-io/incoming)
[![Gem Version](https://badge.fury.io/rb/incoming.png)](http://badge.fury.io/rb/incoming)

## Installation

1. Add Incoming! to your Gemfile and run `bundle install`:

```ruby
gem "incoming"
```

2. Create a new class to receive emails (see examples below)

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

## SendGrid Example

```ruby
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 [email protected] with subject "hello world"
```

[Sendgrid API reference](http://sendgrid.com/docs/API_Reference/Webhooks/parse.html)

## Mailgun Example

```ruby
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 [email protected] with subject "hello world"
```

[Mailgun API reference](http://documentation.mailgun.net/user_manual.html#receiving-messages)

## Postmark Example

```ruby
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 [email protected] with subject "hello world"
```

[Postmark API reference](http://developer.postmarkapp.com/developer-inbound.html)

## CloudMailin Example

Use the Raw Format when setting up your address target.

```ruby
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 [email protected] with subject "hello world"
```

[CloudMailin API reference](http://docs.cloudmailin.com/http_post_formats/)

## 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:

```ruby
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 [email protected] with subject "hello world"
```

[Mandrill API reference](http://help.mandrill.com/entries/22092308-What-is-the-format-of-inbound-email-webhooks-)

## Postfix Example

```ruby
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 [email protected] 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:

```ruby
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 [email protected] 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 `[email protected]` 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

```ruby
# 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
```

```ruby
# config/routes.rb
Rails.application.routes.draw do
post "/emails" => "emails#create"
end
```

```ruby
# spec/controllers/emails_controller_spec.rb
require "spec_helper"

describe EmailsController, "#create" do
it "responds with success when request is valid" do
allow(EmailReceiver).to receive(:receive).and_return(true)
post :create
expect(response.success?).to eq(true)
expect(response.body).to eq(%({"status":"ok"}))
end

it "responds with 403 when request is invalid" do
allow(EmailReceiver).to receive(:receive).and_return(false)
post :create
expect(response.status).to eq(403)
expect(response.body).to eq(%({"status":"rejected"}))
end
end
```

## TODO

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

## Contributing

1. Fork it.
2. Create a topic branch `git checkout -b my_branch`
3. Commit your changes `git commit -am "Boom"`
3. Push to your branch `git push origin my_branch`
4. Send a [pull request](https://github.com/honeybadger-io/incoming/pulls)

## License

Incoming! is free software, and may be redistributed under the terms specified
in the MIT-LICENSE file.