【问题标题】:How to catch error exception in ActionMailer如何在 ActionMailer 中捕获错误异常
【发布时间】:2012-02-01 08:35:26
【问题描述】:

问题是如何在 ActionMailer 发送邮件时捕获异常。对我来说这听起来不可能,因为在这种情况下 ActionMailer 应该向邮件服务器发送邮件,如果邮件服务器返回错误,ActionMailer 应该向我显示这个错误。我只对计算未投递的邮件感兴趣。

您有任何想法如何实施吗? 谢谢!

【问题讨论】:

    标签: ruby-on-rails email actionmailer


    【解决方案1】:

    这是受到@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
    

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

    More explanation about (*) splat operator

    【讨论】:

      【解决方案2】:
      class ApplicationMailer < ActionMailer::Base
        rescue_from [ExceptionThatShouldBeRescued] do |exception|
          #handle it here
        end
      end
      

      适用于 Rails 5 以后。这是最佳做法。

      【讨论】:

      • 并确保其他邮件程序类继承自 ApplicationMailer
      【解决方案3】:

      这应该适用于您的任何环境文件。 development.rbproduction.rb

      config.action_mailer.raise_delivery_errors = true
      

      【讨论】:

      • 我不想向用户显示异常,我只需要识别交付失败
      • 只要你抢救处理,用户就不会看到异常!我还喜欢向 Airbrake 或一些异常通知服务报告事情,以便我们知道事情是否失败——即使他们得到了愉快的处理。
      【解决方案4】:

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

      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
      

      实用类:

      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
      

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

      【讨论】:

      • 它不需要是一个类。只是一个模块,你可以用module_function定义方法
      【解决方案5】:

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

       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 "/"
      

      【讨论】:

        猜你喜欢
        • 2019-09-08
        • 2015-09-21
        • 2015-06-11
        • 2020-06-15
        • 2018-10-22
        • 1970-01-01
        • 1970-01-01
        • 2014-03-21
        • 2010-12-14
        相关资源
        最近更新 更多