diff --git a/app/controllers/webhooks_controller.rb b/app/controllers/webhooks_controller.rb index 05dec8054..09acadc54 100644 --- a/app/controllers/webhooks_controller.rb +++ b/app/controllers/webhooks_controller.rb @@ -38,7 +38,8 @@ class WebhooksController < ActionController::Base end def sendgrid - params["_json"].each do |event| + events = params["_json"] || [params] + events.each do |event| if event["event"] == "bounce".freeze if event["status"]["4."] sendgrid_process(event, Email::Receiver::SOFT_BOUNCE_SCORE) @@ -53,6 +54,21 @@ class WebhooksController < ActionController::Base render nothing: true, status: 200 end + def mailjet + events = params["_json"] || [params] + events.each do |event| + if event["event"] == "bounce".freeze + if event["hard_bounce"] + mailjet_process(event, Email::Receiver::HARD_BOUNCE_SCORE) + else + mailjet_process(event, Email::Receiver::SOFT_BOUNCE_SCORE) + end + end + end + + render nothing: true, status: 200 + end + private def mailgun_failure @@ -101,4 +117,15 @@ class WebhooksController < ActionController::Base Email::Receiver.update_bounce_score(email_log.user.email, bounce_score) end + def mailjet_process(event, bounce_score) + message_id = event["CustomID"] + return if message_id.blank? + + email_log = EmailLog.find_by(message_id: message_id) + return if email_log.nil? + + email_log.update_columns(bounced: true) + Email::Receiver.update_bounce_score(email_log.user.email, bounce_score) + end + end diff --git a/config/routes.rb b/config/routes.rb index 92c241778..626d2a0a8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,8 +16,9 @@ Discourse::Application.routes.draw do match "/404", to: "exceptions#not_found", via: [:get, :post] get "/404-body" => "exceptions#not_found_body" - post "webhooks/mailgun" => "webhooks#mailgun" + post "webhooks/mailgun" => "webhooks#mailgun" post "webhooks/sendgrid" => "webhooks#sendgrid" + post "webhooks/mailjet" => "webhooks#mailjet" if Rails.env.development? mount Sidekiq::Web => "/sidekiq" diff --git a/lib/email/sender.rb b/lib/email/sender.rb index c3884f81c..29683770f 100644 --- a/lib/email/sender.rb +++ b/lib/email/sender.rb @@ -133,6 +133,11 @@ module Email @message.header['X-Discourse-Post-Id'] = nil if post_id.present? @message.header['X-Discourse-Reply-Key'] = nil if reply_key.present? + # it's the only way to pass the original message_id when using mailjet + if ActionMailer::Base.smtp_settings[:address][".mailjet.com"] + @message.header['X-MJ-CustomID'] = @message.message_id + end + # Suppress images from short emails if SiteSetting.strip_images_from_short_emails && @message.html_part.body.to_s.bytesize <= SiteSetting.short_email_length && diff --git a/spec/controllers/webhooks_controller_spec.rb b/spec/controllers/webhooks_controller_spec.rb index 1e8f99db3..cf3223bc2 100644 --- a/spec/controllers/webhooks_controller_spec.rb +++ b/spec/controllers/webhooks_controller_spec.rb @@ -1,11 +1,10 @@ require "rails_helper" describe WebhooksController do + before { $redis.flushall } let(:email) { "em@il.com" } - before { $redis.del("bounce_score:#{email}:#{Date.today}") } - context "mailgun" do it "works" do @@ -16,7 +15,6 @@ describe WebhooksController do email_log = Fabricate(:email_log, user: user, bounce_key: SecureRandom.hex) return_path = "foo+verp-#{email_log.bounce_key}@bar.com" - $redis.del("mailgun_token_#{token}") WebhooksController.any_instance.expects(:mailgun_verify).returns(true) post :mailgun, "token" => token, @@ -41,11 +39,10 @@ describe WebhooksController do post :sendgrid, "_json" => [ { - "email" => email, - "timestamp" => 1249948800, - "smtp-id" => "<12345@il.com>", - "event" => "bounce", - "status" => "5.0.0" + "email" => email, + "smtp-id" => "<12345@il.com>", + "event" => "bounce", + "status" => "5.0.0" } ] @@ -58,4 +55,26 @@ describe WebhooksController do end + context "mailjet" do + + it "works" do + message_id = "12345@il.com" + user = Fabricate(:user, email: email) + email_log = Fabricate(:email_log, user: user, message_id: message_id) + + post :mailjet, { + "event" => "bounce", + "hard_bounce" => true, + "CustomID" => message_id + } + + expect(response).to be_success + + email_log.reload + expect(email_log.bounced).to eq(true) + expect(email_log.user.user_stat.bounce_score).to eq(2) + end + + end + end