Search code examples
ruby-on-railssendgridgriddler

Unable to parse Sendgrid parse api raw callback into Griddler email object


I am trying to accomplish the following:

Have all emails send to my domain parsed for the content of their to, body, subject line and ... in order for me to construct a fax object from it and send it as a fax

So far I have been able to setup my MX record to point to Sendgrid and from Sendgrid's Parse API using Ngrok I get the callback in my localhost server. The next step is to get the raw object into an object I could work with. This lead me to Thoughbot's Griddler Gem.

This is how I have setup my app so far:

Sendgrid Setup: URL: https://8c00fab0.ngrok.io/email_processor | Spam Check and Send Raw are both checked

As mentioned before this part works since I do receive this:

Parameters: {"dkim"=>"{@gmail.com : pass}", "email"=>"Received: by mx0034p1mdw1.sendgrid.net with SMTP id 253FfvZ40f Wed, 09 Sep 2015 22:31:48 +0000 (UTC)\nReceived: from mail-qg0-f54.google.com (mail-qg0-f54.google.com [209.85.192.54]) by mx0034p1mdw1.sendgrid.net (Postfix) with ESMTPS id 63848A83017 for <[email protected]>; Wed,  9 Sep 2015 22:31:48 +0000 (UTC)\nReceived: by qgx61 with SMTP id 61so21251135qgx.3 for <[email protected]>; Wed, 09 Sep 2015 15:31:48 -0700 (PDT)\nDKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to:content-type; bh=Wo6p7CSlR30aGxf5SwjuZ2klt31URDqTZUHrKdmLz7s=; b=fWfFOQ4YOtijYvphYL9/1shyzK8CBTcHS37s89t9Qn4xK8OrXwVKtmGtNnwg7a1n48 JHkEeAdxVvRMpinxPllGiJoPNy0ivVN36uEYbsrLTcZVlx9RIIl8u5PjmrE1aqlnkjPy gOcbfJunVCFZLaLpv3RB/GiNYL1bodgW7nn8sMTmwN5EwoH7SncS7cle4ksPadgiGv9f DVoJniX2yuMqygSVLT4Qrk4JDzR6G2oj1Fz3QkcrQfNKxOS6iyBhpnh3cDuUi8GTSVYl Nqq2dtKlUNqI+U9ojtG1BjGVUKbP0v5apF3Wvmj72p8L0AB3FHqL8uvFnhi2dGTFVq+y 6nUQ==\nX-Received: by 10.140.233.137 with SMTP id e131mr48879201qhc.37.1441837907953; Wed, 09 Sep 2015 15:31:47 -0700 (PDT)\nMIME-Version: 1.0\nFrom: Sam Sedighian <[email protected]>\nDate: Wed, 09 Sep 2015 22:31:38 +0000\nMessage-ID: <CAEMkzYbhsLLB3NPLznG+-RibP5kzDG5yTT++mQL1ep-vH6_orA@mail.gmail.com>\nSubject: test 20\nTo: \"[email protected]\" <[email protected]>\nContent-Type: multipart/alternative; boundary=001a11354d8053d2d1051f580c22\n\n--001a11354d8053d2d1051f580c22\nContent-Type: text/plain; charset=UTF-8\n\nbody etxt\n\n--001a11354d8053d2d1051f580c22\nContent-Type: text/html; charset=UTF-8\n\n<div dir=\"ltr\">body etxt</div>\n\n--001a11354d8053d2d1051f580c22--\n", "to"=>"\"[email protected]\" <[email protected]>", "from"=>"Sam Sedighian <[email protected]>", "sender_ip"=>"209.85.192.54", "spam_report"=>"Spam detection software, running on the system \"mx0034p1mdw1.sendgrid.net\", has\nidentified this incoming email as possible spam.  The original message\nhas been attached to this so you can view it (if it isn't spam) or label\nsimilar future email.  If you have any questions, see\n@@CONTACT_ADDRESS@@ for details.\n\nContent preview:  body etxt body etxt [...] \n\nContent analysis details:   (0.0 points, 5.0 required)\n\n pts rule name              description\n---- ---------------------- --------------------------------------------------\n 0.0 FREEMAIL_FROM          Sender email is freemail (samansb[at]gmail.com)\n 0.0 HTML_MESSAGE           BODY: HTML included in message\n 0.0 T_MIME_NO_TEXT         No text body parts\n\n", "envelope"=>"{\"to\":[\"[email protected]\"],\"from\":\"[email protected]\"}", "subject"=>"test 20", "spam_score"=>"0.012", "charsets"=>"{\"to\":\"UTF-8\",\"subject\":\"UTF-8\",\"from\":\"UTF-8\"}", "SPF"=>"pass"}

Gemfile

gem 'griddler'
gem 'griddler-sendgrid'

Gemfile.lock

griddler (1.2.1)
  htmlentities
  rails (>= 3.2.0)
griddler-sendgrid (0.0.1)
  griddler

routes.rb

post '/email_processor' => 'fax#sendgrid'
# this corresponds to the following route when I rake route:
# email_processor POST   /email_processor(.:format) fax#sendgrid

config/initializers/griddler.rb

Griddler.configure do |config|
  config.processor_class = EmailProcessor
  config.processor_method = :process
  config.reply_delimiter = '-- REPLY ABOVE THIS LINE --'
  config.email_service = :sendgrid
end

app/controllers/fax_controller.rb

def sendgrid
  EmailProcessor.new(params).process
end

app/models/email_processor.rb

class EmailProcessor

  def initialize(email)
    @email = email
    @from = email.from
    @body = email.body
  end

  def self.process(email)
    Fax.create({params go here})
  end

end

I end up giving a Completed 500 Internal server error - Since I do not pass a 200 OK back to Sendgrid but the important part is that I get the following error in my log:

NoMethodError (undefined method `from' for #<ActionController::Parameters:0x007fc742a33070>):
  app/models/email_processor.rb:5:in `initialize'
  app/controllers/fax_controller.rb:31:in `new'
  app/controllers/fax_controller.rb:31:in `sendgrid'

Solution

  • I think the issue is that you're bypassing the work Griddler does on the controller side. You're pointing Sendgrid at a controller and action you created yourself. Instead I think you want to point to Griddler's controller and action. See the README under "Installation".

    Change your routes.rb to be:

    # your own route
    # post '/email_processor' => 'fax#sendgrid'
    
    # griddler's
    post '/email_processor' => 'griddler/emails#create'
    

    If you take a look at Griddler's controller you'll see that there are a few things it does for you to get things into your email processor class.