Reputation:
I am using ActionMailer deliver_later w ActiveJobs / Sidekiq using :
config.active_job.queue_adapter = :sidekiq
as I am testing in dev mode w MailCatcher, the only error I can catch is Errno::ECONNREFUSED, setting port 1026 instead of 1025
When I test deliver_now, I get the Errno::ECONNREFUSED error raised, which is fine
begin
MessageMailer.contact_me_email(@message).deliver_now
rescue Errno::ECONNREFUSED, Net::SMTPAuthenticationError, Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError, Net::SMTPUnknownError => e
flash[:error] = "Problems sending mail. Please try again later"
# delete message or resend it ?
byebug
@message.destroy
format.html { render :new }
end
However, when I request a deliver_later, then the request is sore in the sidekiq mailers queue, and the error is not captured...
begin
MessageMailer.contact_me_email(@message).deliver_later(wait: 1.minute ) # in mailers queue
rescue Errno::ECONNREFUSED, Net::SMTPAuthenticationError, Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError, Net::SMTPUnknownError => e
flash[:error] = "Problems sending mail. Please try again later"
# delete message or resend it ?
byebug
@message.destroy
format.html { render :new }
end
How can I capture and rescue from SMTP errors in this case ? I guess it's a Sidekiq responsibility to handle it ... any hint welcome..
Upvotes: 6
Views: 3088
Reputation: 12111
ActiveJobs allows you to rescue errors that occur when the job is performed using the rescue_from
method. See the api. You will need to implement this method in your ActiveJob subclasses.
Since ActionMailer uses DeliveryJobs to deliver the messages as jobs you will need to add a rescue_from method to this class to handle the exception.
For example, you could place in config/initializers/action_mailer.rb
:
ActionMailer::DeliveryJob.rescue_from(StandardError) do |exception|
Rails.logger.error "Original record not found: #{@serialized_arguments.join(', ')}"
end
This will cleanly rescue any StandardErrors, and simply log them instead of raising an exception. I implemented this myself to quiet Rollbar.
Since it's a corner case, it's a good idea to test it as well:
spec/initializers/action_mailer_spec.rb
:
RSpec.describe 'ActionMailer::DeliveryJob error recovery' do
it 'should log the deserialization errors' do
@user = create(:user)
MyCustomMailer.send_something(@user).deliver_later
@user.destroy
expect(Rails.logger).to receive(:error).at_least(:once)
Delayed::Worker.new.work_off
end
end
Upvotes: 14