Ruby on rails rails 3:如何在actionmailer中中止交付方法?

Ruby on rails rails 3:如何在actionmailer中中止交付方法?,ruby-on-rails,actionmailer,Ruby On Rails,Actionmailer,在我的邮件控制器中,在某些情况下(丢失数据),我们中止发送电子邮件 在这种情况下,如何在不渲染视图的情况下退出控制器方法 返回if@some\u email\u data.nil 由于视图仍在渲染中,因此不起作用(在我尝试使用@some_email_数据的每个位置都会抛出一个错误,除非我添加了大量的nil检查) 即使我做了“零”检查,它也会抱怨没有“发送者”(因为我假设在到达设置发送者和主题的行之前做了“返回”) 也不呈现…返回 基本上,RETURN不会在mailer方法中返回!我没有花太多时间

在我的邮件控制器中,在某些情况下(丢失数据),我们中止发送电子邮件

在这种情况下,如何在不渲染视图的情况下退出控制器方法

返回if@some\u email\u data.nil

由于视图仍在渲染中,因此不起作用(在我尝试使用@some_email_数据的每个位置都会抛出一个错误,除非我添加了大量的nil检查)

即使我做了“零”检查,它也会抱怨没有“发送者”(因为我假设在到达设置发送者和主题的行之前做了“返回”)

也不呈现…返回


基本上,RETURN不会在mailer方法中返回!

我没有花太多时间使用rails 3,但您可以尝试使用

重定向到其他路径


或者,如果你真的只是检查丢失的数据,你可以对表单字段进行js验证,只有通过了才能提交。

我在这里遇到了同样的问题

我的解决办法如下:

module BulletproofMailer
  class BlackholeMailMessage < Mail::Message
    def self.deliver
      false
    end
  end

  class AbortDeliveryError < StandardError
  end

  class Base < ActionMailer::Base

    def abort_delivery
      raise AbortDeliveryError
    end

    def process(*args)
      begin
        super *args
      rescue AbortDeliveryError
        self.message = BulletproofMailer::BlackholeMailMessage
      end
    end
  end
end
模块防弹邮件器
类BlackholeMailMessage
使用这些包装器邮件程序将如下所示:

class EventMailer < BulletproofMailer::Base
  include Resque::Mailer
  def event_created(event_id)
    begin
      @event = CalendarEvent.find(event_id)
    rescue ActiveRecord::RecordNotFound
      abort_delivery
    end
  end
end
class SomeMailer < ActionMailer::Base
  def some_method
    unless @some_email_data.nil?
      mail(...)  
    end  
  end
end
class EventMailer

它也在我的博客中。

我只是清除@to字段并返回,所以在没有任何内容时发送中止。(或者在设置@to之前返回)。

一个比公认答案简单得多的解决方案如下:

class SomeMailer < ActionMailer::Base
  def some_method
    if @some_email_data.nil?
      self.message.perform_deliveries = false
    else
      mail(...)  
    end  
  end
end

设置
self.message.perform\u deliveries=false
对我不起作用

我使用了与其他一些答案类似的方法——使用错误处理来控制流量并阻止邮件发送

下面的例子是中止邮件从非生产环境发送到非白名单邮件,但是助手方法逻辑可以是场景所需的任何东西

class BaseMailer < ActionMailer::Base
  class AbortedMailer < StandardError; end

  def mail(**args)
    whitelist_mail_delivery(args[:to])
    super(args)
  rescue AbortedMailer
    Rails.logger.info "Mail aborted! We do not send emails to external email accounts outside of Production ENV"
  end

  private

  def whitelist_mail_delivery(to_email)
    return if Rails.env.production?

    raise AbortedMailer.new unless internal_email?(to_email)
  end

  def internal_email?(to_email)
    to_email.include?('@widgetbusiness.com')
  end
end
classbasemailer
我发现这种方法似乎是入侵性最小的,因为它可以跨所有mailer方法工作,而不需要您记住捕获错误。在我们的例子中,我们只需要一个设置来完全禁用某些环境中的mailer。在Rails 6中进行了测试,尽管我确信它在Rails 5中也可以正常工作,但可能更低

class ApplicationMailer{}
def确保已启用通知
提出AbortDeliveryError.new,除非
结束
...
结束

空lambda导致Rails 6只返回一个
ActionMailer::Base::NullMail
实例,该实例没有被传递(这与mailer方法没有调用
mail
或过早返回的情况相同)。

没有用户或会话重定向到…(该方法由延迟作业调用,以响应某些事件触发器)我们需要的方法只是在它的轨迹中停止扫描你粘贴了一些相关的代码吗?从邮件程序返回在Rails 2中工作吗?我仍然相信这可以更容易地完成,但我不知道怎么做。@Eisenhorn有-看看我的答案。我的所有邮件都有一个ApplicationMailer基类(很像ApplicationController)我把这个功能放在那里。它可能会中止,但你知道这是一个蹩脚的答案。如果有抄送/密件抄送,电子邮件仍然会发出,而且,由于这是一个黑客行为,因此不能保证这在将来不会抛出巨大错误。它比(当前)更优雅顶级解决方案。优雅与复杂的权衡。Rails显然需要添加一些东西。“优雅”,喜欢它:-PAnd你是如何测试它的?似乎在Rails 3.2.9中你可以看到
邮件。应该是一种空邮件
,但我仍然不知道如何在Rails 3.2.8中测试它,再加上一些小游戏,我发现你可以在Rails 3.2.8中做到这一点:
邮件。执行交付。不应该是
来测试这一切吗已传递:
expect{descripted_class.my_email_method.deliver_now}。not_更改{ActionMailer::Base.deliveries.count}
不应该是
mail.perform\u deliveries
self.message.perform\u deliveries=false
对我不起作用。但是
mail.perform\u deliveries
有效!Rails指南中也提到了它-