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
相关产品推荐
相关产品推荐

