在 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 "" 在 Ruby1.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.2 电子邮件在被 Sendgrid 处理之前延迟了 11 分钟