如何让 ActionMailer 记录已发送的消息但不包括附件?

How do I get ActionMailer to log sent messages but NOT include the attachments?

我喜欢 Rails 自动记录从应用程序发出的所有消息。我喜欢的是它如何用大量无用的 Base64 编码文本填充我的日志文件。这使得查看日志文件变得很痛苦,因为我必须跳过这些 megabytes-long 块不可读的噪音。它还会导致日志文件增长过快并填满磁盘。

如何让它仍然记录所有已发送但不包含任何附件的消息?有没有办法告诉它在登录之前删除附件?

通常我感兴趣的是 headers(主题,发送给谁)和(至少在某些时候)消息 body 文本。

也有一个 list 的附件(文件名和类型)也没什么坏处 — 但看到完整的 Base64 转储肯定对我没有好处所有附件! (如果我想检查附件是否正常通过,我已经知道如何添加一个邮件拦截器,将所有外发邮件密件抄送到我的收件箱。)

消息 body 的记录在此处处理:

https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/log_subscriber.rb#L14

module ActionMailer
  class LogSubscriber < ActiveSupport::LogSubscriber
    def deliver(event)
      info do
        recipients = Array(event.payload[:to]).join(', ')
        "\nSent mail to #{recipients} (#{event.duration.round(1)}ms)"
      end

      debug { event.payload[:mail] }
    end
    # ... more methods ...
  end
end

如果您想完全排除邮件 body,您可以更改日志级别以排除 'debug'。否则你唯一的选择就是覆盖这个方法并做你自己的事情。

不幸的是 event.payload[:mail] 是一个字符串。删除附件可能会很麻烦。使用正则表达式显示 headers 并不难。否则,您需要从该字符串重新创建邮件 object 并提取您想要的内容。

另一种选择是更改 ActionMailer 使用的记录器,以便它记录到自己的文件中。这至少可以使您的标准 Rails 日志保持干净。

https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/railtie.rb#L12

我最终让它记录了每封发出的邮件的以下详细信息:

  1. headers
  2. 电子邮件的结构(哪些部分包含在哪些其他部分中),包括附件列表,然后删除所有内容 附件
  3. 已解码,human-readable,可搜索的消息正文(Rails 默认记录 已编码 ,这对人类来说很难阅读 并在随机位置打断单词,使其难以搜索)

为了完成这个,我覆盖了 ActionMailer::Base.set_payload_for_mail in my app and replaced this line:

payload[:mail]       = mail.encoded

版本为:

  1. 创建邮件副本object
  2. 调用 mail.without_attachments!,并且
  3. 仅日志:

    1. mail.header.encoded
    2. 来自 mail.inspect_structure 的输出(来自 my fork
    3. 为每个 (non-attachment) 部分调用 part.decoded 的结果。

查看此 gist 了解全部内容。