如何在ActionMailer中捕获错误异常

com*_*com 19 email ruby-on-rails actionmailer

问题是如何通过ActionMailer捕获邮件中的异常.对我来说这听起来不可能,因为在这种情况下,ActionMailer应该发送邮件到mailserver,如果mailserver返回错误,ActionMailer应该向我显示此错误.我只对计算未交付的邮件感兴趣.

你有任何想法如何实现这个?谢谢!

pif*_*ffy 28

我在控制器中使用这样的东西:

 if @user.save
      begin
      UserMailer.welcome_email(@user).deliver
      flash[:success] = "#{@user.name} created"
      rescue Net::SMTPAuthenticationError, Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError, Net::SMTPUnknownError => e
        flash[:success] = "Utente #{@user.name} creato. Problems sending mail"
      end
      redirect_to "/"
Run Code Online (Sandbox Code Playgroud)


Suk*_*iga 12

这应该适用于您的任何环境文件.development.rb要么production.rb

config.action_mailer.raise_delivery_errors = true
Run Code Online (Sandbox Code Playgroud)

  • 只要您拯救并处理它,用户就不会看到异常!我还想向Airbrake或一些例外通知服务报告事情,以便我们知道事情是否失败 - 即使他们处理得很愉快. (2认同)

Suk*_*iga 8

class ApplicationMailer < ActionMailer::Base
  rescue_from [ExceptionThatShouldBeRescued] do |exception|
    #handle it here
  end
end
Run Code Online (Sandbox Code Playgroud)

与 Rails 5 一起使用。这是最佳实践。


Mic*_*aev 7

如果您要发送大量电子邮件,还可以使代码更加干燥,并通过执行以下操作获取电子邮件例外通知:

status = Utility.try_delivering_email do
  ClientMailer.signup_confirmation(@client).deliver
end

unless status
  flash.now[:error] = "Something went wrong when we tried sending you and email :("
end
Run Code Online (Sandbox Code Playgroud)

实用类:

class Utility
  # Logs and emails exception
  # Optional args:
  # request: request Used for the ExceptionNotifier
  # info: "A descriptive messsage"
  def self.log_exception(e, args = {})
    extra_info = args[:info]

    Rails.logger.error extra_info if extra_info
    Rails.logger.error e.message
    st = e.backtrace.join("\n")
    Rails.logger.error st

    extra_info ||= "<NO DETAILS>"
    request = args[:request]
    env = request ? request.env : {}
    ExceptionNotifier::Notifier.exception_notification(env, e, :data => {:message => "Exception: #{extra_info}"}).deliver
  end

  def self.try_delivering_email(options = {}, &block)
    begin
      yield
      return true
    rescue  EOFError,
            IOError,
            TimeoutError,
            Errno::ECONNRESET,
            Errno::ECONNABORTED,
            Errno::EPIPE,
            Errno::ETIMEDOUT,
            Net::SMTPAuthenticationError,
            Net::SMTPServerBusy,
            Net::SMTPSyntaxError,
            Net::SMTPUnknownError,
            OpenSSL::SSL::SSLError => e
      log_exception(e, options)
      return false
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

从这里得到了我最初的灵感:http://www.railsonmaui.com/blog/2013/05/08/strategies-for-rails-logging-and-error-handling/


小智 5

这是受到以下答案的启发 @sukeerthi-adiga

class ApplicationMailer < ActionMailer::Base
  # Add other exceptions you want rescued in the array below
  ERRORS_TO_RESCUE = [
    Net::SMTPAuthenticationError,
    Net::SMTPServerBusy,
    Net::SMTPSyntaxError,
    Net::SMTPFatalError,
    Net::SMTPUnknownError,
    Errno::ECONNREFUSED
  ]

  rescue_from *ERRORS_TO_RESCUE do |exception|
    # Handle it here
    Rails.logger.error("failed to send email")
  end

end
Run Code Online (Sandbox Code Playgroud)

* 是 splat 运算符。它将数组扩展为参数列表。

关于 (*) splat 运算符的更多解释