Rails ActionMailer - 格式化发件人和收件人姓名/电子邮件地址

Posted

技术标签:

【中文标题】Rails ActionMailer - 格式化发件人和收件人姓名/电子邮件地址【英文标题】:Rails ActionMailer - format sender and recipient name/email address 【发布时间】:2010-10-31 17:47:40 【问题描述】:

在使用 ActionMailer 时,有没有办法为发件人和收件人信息指定电子邮件和名称?

通常你会这样做:

@recipients   = "#user.email"
@from         = "info@mycompany.com"
@subject      = "Hi"
@content_type = "text/html"

但是,我也想指定名称--MyCompany <info@mycompany.com>John Doe <john.doe@mycompany>

有没有办法做到这一点?

【问题讨论】:

Rails 指南有一个如何做到这一点的示例:guides.rubyonrails.org/… 也可以在此问题中查看另一个答案***.com/a/8106387/879854 【参考方案1】:

由于Rails 6.1,ActionMailer::Base 上有一个新的便捷辅助方法:

ActionMailer::Base.email_address_with_name("test@test.com", "John Test with Quotes <'")
=> "\"John Test with Quotes <'\" <test@test.com>"

在 Mailer 中,无需类名即可访问:

mail to: email_address_with_name(user.email, user.name), ...

在引擎盖下它使用 Mail::Address 就像在上面的答案中一样。

【讨论】:

【参考方案2】:

如果您正在接受用户输入的姓名和电子邮件,那么除非您非常仔细地验证或转义姓名和电子邮件,否则您可能会通过简单地连接字符串而得到无效的 From 标头。这是一个安全的方法:

require 'mail'
address = Mail::Address.new email # ex: "john@example.com"
address.display_name = name.dup   # ex: "John Doe"
# Set the From or Reply-To header to the following:
address.format # returns "John Doe <john@example.com>"

【讨论】:

非常感谢!我认为有比字符串 concat 更好的方法,但是在我阅读的任何文档中都不清楚使用 Mail::Address address.display_name 在某些情况下似乎会改变字符串编码,因此如果您打算稍后使用name,例如在 Rails 邮件视图中,执行 address.display_name = name.dup 看起来 Mail gem 现在欺骗了传入的字符串,所以name.dup 似乎不再需要了。 Source 读作:@display_name = str.nil? ? nil : str.dup 这甚至可以在设计初始化器中工作:config.mailer_sender = Proc.new address = Mail::Address.new... 【参考方案3】:

我喜欢用这个的版本是

%`"#account.full_name" <#account.email>`

`

更新

你也可以改成

%|"#account.full_name" <#account.email>|
%\"#account.full_name" <#account.email>\
%^"#account.full_name" <#account.email>^
%["#account.full_name" <#account.email>]

Read more about string literals.

【讨论】:

【参考方案4】:

在 rails3 中,我在每个环境中放置以下内容。即生产.rb

ActionMailer::Base.default :from => "Company Name <no-reply@production-server.ca>"

在 Rails3 中,我无法在公司名称周围加上引号。

【讨论】:

如果你没有环境限制,也可以像:from =&gt; "Company Name &lt;no-reply@email.com&gt;"这样直接放在你的mailer.rb文件中。【参考方案5】:

另一个令人讨厌的方面,至少对于新的 AR 格式,是记住在类级别调用“默认”。引用仅实例的例程会导致它静默失败并在您尝试使用它时放弃:

 NoMethodError: undefined method `new_post' for Notifier:Class

这是我最终使用的:

def self.named_email(name,email) "\"#name\" <#email>" end
default :from => named_email(user.name, user.email)

【讨论】:

【参考方案6】:

在 Rails 2.3.3 中引入了 ActionMailer 中的错误。你可以在这里看到票Ticket #2340。它已在 2-3-stable 和 master 中解决,因此将在 3.x 和 2.3.6 中修复。

为了解决 2.3.* 中的问题,您可以使用票证 cmets 中提供的代码:

module ActionMailer
  class Base
    def perform_delivery_smtp(mail)
      destinations = mail.destinations
      mail.ready_to_send
      sender = (mail['return-path'] && mail['return-path'].spec) || Array(mail.from).first

      smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port])
      smtp.enable_starttls_auto if smtp_settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
      smtp.start(smtp_settings[:domain], smtp_settings[:user_name], smtp_settings[:password],
                 smtp_settings[:authentication]) do |smtp|
        smtp.sendmail(mail.encoded, sender, destinations)
      end
    end
  end
end

【讨论】:

对于任何有我的问题的人,“我应该把这段代码放在哪里?”答案是将其保存为 .rb 文件在您的 [rails app root]/config/initializers 目录中。【参考方案7】:
@recipients   = "\"#user.name\" <#user.email>"
@from         = "\"MyCompany\" <info@mycompany.com>"

【讨论】:

我不这么认为。它不能包含任何非 ASCII 字符,不能包含引号字符本身,并且在标题中也有一些不允许/不推荐的 ASCII 字符。我发现 RFC2047 提供了一种对此类值进行 base64 编码的机制。 查看我的答案,了解正确编码字符串的方法。 这很有帮助!仅供参考,如果您尝试对此进行测试,则需要查看@email.header['From'].to_s,而不是@email.from。后者仅包含电子邮件地址而不包含名称。 不要这样做。请参阅@JamesMcKinney 的答案。 再一次,不要使用它,因为它不安全。请参阅@JamesMcKinney 的答案。

以上是关于Rails ActionMailer - 格式化发件人和收件人姓名/电子邮件地址的主要内容,如果未能解决你的问题,请参考以下文章

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

Rails ActionMailer 用户邮件发送器 无方法

Rails 5:ActionMailer 的“deliver_later”永远不会在生产中交付

Rails-如何测试ActionMailer发送了特定附件?

Rails 6 ActionMailer预览和http基本身份验证

Rails - 你如何测试 ActionMailer 在测试中发送了特定的电子邮件