Rails 4 ActionMailer - 如何在使用 deliver_later 时捕获连接和 SMTP 错误
Rails 4 ActionMailer - How to capture connection and SMTP errors when using deliver_later
我正在使用 ActionMailer deliver_later w ActiveJobs / Sidekiq 使用:
config.active_job.queue_adapter = :sidekiq
因为我正在使用 MailCatcher 在开发模式下进行测试,所以我可以捕获的唯一错误是 Errno::ECONNREFUSED,设置端口 1026 而不是 1025
当我测试 deliver_now 时,出现 Errno::ECONNREFUSED 错误,这很好
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
但是,当我请求 deliver_later 时,请求在 sidekiq 邮件队列中很糟糕,并且没有捕获到错误...
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
在这种情况下,我如何捕获和修复 SMTP 错误?我想这是 Sidekiq 的责任来处理它……欢迎任何提示……
ActiveJobs 允许您挽救使用 rescue_from
方法执行作业时发生的错误。参见 the api。您将需要在您的 ActiveJob subclasses.
中实施此方法
由于 ActionMailer 使用 DeliveryJobs 将消息作为作业传递,因此您需要向此 class 添加一个 rescue_from 方法来处理异常。
例如,您可以在 config/initializers/action_mailer.rb
中放置:
ActionMailer::DeliveryJob.rescue_from(StandardError) do |exception|
Rails.logger.error "Original record not found: #{@serialized_arguments.join(', ')}"
end
这将彻底挽救任何标准错误,并简单地记录它们而不是引发异常。我自己实现了这个来安静 Rollbar。
由于这是一个极端情况,最好也对其进行测试:
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
我正在使用 ActionMailer deliver_later w ActiveJobs / Sidekiq 使用:
config.active_job.queue_adapter = :sidekiq
因为我正在使用 MailCatcher 在开发模式下进行测试,所以我可以捕获的唯一错误是 Errno::ECONNREFUSED,设置端口 1026 而不是 1025
当我测试 deliver_now 时,出现 Errno::ECONNREFUSED 错误,这很好
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
但是,当我请求 deliver_later 时,请求在 sidekiq 邮件队列中很糟糕,并且没有捕获到错误...
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
在这种情况下,我如何捕获和修复 SMTP 错误?我想这是 Sidekiq 的责任来处理它……欢迎任何提示……
ActiveJobs 允许您挽救使用 rescue_from
方法执行作业时发生的错误。参见 the api。您将需要在您的 ActiveJob subclasses.
由于 ActionMailer 使用 DeliveryJobs 将消息作为作业传递,因此您需要向此 class 添加一个 rescue_from 方法来处理异常。
例如,您可以在 config/initializers/action_mailer.rb
中放置:
ActionMailer::DeliveryJob.rescue_from(StandardError) do |exception|
Rails.logger.error "Original record not found: #{@serialized_arguments.join(', ')}"
end
这将彻底挽救任何标准错误,并简单地记录它们而不是引发异常。我自己实现了这个来安静 Rollbar。
由于这是一个极端情况,最好也对其进行测试:
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