chore(email): log smtp errors

This commit is contained in:
Colin Darie 2023-01-09 23:16:14 +01:00
parent 6cb2389eef
commit 0a22c1d2f0
3 changed files with 48 additions and 4 deletions

View file

@ -6,16 +6,20 @@ class ApplicationMailer < ActionMailer::Base
before_action :add_dolist_header before_action :add_dolist_header
# Dont retry to send a message if the server rejects the recipient address # Dont retry to send a message if the server rejects the recipient address
rescue_from Net::SMTPSyntaxError do |_error| rescue_from Net::SMTPSyntaxError do |_exception|
message.perform_deliveries = false message.perform_deliveries = false
end end
rescue_from Net::SMTPServerBusy do |error| rescue_from Net::SMTPServerBusy do |exception|
if /unexpected recipients/.match?(error.message) if /unexpected recipients/.match?(exception.message)
message.perform_deliveries = false message.perform_deliveries = false
else
log_smtp_error(exception)
end end
end end
rescue_from Net::SMTPError, with: :log_smtp_error
# Attach the procedure logo to the email (if any). # Attach the procedure logo to the email (if any).
# Returns the attachment url. # Returns the attachment url.
def attach_logo(procedure) def attach_logo(procedure)
@ -38,4 +42,14 @@ class ApplicationMailer < ActionMailer::Base
def add_dolist_header def add_dolist_header
headers['X-Dolist-Message-Name'] = action_name headers['X-Dolist-Message-Name'] = action_name
end end
def log_smtp_error(exception)
if defined?(message) && message.to.present?
EmailEvent.create_from_message!(message, status: "dispatch_error")
end
Sentry.capture_exception(exception, extra: { to: message&.to, subject: message&.subject })
# TODO find a way to re attempt the job
end
end end

View file

@ -13,8 +13,10 @@
# #
class EmailEvent < ApplicationRecord class EmailEvent < ApplicationRecord
enum status: { enum status: {
dispatched: 'dispatched' dispatched: 'dispatched',
dispatch_error: 'dispatch_error'
} }
class << self class << self
def create_from_message!(message, status:) def create_from_message!(message, status:)
message.to.each do |recipient| message.to.each do |recipient|

View file

@ -40,5 +40,33 @@ RSpec.describe ApplicationMailer, type: :mailer do
expect(event.processed_at).to be_within(1.second).of(Time.zone.now) expect(event.processed_at).to be_within(1.second).of(Time.zone.now)
expect(event.status).to eq('dispatched') expect(event.status).to eq('dispatched')
end end
context "when email is not sent" do
subject(:send_email) { UserMailer.ask_for_merge(user1, user2.email).deliver_now }
before do
allow_any_instance_of(Mail::Message)
.to receive(:deliver)
.and_raise(smtp_error)
end
context "smtp server busy" do
let(:smtp_error) { Net::SMTPServerBusy.new }
it "creates an event" do
expect { send_email }.to change { EmailEvent.count }.by(1)
expect(EmailEvent.last.status).to eq('dispatch_error')
end
end
context "smtp unknown error" do
let(:smtp_error) { Net::SMTPUnknownError.new }
it "creates an event" do
expect { send_email }.to change { EmailEvent.count }.by(1)
expect(EmailEvent.last.status).to eq('dispatch_error')
end
end
end
end end
end end