evendis / mandrill-rails

Webhook processing and event decoration to make using Mandrill with Rails just that much easier
MIT License
288 stars 36 forks source link

handle_inbound not called from local request #10

Closed vladCovaliov closed 10 years ago

vladCovaliov commented 10 years ago

Hi guys,

I am trying to test some inbounds on localhost, and this is what I was thinking:

I use httparty gem, to send a post request to my route, with the json content from spec/fixtures/webhook_examples/inbound_with_multiple_attachaments.json.

This is my code:

class EmailsController < ApplicationController
  include Mandrill::Rails::WebHookProcessor

  def handle_inbound(event_payload)
    binding.pry # I try to stop here, so I can handle the incoming request
  end
end
require 'httparty'
require 'pry'
require 'json'

# Read Json File
json = File.read('mandrill_test/inbound_with_multiple_attachments.json')

# Parse json string to hash
content = JSON.parse(json)

# Send hash as paramenter 
HTTParty.post(
  'http://localhost:3000/emails', 
  body: content[0]
)
resource :emails, :controller => 'emails', :only => [:show,:create]

Pretty straightforward I guess, but for some reason, I'm missing something. Doesn't this request call the handle_income method?

Thanks, Vlad

vladCovaliov commented 10 years ago

Ok, I figured this out alone. I created my own method, and with this line of code, I created the Mandrill::WebHook::EventDecorator I was looking for.

@event = Mandrill::WebHook::EventDecorator[params[:mandrill_events]]

Thanks

tardate commented 10 years ago

I should add some rspec helpers for this - I have a couple of standard tricks that I usually use in projects that use mandrill-rails but they are not in the gem.

Seems like you got it sorted out, but just to expand a bit:

If the fixture file contains an array of mandrill events, like inbound_with_multiple_attachments.json i.e.

[
  { "event": "inbound", ... }
]

Then the (rspec) equivalent of what Mandrill will actually post to the app is this:

let(:multi_event_json) { File.read('mandrill_test/inbound_with_multiple_attachments.json') }
subject { post :create,  { 'mandrill_events' => multi_event_json } }

The WebHookProcessor will take each event in multi_event_json array, decorate it with Mandrill::WebHook::EventDecorator and post each inbound event to the handle_inbound method

jfrux commented 9 years ago

Okay so I cloned repo and altered the processor.rb like so...

def run!
    puts mandrill_events.to_yaml

    mandrill_events.each do |raw_payload|
    # ...
end

When I send my curl to it, I'm getting empty array... very strange. I'll keep debugging.

# ...
--- []
Completed 200 OK in 1ms (ActiveRecord: 0.0ms)
jfrux commented 9 years ago

Aha! So since that rescue is there, it's returning [].

The error it's throwing is:

