You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails初始化器中调用ActionMailer::Base.mail提示不可用如何解决

问题根因

mail 是 ActionMailer::Base 的实例方法,并非类方法,所以你直接调用 ActionMailer::Base.mail 会提示方法不可用,这是正常现象。mail 方法的设计使用场景是在继承了 ActionMailer::Base 的自定义邮件类的实例方法内部调用,或者通过邮件类的实例对象调用。

最优解决方案

你不需要手动调用 mail 和 render 方法生成邮件内容,DeliveryJob 入参中已经存储了渲染邮件所需的全部信息:邮件类名、调用的方法名、入参,直接复用这些信息就能快速得到异常发生时的邮件渲染结果,完全避免后续数据变更导致的内容不一致问题。

修改后的代码参考:

ActionMailer::DeliveryJob.rescue_from(StandardError) do |exception|
  attempt = EmailAttempt.new
  attempt.error_class    = exception.class.to_s
  attempt.mailer         = self.arguments[0]
  attempt.email_template = self.arguments[1]
  attempt.params         = self.arguments[3]
  attempt.enqueued_at    = self.enqueued_at
  attempt.timezone       = self.timezone

  # 常量化得到自定义邮件类,调用对应方法得到已渲染的邮件实例
  mailer_klass = self.arguments[0].constantize
  mail_instance = mailer_klass.with(**self.arguments[3]).send(self.arguments[1])
  # 提取邮件正文,优先取HTML格式,没有就取纯文本格式
  attempt.email_body = if mail_instance.html_part.present?
    mail_instance.html_part.body.to_s
  else
    mail_instance.body.to_s
  end
  # 若后续需要直接重试发送原始邮件,也可以直接存储完整mime邮件体
  # attempt.raw_mail = mail_instance.to_s

  attempt.save!
end
手动调用mail方法的写法(不推荐)

如果你一定要手动构造邮件对象,需要先实例化邮件类,再调用实例的mail方法:

mailer = ActionMailer::Base.new
mail_obj = mailer.mail(**self.arguments[3][:email]) do |format|
  format.html do
    # 手动渲染需要传入完整模板路径,上下文环境和你自定义邮件类不一致容易报错
    render template: "your_mailer_template_path", locals: self.arguments[3][:body]
  end
end

内容的提问来源于stack exchange,提问作者sifear

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 01:54:03