July 6, 2017
Monkey Patching Griddler to Add Mailgun Properties
Griddler is a great gem to consider if your Rails application needs to receive email messages. Griddler works by creating an endpoint to receive webhooks from email services like SendGrid and Postmark. Since each email service formats their webhook payloads differently, Griddler adapts each incoming message into a generic Email
class instance.
While this generic class makes it really easy to switch email services without rewriting your code, it does require you to discard any data from incoming messages that Griddler doesn’t include in its Email
class. For example, I prefer to use Mailgun due to its addition a stripped-text
parameter, which automatically removes quoted text and signature blocks from emails.
When using Griddler out of the box, messages received from Mailgun don’t include the stripped-text
parameter since it’s not a common email field. Luckily, we can use monkey patching to cleanly extend Griddler and add this functionality just for our app.
Install Griddler
Let’s first install Griddler in our Rails app by adding the griddler-mailgun
gem to the end of the Gemfile
:
Run bundle install
to install the Griddler gem with the Mailgun adapter. Next, add the default Griddler endpoint to app/config/routes.rb
:
This will create an endpoint at /email_processor
- Mailgun will send emails to this route, and they’ll be processed by Griddler.
We also need to add an initializer file to configure Griddler, so create a new file named app/config/initializers/griddler.rb
with the following code:
Finally, we’ll need to create a class named EmailProcessor
- Griddler needs this to be defined in our app, and it’s where you’ll eventually process email messages after they arrive. You can place this file wherever you prefer in your Rails project, but let’s create it at lib/email_processor.rb
:
In the process
method above, the @email
object will contain an email message that was sent from Mailgun, arrived at your app’s /email_processor
endpoint, and was processed by Griddler. You can easily access the contents of the message as attributes, such as @email.from
and @email.body
.
Now let’s extend Griddler to handle Mailgun’s stripped-text
attribute, which is currently simply dropped when an email is processed.
Extending the Mailgun Adapter
Let’s first take a look at the source code of the Griddler Mailgun adapter class, which processes webhook payloads as they arrive from Mailgun:
We’re mainly interested in normalize_params
- this method maps the params
values to a new hash that can be parsed into a Griddler::Email instance. Since we know stripped-text
is included in the params sent from Mailgun, we simply need to add a new key/value pair to the hash returned from normalize_params
.
Let’s create a new module in our app to extend Griddler::Mailgun::Adapter
- add the following code to app/config/initializers/griddler.rb
:
Our module contains its own normalize_params
method, which will be used to override the normalize_params
method in Griddler::Mailgun::Adapter
. The super
method calls the original normalize_params
method, which returns a hash object. A new :stripped_text
key is added to the hash, with the value of params['stripped-text']
from the Mailgun payload. The modified hash is then returned.
Our extension module is then applied to Griddler::Mailgun::Adapter
by using class_eval
to “open” the original class. The prepend
method is then used to “mix in” our extension module method.
Now our new normalize_params
code will execute in place of the original method in Griddler::Mailgun::Adapter
, and the resulting hash output will include our new key/value pair.
Extending Griddler’s Email Class
We also need to monkey patch Griddler::Email
to account for the updates we made to the Adapter. Here’s the relevant source code:
We need to add :stripped_text
to the attr_reader
declaration, and make sure it’s parsed in the initialize
method.
Add this code to app/config/initializers/griddler.rb
:
We’ve now defined a module with an initialize
method, which uses super
to call the original overridden method. An instance variable named @stripped_text
is declared to store the value of params[:stripped_text]
from our modified adapter (see previous section).
Finally, class_eval
is used to modify the Griddler::Email
class, where we add :stripped_text
to the attr_reader
declarations, then prepend our extension module method.
Wrapping it Up
Here’s the final version of app/config/initializers/griddler.rb
:
To recap, we’ve added a small amount of functionality to Griddler. When an email arrives from Mailgun, the stripped-text
parameter is now processed, and is included as an attribute of the resulting Griddler::Email
object. We’re now free to use stripped-text
anywhere in our application!
Source Code Available on GitHub
You can find the full source code for this example here: https://github.com/jwkratz/griddler-stripped-text