JSON::ParserError: 399: unexpected token at '{"event":"hard_bounce","_id":"1dbc399ff23847f1a7bd5bcc047b3089","msg":{"ts":1427800854,"_id":"1dbc399ff23847f1a7bd5bcc047b3089","state":"bounced","subject":"my subject","email":"example@example.org","tags":["ccpd_credit"],"smtp_events":[{"ts":1427800855,"type":"sent","diag":"250 2.0.0 OK 1427800855 s44si7119005yho.99 - gsmtp","source_ip":"<filtered>","destination_ip":"<filtered>","size":19486}],"resends":[],"_version":"n7ryzhjgtNQ7iu-681TS9g","diag":"X-Postfix'
from /Users/Joshua/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/json-1.8.2/lib/json/common.rb:155:in `parse'
jfrux commented 9 years ago

Okay so this is when I copy and paste the "curl" call from the 'Emulate Webhook Using cURL' On the Webhook Batch Detail screen on mandrillapp.com > Settings > Webhooks >

I use curl to send it to my localhost:4000 instead of my production server.

This is the exact output I get if I comment out the "rescue" on the processor.rb run! method. I've of course altered the IP's and sensitive data.

Started POST "/webhook" for 127.0.0.1 at 2015-03-31 14:19:07 -0400
Processing by WebhookController#create as */*
  Parameters: {"mandrill_events"=>"[{\"event\":\"hard_bounce\",\"_id\":\"1dbc399ff23847f1a7bd5bcc047b3089\",\"msg\":{\"ts\":1427800854,\"_id\":\"1dbc399ff23847f1a7bd5bcc047b3089\",\"state\":\"bounced\",\"subject\":\"This is my subject\",\"email\":\"example@example.org\",\"tags\":[\"ccpd_credit\"],\"smtp_events\":[{\"ts\":1427800855,\"type\":\"sent\",\"diag\":\"250 2.0.0 OK 1427800855 s44si7119005yho.99 - gsmtp\",\"source_ip\":\"123.123.123.123\",\"destination_ip\":\"123.123.123.123\",\"size\":19486}],\"resends\":[],\"_version\":\"n7ryzhjgtNQ7iu-681TS9g\",\"diag\":\"X-Postfix", "unknown user: \\\"example\\\"\\n\\n--333F7821C6.1427800810\\/example.org\",\"bgtools_code\":10,\"metadata\":{\"person\":314911,\"activity\":17351,\"attendee\":410289},\"sender\":\"fromemail@example.org\",\"template\":null,\"bounce_description\":\"bad_mailbox\"},\"ts\":1427801665}"=>"[FILTERED]"}
Completed 500 Internal Server Error in 1ms

JSON::ParserError (399: unexpected token at '{"event":"hard_bounce","_id":"1dbc399ff23847f1a7bd5bcc047b3089","msg":{"ts":1427800854,"_id":"1dbc399ff23847f1a7bd5bcc047b3089","state":"bounced","subject":"This is my subject","email":"example@example.org","tags":["ccpd_credit"],"smtp_events":[{"ts":1427800855,"type":"sent","diag":"250 2.0.0 OK 1427800855 s44si7119005yho.99 - gsmtp","source_ip":"123.123.123.123","destination_ip":"123.123.123.123","size":19486}],"resends":[],"_version":"n7ryzhjgtNQ7iu-681TS9g","diag":"X-Postfix'):
  json (1.8.2) lib/json/common.rb:155:in `parse'
  json (1.8.2) lib/json/common.rb:155:in `parse'
  /Users/Joshua/Projects/mandrill-rails/lib/mandrill/web_hook/processor.rb:15:in `mandrill_events'
  /Users/Joshua/Projects/mandrill-rails/lib/mandrill/web_hook/processor.rb:22:in `run!'
  /Users/Joshua/Projects/mandrill-rails/lib/mandrill-rails/web_hook_processor.rb:79:in `create'
  actionpack (4.1.8) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
  actionpack (4.1.8) lib/abstract_controller/base.rb:189:in `process_action'
  actionpack (4.1.8) lib/action_controller/metal/rendering.rb:10:in `process_action'
  actionpack (4.1.8) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
  activesupport (4.1.8) lib/active_support/callbacks.rb:113:in `call'
  activesupport (4.1.8) lib/active_support/callbacks.rb:113:in `call'
  activesupport (4.1.8) lib/active_support/callbacks.rb:149:in `block in halting_and_conditional'
  activesupport (4.1.8) lib/active_support/callbacks.rb:229:in `call'
  activesupport (4.1.8) lib/active_support/callbacks.rb:229:in `block in halting'
  activesupport (4.1.8) lib/active_support/callbacks.rb:86:in `call'
  activesupport (4.1.8) lib/active_support/callbacks.rb:86:in `run_callbacks'
  actionpack (4.1.8) lib/abstract_controller/callbacks.rb:19:in `process_action'
  actionpack (4.1.8) lib/action_controller/metal/rescue.rb:29:in `process_action'
  actionpack (4.1.8) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
  activesupport (4.1.8) lib/active_support/notifications.rb:159:in `block in instrument'
  activesupport (4.1.8) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  activesupport (4.1.8) lib/active_support/notifications.rb:159:in `instrument'
  actionpack (4.1.8) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
  actionpack (4.1.8) lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
  activerecord (4.1.8) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
  actionpack (4.1.8) lib/abstract_controller/base.rb:136:in `process'
  actionview (4.1.8) lib/action_view/rendering.rb:30:in `process'
  actionpack (4.1.8) lib/action_controller/metal.rb:196:in `dispatch'
  actionpack (4.1.8) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
  actionpack (4.1.8) lib/action_controller/metal.rb:232:in `block in action'
  actionpack (4.1.8) lib/action_dispatch/routing/route_set.rb:82:in `call'
  actionpack (4.1.8) lib/action_dispatch/routing/route_set.rb:82:in `dispatch'
  actionpack (4.1.8) lib/action_dispatch/routing/route_set.rb:50:in `call'
  actionpack (4.1.8) lib/action_dispatch/journey/router.rb:73:in `block in call'
  actionpack (4.1.8) lib/action_dispatch/journey/router.rb:59:in `each'
  actionpack (4.1.8) lib/action_dispatch/journey/router.rb:59:in `call'
  actionpack (4.1.8) lib/action_dispatch/routing/route_set.rb:678:in `call'
  omniauth (1.2.2) lib/omniauth/strategy.rb:186:in `call!'
  omniauth (1.2.2) lib/omniauth/strategy.rb:164:in `call'
  omniauth (1.2.2) lib/omniauth/strategy.rb:186:in `call!'
  omniauth (1.2.2) lib/omniauth/strategy.rb:164:in `call'
  omniauth (1.2.2) lib/omniauth/builder.rb:59:in `call'
  warden (1.2.3) lib/warden/manager.rb:35:in `block in call'
  warden (1.2.3) lib/warden/manager.rb:34:in `catch'
  warden (1.2.3) lib/warden/manager.rb:34:in `call'
  rack (1.5.2) lib/rack/etag.rb:23:in `call'
  rack (1.5.2) lib/rack/conditionalget.rb:35:in `call'
  rack (1.5.2) lib/rack/head.rb:11:in `call'
  actionpack (4.1.8) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
  actionpack (4.1.8) lib/action_dispatch/middleware/flash.rb:254:in `call'
  rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
  rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
  actionpack (4.1.8) lib/action_dispatch/middleware/cookies.rb:560:in `call'
  activerecord (4.1.8) lib/active_record/query_cache.rb:36:in `call'
  activerecord (4.1.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:621:in `call'
  activerecord (4.1.8) lib/active_record/migration.rb:380:in `call'
  actionpack (4.1.8) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
  activesupport (4.1.8) lib/active_support/callbacks.rb:82:in `run_callbacks'
  actionpack (4.1.8) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  actionpack (4.1.8) lib/action_dispatch/middleware/reloader.rb:73:in `call'
  actionpack (4.1.8) lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
  actionpack (4.1.8) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
  actionpack (4.1.8) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  railties (4.1.8) lib/rails/rack/logger.rb:38:in `call_app'
  railties (4.1.8) lib/rails/rack/logger.rb:20:in `block in call'
  activesupport (4.1.8) lib/active_support/tagged_logging.rb:68:in `block in tagged'
  activesupport (4.1.8) lib/active_support/tagged_logging.rb:26:in `tagged'
  activesupport (4.1.8) lib/active_support/tagged_logging.rb:68:in `tagged'
  railties (4.1.8) lib/rails/rack/logger.rb:20:in `call'
  quiet_assets (1.1.0) lib/quiet_assets.rb:27:in `call_with_quiet_assets'
  actionpack (4.1.8) lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
  rack (1.5.2) lib/rack/runtime.rb:17:in `call'
  activesupport (4.1.8) lib/active_support/cache/strategy/local_cache_middleware.rb:26:in `call'
  rack (1.5.2) lib/rack/lock.rb:17:in `call'
  actionpack (4.1.8) lib/action_dispatch/middleware/static.rb:84:in `call'
  rack (1.5.2) lib/rack/sendfile.rb:112:in `call'
  railties (4.1.8) lib/rails/engine.rb:514:in `call'
  railties (4.1.8) lib/rails/application.rb:144:in `call'
  rack (1.5.2) lib/rack/lock.rb:17:in `call'
  rack (1.5.2) lib/rack/content_length.rb:14:in `call'
  rack (1.5.2) lib/rack/handler/webrick.rb:60:in `service'
  /Users/Joshua/.rbenv/versions/2.1.5/lib/ruby/2.1.0/webrick/httpserver.rb:138:in `service'
  /Users/Joshua/.rbenv/versions/2.1.5/lib/ruby/2.1.0/webrick/httpserver.rb:94:in `run'
  /Users/Joshua/.rbenv/versions/2.1.5/lib/ruby/2.1.0/webrick/server.rb:295:in `block in start_thread'

  Rendered /Users/Joshua/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/actionpack-4.1.8/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.3ms)
  Rendered /Users/Joshua/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/actionpack-4.1.8/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (0.8ms)
  Rendered /Users/Joshua/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/actionpack-4.1.8/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.7ms)
  Rendered /Users/Joshua/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/actionpack-4.1.8/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (15.0ms)
