Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/thoughtbot/griddler

Simplify receiving email in Rails (deprecated)
https://github.com/thoughtbot/griddler

Last synced: about 2 months ago
JSON representation

Simplify receiving email in Rails (deprecated)

Awesome Lists containing this project

README

        

## Deprecated as of June 6, 2024

Griddler has been deprecated in favor of [ActionMailbox](https://guides.rubyonrails.org/action_mailbox_basics.html) since this is built into Rails now.

Griddler
========

### Receive emails in your Rails app

Griddler is a Rails engine that provides an endpoint for services that convert
incoming emails to HTTP POST requests. It parses these POSTs and hands off a
built email object to a class implemented by you.

Tutorials
---------

* SendGrid wrote a
[great tutorial](https://sendgrid.com/blog/receiving-email-in-your-rails-app-with-griddler/)
on integrating Griddler with your application.
* We have our own blog post on the subject over at
[Giant Robots](https://robots.thoughtbot.com/griddler-is-better-than-ever).

Installation
------------

1. Add `griddler` and an [adapter] gem to your application's Gemfile
and run `bundle install`.

[adapter]: #adapters

2. A route is needed for the endpoint which receives `POST` messages. To add the
route, in `config/routes.rb` you may either use the provided routing method
`mount_griddler` or set the route explicitly. Examples:

```ruby
# config/routes.rb

# mount using default path: /email_processor
mount_griddler

# mount using a custom path
mount_griddler('/email/incoming')

# the DIY approach:
post '/email_processor' => 'griddler/emails#create'
```

### Configuration Options

An initializer can be created to control some of the options in Griddler.
Defaults are shown below with sample overrides following. In
`config/initializers/griddler.rb`:

```ruby
Griddler.configure do |config|
config.processor_class = EmailProcessor # CommentViaEmail
config.email_class = Griddler::Email # MyEmail
config.processor_method = :process # :create_comment (A method on CommentViaEmail)
config.reply_delimiter = '-- REPLY ABOVE THIS LINE --'
config.email_service = :sendgrid # :cloudmailin, :postmark, :mandrill, :mailgun
end
```

| Option | Meaning
| ------ | -------
| `processor_class` | The class Griddler will use to handle your incoming emails.
| `email_class` | The class Griddler will use to represent an incoming e-mail. It must support an initializer that receives a hash as the only argument. We recommend inheriting it from Griddler::Email or checking this class to see all the methods it responds to.
| `processor_method` | The method Griddler will call on the processor class when handling your incoming emails.
| `reply_delimiter` | The string searched for that will split your body. You can also supply an array of string - useful if you need translated versions of the delimiter
| `email_service` | Tells Griddler which email service you are using. The supported email service options are `:sendgrid` (the default), `:cloudmailin` (expects multipart format), `:postmark`, `:mandrill` and `:mailgun`. You will also need to have an appropriate [adapter] gem included in your Gemfile.

By default Griddler will look for a class named `EmailProcessor`. The class is
initialized with a `Griddler::Email` instance representing the incoming
email, and has a `process` method to actually process the email.
For example, in `./lib/email_processor.rb`:

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

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

# here's an example of model creation
user = User.find_by_email(@email.from[:email])
user.posts.create!(
subject: @email.subject,
body: @email.body
)
end
end
```

Griddler::Email attributes
--------------------------

| Attribute | Description
| -------------- | -----------
| `#to` | An array of hashes containing recipient address information. See [Email Addresses](#email-addresses) for more information.
| `#from` | A hash containing the sender address information.
| `#cc` | An array of hashes containing cc email address information.
| `#subject` | The subject of the email message.
| `#body` | The full contents of the email body **unless** there is a line in the email containing the string `-- REPLY ABOVE THIS LINE --`. In that case `.body` will contain everything before that line.
| `#raw_text` | The raw text part of the body.
| `#raw_html` | The raw html part of the body.
| `#raw_body` | The raw body information provided by the email service.
| `#attachments` | An array of `File` objects containing any attachments.
| `#headers` | A hash of headers parsed by `Mail::Header`, unless they are already formatted as a hash when received from the adapter in which case the original hash is returned.
| `#raw_headers` | The raw headers included in the message.
| `#to_h` | A hash of the above attributes.

### Email Addresses

Gridder::Email provides email addresses as hashes. Each hash will have the following
information of each recipient:

| Key | Value
| --- | -----
| `:token` | All the text before the email's "@". We've found that this is the most often used portion of the email address and consider it to be the token we'll key off of for interaction with our application.
| `:host` | All the text after the email's "@". This is important to filter the recipients sent to the application vs emails to other domains. More info below on the Upgrading to 0.5.0 section.
| `:email` | The email address of the recipient.
| `:full` | The whole recipient field (e.g., `Some User `).
| `:name` | The name of the recipient (e.g., `Some User`).

Testing In Your App
-------------------

You may want to create a factory for when testing the integration of Griddler
into your application. If you're using factory\_girl this can be accomplished
with the following sample factory:

```ruby
factory :email, class: OpenStruct do
# Assumes Griddler.configure.to is :hash (default)
to { [{ full: '[email protected]', email: '[email protected]', token: 'to_user', host: 'email.com', name: nil }] }
from { { token: 'from_user', host: 'email.com', email: '[email protected]', full: 'From User ', name: 'From User' } }
subject { 'email subject' }
body { 'Hello!' }
attachments { '0' }

trait :with_attachment do
attachments {[
ActionDispatch::Http::UploadedFile.new({
filename: 'img.png',
type: 'image/png',
tempfile: File.new("#{File.expand_path(File.dirname(__FILE__))}/fixtures/img.png")
})
]}
end
end
```

Bear in mind, if you plan on using the `:with_attachment` trait, that this
example assumes your factories are in `spec/factories.rb` and you have
an image file in `spec/fixtures/`.

To use it in your tests, build with `email = build(:email)`
or `email = build(:email, :with_attachment)`.

Adapters
--------

Depending on the service you want to use Griddler with, you'll need to add an
adapter gem in addition to `griddler`.

| Service | Adapter
| ------- | -------
| sendgrid | [griddler-sendgrid]
| cloudmailin | [griddler-cloudmailin]
| mandrill | [griddler-mandrill]
| mailgun | [griddler-mailgun]
| postmark | [griddler-postmark]
| sparkpost | [griddler-sparkpost]
| ses (amazon)| [griddler-amazon_ses]

[griddler-sendgrid]: https://github.com/thoughtbot/griddler-sendgrid
[griddler-cloudmailin]: https://github.com/thoughtbot/griddler-cloudmailin
[griddler-mandrill]: https://github.com/wingrunr21/griddler-mandrill
[griddler-mailgun]: https://github.com/bradpauly/griddler-mailgun
[griddler-postmark]: https://github.com/r38y/griddler-postmark
[griddler-sparkpost]: https://github.com/PrestoDoctor/griddler-sparkpost
[griddler-amazon_ses]: https://github.com/ccallebs/griddler-amazon_ses

Writing an Adapter
------------------

Griddler can theoretically work with any email => POST service. In order to work
correctly, adapters need to have their POST parameters restructured.

`Griddler::Email` expects certain parameters to be in place for proper parsing
to occur. When writing an adapter, ensure that the `normalized_params` method of
your adapter returns a hash with these keys:

| Parameter | Contents
| --------- | --------
| `:to` | The recipient field
| `:from` | The sender field
| `:subject` | Email subject
| `:text` | The text body of the email
| `:html` | The html body of the email, or an empty string
| `:attachments` | Array of attachments to the email. Can be an empty array.
| `:headers` | The raw headers of the email. **Optional**.
| `:charsets` | A JSON string containing the character sets of the fields extracted from the message. **Optional**.

All keys are required unless otherwise stated.

Adapters should be provided as gems. If you write an adapter, let us know and we
will add it to this README. See [griddler-sendgrid] for an example
implementation.

Credits
-------

Griddler was written by Caleb Hearth and Joel Oliveira.

Thanks to our [contributors](https://github.com/thoughtbot/griddler/contributors)!

## About thoughtbot

![thoughtbot](https://thoughtbot.com/thoughtbot-logo-for-readmes.svg)

This repo is maintained and funded by thoughtbot, inc.
The names and logos for thoughtbot are trademarks of thoughtbot, inc.

We love open source software!
See [our other projects][community].
We are [available for hire][hire].

[community]: https://thoughtbot.com/community?utm_source=github
[hire]: https://thoughtbot.com/hire-us?utm_source=github