使用 ActionMailer 在 Rails 中发送给多个收件人
Posted
技术标签:
【中文标题】使用 ActionMailer 在 Rails 中发送给多个收件人【英文标题】:Send to multiple recipients in Rails with ActionMailer 【发布时间】:2011-11-18 05:34:45 【问题描述】:我正在尝试根据数据库中的布尔值发送多封电子邮件。该应用程序是一个简单的调度应用程序,用户可以将他们的班次标记为“replacement_needed”,这应该会向所有请求接收这些电子邮件的用户发送电子邮件。麻烦的是,它似乎只发送到一封电子邮件。这是我当前的代码:
def request_replacement(shift)
@shift = shift
@user = shift.user
@recipients = User.where(:replacement_emails => true).all
@url = root_url
@recipients.each do |r|
@name = r.fname
mail(:to => r.email,
:subject => "A replacement clerk has been requested")
end
end
【问题讨论】:
对#mail 的调用实际上并不发送电子邮件,它只是创建了邮件对象。在该邮件对象上调用 #deliver 会发送它。因此,当您调用 #deliver 时,只会发送最后一个创建的文件(大概在另一段代码中)。 【参考方案1】:您可以像这样为多个收件人发送一封电子邮件。
def request_replacement(shift)
@shift = shift
@user = shift.user
@recipients = User.where(:replacement_emails => true)
@url = root_url
emails = @recipients.collect(&:email).join(",")
mail(:to => emails, :subject => "A replacement clerk has been requested")
end
这将获取您所有的@recipients
电子邮件地址,并将它们与,
一起加入。我认为您也可以将数组传递给:to
键,但不确定。
唯一的问题是您将无法在模板中使用@name
。 :(
【讨论】:
是的,但我真的不想公开每个用户的电子邮件地址......我想我找到了一个解决方案,方法是将 .each 块移动到模型中并从那里调用传递。 真的,如果是这样的话。您可以使用bcc
字段。
FWIW,这似乎不适用于 Amazon SES,他们希望逗号作为分隔符(尽管当您使用逗号而不是分号时它可以工作)。
逗号是正确的分隔符,而不是分号。 AFAIK 只有 Outlook 使用 semicon,并在生成最终电子邮件时将其转换为逗号。
bcc
是联系don't want to expose the email addresses of every user
的一种方式,但由于这会隐藏收件人地址,因此许多邮件服务会将邮件检测为垃圾邮件。【参考方案2】:
在 Rails 指南(Action Mailer Basics)中,关于多封电子邮件的内容如下:
电子邮件列表可以是电子邮件地址数组或单个字符串,地址以逗号分隔。
所以"test1@gmail.com, test1@gmail.com"
和["test1@gmail.com", "test1@gmail.com"]
都应该可以工作。
查看更多信息:http://guides.rubyonrails.org/action_mailer_basics.html
【讨论】:
这是最好的解决方案,它链接到官方文档。如果您想隐藏收件人,请使用密件抄送。【参考方案3】:我也有同样的问题。我不知道这是什么交易。我回避它:
而不是调用
Mailer.request_replacement(shift).deliver
来自我的控制器,
我会在邮件程序上定义一个类方法,然后调用它。然后该方法将遍历列表并调用交付“n”次。这似乎有效:
class Mailer
def self.send_replacement_request(shift)
@recipients = ...
@recipients.each do |recipient|
request_replacement(recipient, shift).deliver
end
end
def request_replacement(recipient, shift)
...
mail(...)
end
end
从控制器调用
Mailer.send_replacement_request(shift)
【讨论】:
我想我永远也想不通。谢谢! 如果你不在控制器中调用deliver方法,它甚至不会进入mailer方法。【参考方案4】:要防止每个收件人看到其他电子邮件地址:
@recipients.each |recipient| Mailer.request_replacement(recipient, shift).deliver
【讨论】:
您也可以将它们添加为bcc
,如下所示:mail(:to =>"your_email@domain.com", :subject => "A replacement clerk has been requested", :bcc => @recipients.map(&:email).join(","))
我只想指出您评论中的join
是不需要的。 action mailer 可以接收电子邮件数组【参考方案5】:
我正在使用 Rails 5,我有同样的情况,电子邮件仅发送给最后一个收件人,但它也以纯文本形式发送,而不是HTML 电子邮件。
在尝试了一些建议后,我最终以这种方式修复它:
邮寄者:
class BrochureMailer < ApplicationMailer
default from: "info@site.com"
def newsletter(sponsor, brochures_list)
@sponsor = sponsor
@brochures = brochures_list
mail(
to: @sponsor.email,
subject: "Interesting subject!"
)
end
end
调用邮件程序的控制器:
class Admin::DashboardController < Admin::BaseController
def send_newsletter
sponsors = params[:sponsor_ids]
brochures = params[:brochure_ids]
sponsors = Sponsor.where(id: sponsors)
brochures = Brochure.where(id: brochures).to_a
# Send Newsletter email to the given Sponsors
sponsors.each do |sponsor|
BrochureMailer.newsletter(sponsor, brochures).deliver_later
end
redirect_back(fallback_location: admin_root_path, success: 'Newsletter sent!')
end
end
在视图中,是这样的:
<% @brochures.each do |brochure| %>
<table border="0" cellpadding="0" cellspacing="0" align="left" valign="top" class="floater">
<tr>
<td align="center" valign="top">
<a target="_blank" href="<%= brochure_url(brochure) %>">
<img border="0" vspace="0" hspace="0" src="<%= brochure.image.blank? ? 'default.png' : brochure.image.url(public: true) %>" >
<b><%= brochure.title %></b>
</a>
<br>
<%= brochure.description.truncate(60) %>
</td>
</tr>
</table>
<% end %>
它就像一个魅力! 我不确定这是否是正确的方式或最佳的方式,但只是将其视为第二种可能性。
我希望它对其他人有用。
【讨论】:
以上是关于使用 ActionMailer 在 Rails 中发送给多个收件人的主要内容,如果未能解决你的问题,请参考以下文章
使用 ActionMailer 在 Rails 中发送给多个收件人
Rails - 你如何测试 ActionMailer 在测试中发送了特定的电子邮件
Rails 4 ActionMailer - 如何在使用 Deliver_later 时捕获连接和 SMTP 错误