如何让 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
我最终让它记录了每封发出的邮件的以下详细信息:
- headers
- 电子邮件的结构(哪些部分包含在哪些其他部分中),包括附件列表,然后删除所有内容
附件
- 已解码,human-readable,可搜索的消息正文(Rails 默认记录 已编码 ,这对人类来说很难阅读
并在随机位置打断单词,使其难以搜索)
为了完成这个,我覆盖了 ActionMailer::Base.set_payload_for_mail
in my app and replaced this line:
payload[:mail] = mail.encoded
版本为:
- 创建邮件副本object
- 调用
mail.without_attachments!
,并且
仅日志:
mail.header.encoded
- 来自
mail.inspect_structure
的输出(来自 my fork)
- 为每个 (non-attachment) 部分调用
part.decoded
的结果。
查看此 gist 了解全部内容。
我喜欢 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
我最终让它记录了每封发出的邮件的以下详细信息:
- headers
- 电子邮件的结构(哪些部分包含在哪些其他部分中),包括附件列表,然后删除所有内容 附件
- 已解码,human-readable,可搜索的消息正文(Rails 默认记录 已编码 ,这对人类来说很难阅读 并在随机位置打断单词,使其难以搜索)
为了完成这个,我覆盖了 ActionMailer::Base.set_payload_for_mail
in my app and replaced this line:
payload[:mail] = mail.encoded
版本为:
- 创建邮件副本object
- 调用
mail.without_attachments!
,并且 仅日志:
mail.header.encoded
- 来自
mail.inspect_structure
的输出(来自 my fork) - 为每个 (non-attachment) 部分调用
part.decoded
的结果。
查看此 gist 了解全部内容。