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

如何保存Noticed gem发送的邮件?自定义DeliveryJob失效问题解决

解决Noticed发送邮件时无法记录邮件数据的问题

问题背景

自定义了Jobs::EmailDeliveryJob并绑定到ApplicationMailer,手动调用邮件方法时能正常将邮件数据存入SentEmails表,但通过Noticed的deliver_by :email发送邮件时,会跳过这个自定义Job,无法获取邮件主题和正文进行存储。

可行解决思路

思路1:让Noticed调用自定义DeliveryJob

Noticed默认的邮件投递逻辑会直接调用deliver_now/deliver_later,不会关联我们自定义的Job。可以重写Noticed的Email投递方法,强制使用自定义Job:

# config/initializers/noticed.rb
Noticed::DeliveryMethods::Email.class_eval do
  def deliver
    mailer_class = Object.const_get(mailer)
    mail_instance = mailer_class.send(method, *args, **kwargs)
    
    # 调用自定义DeliveryJob,而非默认的投递逻辑
    Jobs::EmailDeliveryJob.perform_later(
      mailer_class.name,
      method,
      mail_instance.delivery_method,
      args: args,
      kwargs: kwargs,
      params: { user: recipient } # 根据你的需求传递参数,这里假设recipient是用户对象
    )
  end
end

这样Noticed发送的邮件会走自定义Job,原有的SentEmail存储逻辑就能正常执行。

思路2:在Noticed邮件生成后直接记录数据

不需要依赖DeliveryJob,利用Noticed的钩子在邮件实例生成后直接存储数据:

单通知类实现

在具体的Noticed通知类中添加before_deliver钩子:

class SomeNotification < Noticed::Base
  deliver_by :email, mailer: 'SomeMailer', method: :mail_type, delay: 1.second do |config|
    config.before_deliver do |notification, mail|
      SentEmail.create!(
        user: notification.user,
        email_type: "#{mail.class.name.deconstantize}.#{mail.method_name}",
        subject: mail.subject,
        sent_at: Time.zone.now,
        content: mail.body.to_s
      )
    end
  end
end

全局通用实现

创建一个基础通知类,所有通知继承它,统一处理邮件记录:

# app/notices/application_notice.rb
class ApplicationNotice < Noticed::Base
  before_deliver :persist_sent_email

  private

  def persist_sent_email
    return unless delivery_method == :email

    # 生成邮件实例
    mailer_class = Object.const_get(mailer)
    mail = mailer_class.send(method, *args, **kwargs)
    
    SentEmail.create!(
      user: self.user, # 确保通知类中存在user属性,按需调整
      email_type: "#{mailer}.#{method}",
      subject: mail.subject,
      sent_at: Time.zone.now,
      content: mail.body.to_s
    )
  end
end

后续所有通知类继承ApplicationNotice即可自动记录邮件数据。

为什么扩展Noticed::Base#deliver无效?

Noticed::Base#deliver是调度投递方法的入口,此时邮件尚未生成,无法获取主题、正文等有效数据,必须在邮件实例创建完成后(如before_deliver钩子、DeliveryJob执行阶段)进行处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 06:28:14