discourse/app/jobs/regular/process_sns_notification.rb
Martin Brennan 4086ee551e
DEV: Add bounce_error_code to EmailLog (#15948)
Whenever we got a bounced email in the Email::Receiver we
previously would just set bounced: true on the EmailLog and
discard the status/diagnostic code. This commit changes this
flow to store the bounce error code (defined in the RFC at
https://www.iana.org/assignments/smtp-enhanced-status-codes/smtp-enhanced-status-codes.xhtml)
not just in the Email::Receiver, but also via webhook events
from other mail services and from SNS.

This commit does not surface the bounce error in the UI,
we can do that later if necessary.
2022-02-15 14:17:26 +10:00

44 lines
1.4 KiB
Ruby

# frozen_string_literal: true
module Jobs
class ProcessSnsNotification < ::Jobs::Base
sidekiq_options retry: false
def execute(args)
return unless raw = args[:raw].presence
return unless json = args[:json].presence
return unless message = json["Message"].presence
message = begin
JSON.parse(message)
rescue JSON::ParserError
nil
end
return unless message && message["notificationType"] == "Bounce"
return unless message_id = message.dig("mail", "messageId").presence
return unless bounce_type = message.dig("bounce", "bounceType").presence
require "aws-sdk-sns"
return unless Aws::SNS::MessageVerifier.new.authentic?(raw)
message.dig("bounce", "bouncedRecipients").each do |r|
if email_log = EmailLog.order("created_at DESC").where(to_address: r["emailAddress"]).first
email_log.update_columns(bounced: true, bounce_error_code: r["status"])
if email_log.user&.email.present?
if email_log.user.user_stat.bounce_score.to_s.start_with?("4.") || bounce_type == "Transient"
Email::Receiver.update_bounce_score(email_log.user.email, SiteSetting.soft_bounce_score)
else
Email::Receiver.update_bounce_score(email_log.user.email, SiteSetting.hard_bounce_score)
end
end
end
end
end
end
end