在 Rails3 / ActionMailer 中设置 Message-ID 邮件头

Posted

技术标签:

【中文标题】在 Rails3 / ActionMailer 中设置 Message-ID 邮件头【英文标题】:Set the Message-ID mail header in Rails3 / ActionMailer 【发布时间】:2011-09-29 17:05:57 【问题描述】:

我想更改使用 ActionMailer 从 Ruby on Rails v3 应用程序发送的电子邮件的标题部分中的 Message-ID 标题。

我在本地主机上使用 Sendmail 进行邮件传递。

我是否在 Sendmail 或 ActionMailer 中进行配置?

我在哪里配置它(如果是 ActionMailer):config/ 文件夹中的文件或 app/mailers/ 文件夹中的文件?

【问题讨论】:

【参考方案1】:

我想通了。最简单的方法是使用邮件程序类文件顶部的default 方法。

例子:

require 'digest/sha2'
class UserMailer < ActionMailer::Base
  default "Message-ID"=>"#Digest::SHA2.hexdigest(Time.now.to_i.to_s)@yourdomain.com"

  # ... the rest of your mailer class
end

但是,我发现这很难测试,所以我写了一个私有方法并使用sent_at时间而不是Time.now

def message_id_in_header(sent_at=Time.now)
  headers["Message-ID"] = "#Digest::SHA2.hexdigest(sent_at.to_i.to_s)@yourdomain.com"
end

我只是在调用mail 方法之前调用了该方法。这使得从我的测试中传递sent_at 参数并验证email.encoded 中的匹配变得容易。

【讨论】:

如果你真的希望每条消息都有不同的ID,你需要将默认设置为lamba。在上面的第一个代码块中,它在初始化时计算一次消息 ID,并为每条消息使用相同的 ID。啊,我想在这里提供一些代码,而 *** 不会让我格式化它。我将添加另一个答案。 这种方法的一个问题是,如果您每秒发送多封电子邮件,所有这些电子邮件都将具有相同的消息 ID【参考方案2】:

我通常更喜欢使用 UUID 生成消息 ID。假设你有 uuid gem:

headers['Message-ID'] = "<# UUID.generate @example.com>"

另外你应该注意,根据RFC 2822,message-id 应该放在 ""

【讨论】:

我在其他代码中经常使用 uuid gem。这是一个很好的建议。最好使用 UUID 与当前时间戳的 SHA256 校验和。 从 Ruby 1.9.3 开始,您似乎不需要 gem 来执行此操作:require 'securerandom' 后跟 SecureRandom.uuid【参考方案3】:

Teddy 的回答很好,只是如果你真的希望每条消息都有不同的 ID,你需要将默认设置为 lambda。在他回答的第一个代码块中,它在初始化时计算一次消息 ID,并为每条消息使用相同的 ID。

这是我在我的应用程序中执行此操作的方式:

default "Message-ID" => lambda "<#SecureRandom.uuid@#Rails.application.config.mailgun_domain>"

... 域取自自定义应用配置变量(并使用 SecureRandom.uuid,它比基于时间戳 IMO 的 SHA-2 更简单一些。)

【讨论】:

btw - message-id 必须放在“”之间 - 否则,它不符合邮件标准。因此,代码将是:默认 "Message-ID" => lambda "" 虽然这基本上是正确的答案,但我相信它应该被编辑以包含 正如@andrewleung 提到的那样。否则,它将被忽略。默认“消息 ID”=> lambda "" 在 Ruby 1.9.3-p484 中我必须将 |v| 添加到 lambda 以避免异常:wrong number of arguments (1 for 0) 谢谢@sorens。我的猜测是这与 Ruby 版本关系不大,而与 Rails (ActionMailer) 版本关系更大。我想我这样做的时候是在 Rails 3.2 上。 @sorens 或者使用 proc ... 代替 lambda |v| ... ??不确定,但有人建议 lambdas 开始关心 Ruby 1.9 的确切参数计数,并且至少当前的 ActionMailer 正在传递一个对象。【参考方案4】:

在 Rails 4+(或只是 Ruby 2.0+)中,以下语法可以正常工作:

default "Message-ID" => ->(v)"<#Digest::SHA2.hexdigest(Time.now.to_i.to_s)@yourdomain.com>"

用 MailCatcher 对此进行了测试。

【讨论】:

【参考方案5】:

@jasoncrawford 几乎是对的。问题是 mailgun_domain 属性可能无法在开发环境中使用,因此最好访问 ActionMailer 配置。

default "Message-ID" => lambda "<#SecureRandom.uuid@ActionMailer::Base.smtp_settings[:domain]>"

【讨论】:

以上是关于在 Rails3 / ActionMailer 中设置 Message-ID 邮件头的主要内容,如果未能解决你的问题,请参考以下文章

在开发环境中使用 Rails 3 发送邮件

Rails 3 - 从视图中渲染 PDF 并附加到电子邮件

Rails 3 中的联系我们功能

Rails 3.2 电子邮件在被 Sendgrid 处理之前延迟了 11 分钟

在 Rails 3.1 中为 Mailer 和 View 提供自定义助手

如何在 Rails 3 中使用多线程?