/ griddler-gem

Allow posting comments by replying to an email with Griddler gem

As you’re probably aware, SendGrid is great at sending your email, but SendGrid can also help you process email using the Inbound Parse Webhook. The Inbound Parse Webhook processes all incoming email for a domain or subdomain, parses the contents and attachments of that email, then POSTs the multipart/form-data of the attachment and JSON-encoded content to the URL of your choosing.
To send an email to the application we use sendgrid services. Sendgrid provides different APIs for different purposes. For incoming email processing use inbound parse webhook API.
The API says that:

The Parse API will POST the parsed email to a URL that you specify.

Setup

To begin processing email using SendGrid’s Inbound Parse Webhook, you will have to setup MX Records, choose the hostname (or receiving domain) that will be receiving the emails you want to parse, and define the URL where you want to POST your parsed emails.
The following steps are required to begin parsing email:

  • Point the MX Record of a Domain/Hostname or Subdomain to mx.sendgrid.net
  • Associate the Domain/Hostname and the URL in the Parse API settings page.

To handle this incoming emails to the sendgrid in application we need an endpoint at application site which is Griddler Gem.

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.

Installation

  • Add griddler and an adapter gem to your application's Gemfile and then run bundle
    install:

      gem 'griddler'
      gem 'griddler-sendgrid'
    
  • A route is needed for the endpoint which receives POST messages. To add the route, in config/routes.rb use the provided routing method mount_griddler. Examples:

config/routes.rb

# mount using default path: /email_processor
  mount_griddler

Configuration Options
An initializer can be created to control some of the options in Griddler. In config/initializers/griddler.rb:

Griddler.configure do |config|
  config.processor_class = EmailProcessor     # CommentViaEmail
  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

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:

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

  def process
    user = User.find_by(email: @email.from[:email])
    post_url_token = parse_post_url_token_from_response_email
    begin
      Post.find_by(url_token: post_url_token).
      comments.create(user_id: user.id, comment: @email.body)
    rescue StandardError => e
      Rails.logger.error e.message
    end
  end 

  private
  def parse_post_url_token_from_response_email
    @email.to[0][:token].split('+').second
  end
end

In above process method, we are creating a comment with the incoming email body as a comment to the post corresponding to the post-url-token inside the reply-to field shown in the below method. In this we were sending an E-mail to all other Users when any new Article is posted. So we added reply-to field to the mail so that other user can reply to that email.

def send_notification_on_new_post(users_list, post)
  @post = Post.find(post["id"])

  post_user = @post.user
  user_name = post_user.name.titleize || post_user.email

  headers "X-SMTPAPI" => {
    "unique_args": {
      "post_id": post.id
    }
  }.to_json

  @subject = user_name + " posted a new article on KnowBuddy"
  mail(
    bcc: users_list,
    subject: @subject,
    reply_to: "reply+#{post.url_token}@#{KIPROSH_APP_DOMAIN}")
 end

Now you are able to post a comment by replying to an email.

Griddler::Email attributesenter image description here