使用 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 错误

Rails ActionMailer嵌套在模块中

带有多个 SMTP 服务器的 Rails ActionMailer

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