jfrux commented 9 years ago

Thinking might be a variation in the mandrill responses? or maybe the "curl" output hasn't been updated properly on the mandrill system?

jfrux commented 9 years ago

Okay... sorry for so many messages... Did this during binding.pry:

[7] pry(#<Mandrill::WebHook::Processor>)> params
=> {"mandrill_events"=>
  "[{\"event\":\"hard_bounce\",\"_id\":\"1dbc399ff23847f1a7bd5bcc047b3089\",\"msg\":{\"ts\":1427800854,\"_id\":\"1dbc399ff23847f1a7bd5bcc047b3089\",\"state\":\"bounced\",\"subject\":\"This is my subject\",\"email\":\"example@example.org\",\"tags\":[\"ccpd_credit\"],\"smtp_events\":[{\"ts\":1427800855,\"type\":\"sent\",\"diag\":\"250 2.0.0 OK 1427800855 s44si7119005yho.99 - gsmtp\",\"source_ip\":\"123.123.123.123\",\"destination_ip\":\"123.123.123.123\",\"size\":19486}],\"resends\":[],\"_version\":\"n7ryzhjgtNQ7iu-681TS9g\",\"diag\":\"X-Postfix",
 "unknown user: \\\"example\\\"\\n\\n--333F7821C6.1427800810\\/example.org\",\"bgtools_code\":10,\"metadata\":{\"person\":314911,\"activity\":17351,\"attendee\":410289},\"sender\":\"fromemail@example.org\",\"template\":null,\"bounce_description\":\"bad_mailbox\"},\"ts\":1427801665}"=>
  nil,
 "action"=>"create",
 "controller"=>"webhook"}

params is not structured properly... It's having trouble interpreting what webhook is sending it. It's cutting off the json string at: X-Postfix;

and moves it to a new param in the hash

jfrux commented 9 years ago

I'm sorry, this is completely isolated to CURL. What a waste of your and my time. WHen I use the curl command they provide it does it but if I use something else to send the POST it works fine.