edge
更多信息请访问 rubyonrails.org: 更多 Ruby on Rails

Action Mailer基础知识

本指南为您提供了一切开始从应用程序发送电子邮件所需的内容,以及Action Mailer的许多内部知识。它还涵盖了如何测试您的邮件发送器。

阅读本指南后,您将了解:

1 什么是Action Mailer?

Action Mailer允许您使用邮件发送器类和视图从应用程序发送电子邮件。

1.1 邮件发送器类类似于控制器

它们继承自ActionMailer::Base,并位于app/mailers目录中。邮件发送器类的工作方式也与控制器非常相似。以下是一些相似之处的示例。邮件发送器类具有:

  • 动作,以及在app/views中显示的相关视图。
  • 在视图中可访问的实例变量。
  • 使用布局和局部视图的能力。
  • 访问params哈希的能力。

2 发送电子邮件

本节将提供逐步指南,以创建一个邮件发送器及其视图。

2.1 生成邮件发送器的步骤

2.1.1 创建邮件发送器

$ bin/rails generate mailer User
create  app/mailers/user_mailer.rb
create  app/mailers/application_mailer.rb
invoke  erb
create    app/views/user_mailer
create    app/views/layouts/mailer.text.erb
create    app/views/layouts/mailer.html.erb
invoke  test_unit
create    test/mailers/user_mailer_test.rb
create    test/mailers/previews/user_mailer_preview.rb
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  default from: "[email protected]"
  layout 'mailer'
end
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
end

如您所见,您可以像使用其他Rails生成器一样生成邮件发送器。

如果您不想使用生成器,您可以在app/mailers中创建自己的文件,只需确保它继承自ActionMailer::Base

class MyMailer < ActionMailer::Base
end

2.1.2 编辑邮件发送器

邮件发送器具有称为“动作”的方法,并使用视图来组织其内容。控制器生成HTML等内容以发送回客户端,而邮件发送器则创建一条通过电子邮件发送的消息。 app/mailers/user_mailer.rb 包含一个空的邮件发送器:

class UserMailer < ApplicationMailer
end

让我们添加一个名为 welcome_email 的方法,用于向用户的注册邮箱发送邮件:

class UserMailer < ApplicationMailer
  default from: '[email protected]'

  def welcome_email
    @user = params[:user]
    @url  = 'http://example.com/login'
    mail(to: @user.email, subject: '欢迎来到我的网站')
  end
end

下面是对上述方法中的项目的简要解释。有关所有可用选项的完整列表,请查看下面的完整的 Action Mailer 用户可设置属性列表部分。

  • default 方法为此邮件发送器中发送的所有邮件设置默认值。在这种情况下,我们使用它来为此类中的所有消息设置 :from 标头的值。这可以在每个邮件的基础上进行覆盖。
  • mail 方法创建实际的电子邮件消息。我们使用它来指定每个邮件的 :to:subject 等标头的值。

2.1.3 创建一个邮件模板视图

app/views/user_mailer/ 中创建一个名为 welcome_email.html.erb 的文件。这将是用于电子邮件的模板,以 HTML 格式化:

<!DOCTYPE html>
<html>
  <head>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
  </head>
  <body>
    <h1>欢迎来到 example.com,<%= @user.name %></h1>
    <p>
      您已成功注册 example.com,
      您的用户名是: <%= @user.login %><br>
    </p>
    <p>
      要登录网站,请点击此链接: <%= @url %></p>
    <p>感谢您的加入,祝您有美好的一天!</p>
  </body>
</html>

我们还要为此电子邮件创建一个纯文本部分。并非所有客户端都喜欢 HTML 邮件,因此发送两者是最佳实践。为此,请在 app/views/user_mailer/ 中创建一个名为 welcome_email.text.erb 的文件:

欢迎来到 example.com,<%= @user.name %>
===============================================

您已成功注册 example.com,
您的用户名是: <%= @user.login %>。

要登录网站,请点击此链接: <%= @url %>。

感谢您的加入,祝您有美好的一天!

当您现在调用mail方法时,Action Mailer将检测到两个模板(文本和HTML),并自动生成一个multipart/alternative邮件。

2.1.4 调用 Mailer

Mailer实际上只是另一种渲染视图的方式。它们不是通过HTTP协议渲染视图并发送,而是通过电子邮件协议发送。因此,当成功创建用户时,让控制器告诉Mailer发送电子邮件是有意义的。

设置这个很简单。

首先,让我们创建一个User脚手架:

$ bin/rails generate scaffold user name email login
$ bin/rails db:migrate

现在我们有一个可以使用的用户模型,我们将编辑app/controllers/users_controller.rb文件,通过编辑create操作并在用户成功保存后插入一个调用UserMailer.with(user: @user).welcome_email的方式,来指示UserMailer向新创建的用户发送电子邮件。

我们将使用deliver_later将电子邮件加入发送队列,它是由Active Job支持的。这样,控制器操作可以继续进行,而不需要等待发送完成。

class UsersController < ApplicationController
  # ...

  # POST /users or /users.json
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        # 告诉UserMailer在保存后发送欢迎电子邮件
        UserMailer.with(user: @user).welcome_email.deliver_later

        format.html { redirect_to(@user, notice: 'User was successfully created.') }
        format.json { render json: @user, status: :created, location: @user }
      else
        format.html { render action: 'new' }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # ...
end

注意:Active Job的默认行为是通过:async适配器执行作业。因此,您可以使用deliver_later异步发送电子邮件。Active Job的默认适配器使用进程内线程池运行作业。它非常适合开发/测试环境,因为它不需要任何外部基础设施,但它不适合生产环境,因为它在重新启动时会丢弃待处理的作业。如果您需要持久的后端,您需要使用具有持久后端的Active Job适配器(如Sidekiq、Resque等)。 如果您想立即发送电子邮件(例如从cronjob),只需调用deliver_now

class SendWeeklySummary
  def run
    User.find_each do |user|
      UserMailer.with(user: user).weekly_summary.deliver_now
    end
  end
end

传递给with的任何键值对都将成为邮件动作的params。因此,with(user: @user, account: @user.account)将使params[:user]params[:account]在邮件动作中可用。就像控制器有params一样。

welcome_email方法返回一个ActionMailer::MessageDelivery对象,然后可以告诉它deliver_nowdeliver_later以发送自身。ActionMailer::MessageDelivery对象是Mail::Message的包装器。如果您想检查、更改或对Mail::Message对象执行其他操作,可以使用ActionMailer::MessageDelivery对象上的message方法访问它。

2.2 自动编码标题值

Action Mailer处理标题和正文中的多字节字符的自动编码。

有关更复杂的示例,例如定义替代字符集或首先进行自编码文本,请参阅Mail库。

2.3 Action Mailer方法的完整列表

您只需要使用三个方法就可以发送几乎任何电子邮件消息:

  • headers - 指定您想要的电子邮件上的任何标题。您可以传递一个标题字段名称和值对的哈希,或者您可以调用headers[:field_name] = 'value'
  • attachments - 允许您向电子邮件添加附件。例如,attachments['file-name.jpg'] = File.read('file-name.jpg')
  • mail - 创建实际的电子邮件本身。您可以将标题作为哈希传递给mail方法作为参数。mail将根据您定义的电子邮件模板创建电子邮件 - 纯文本或多部分。

2.3.1 添加附件

Action Mailer非常容易添加附件。

  • 传递文件名和内容给Action Mailer和Mail gem,它将自动猜测mime_type,设置encoding并创建附件。 ruby attachments['filename.jpg'] = File.read('/path/to/filename.jpg')

当触发mail方法时,它将发送一个带有附件的多部分电子邮件,顶层为multipart/mixed,第一部分为包含纯文本和HTML电子邮件消息的multipart/alternative

注意:Mail将自动对附件进行Base64编码。如果您想要其他内容,请对内容进行编码,并将编码后的内容和编码传递给attachments方法的Hash

  • 传递文件名并指定标题和内容,Action Mailer和Mail将使用您传递的设置。
encoded_content = SpecialEncode(File.read('/path/to/filename.jpg'))
attachments['filename.jpg'] = {
  mime_type: 'application/gzip',
  encoding: 'SpecialEncoding',
  content: encoded_content
}

注意:如果您指定了编码,Mail将假定您的内容已经编码,并且不会尝试对其进行Base64编码。

2.3.2 创建内联附件

Action Mailer 3.0使内联附件(在3.0之前的版本中需要进行大量的修改)变得更简单和轻松,正如它们应该的那样。

  • 首先,要告诉Mail将附件转换为内联附件,只需在Mailer中的attachments方法上调用#inline
def welcome
  attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
end
  • 然后在视图中,您可以将attachments作为哈希引用,并指定要显示的附件,调用其上的url,然后将结果传递给image_tag方法:
<p>Hello there, this is our image</p>

<%= image_tag attachments['image.jpg'].url %>
  • 由于这是对image_tag的标准调用,您可以在附件URL之后传递一个选项哈希,就像对任何其他图像一样:
<p>Hello there, this is our image</p>

<%= image_tag attachments['image.jpg'].url, alt: 'My Photo', class: 'photos' %>

2.3.3 发送邮件给多个收件人

可以在一封电子邮件中向一个或多个收件人发送邮件(例如,通知所有管理员有新的注册),方法是将电子邮件列表设置为:to键。电子邮件列表可以是一个包含电子邮件地址的数组,也可以是一个用逗号分隔的地址的字符串。 ```ruby class AdminMailer < ApplicationMailer default to: -> { Admin.pluck(:email) }, from: '[email protected]'

def new_registration(user) @user = user mail(subject: "新用户注册: #{@user.email}") end end ```

可以使用相同的格式来设置抄送(Cc:)和密件抄送(Bcc:)收件人,分别使用:cc:bcc键。

2.3.4 带有名称的发送邮件

有时候,当收件人收到邮件时,您希望显示该人的名称而不仅仅是他们的电子邮件地址。您可以使用email_address_with_name来实现:

def welcome_email
  @user = params[:user]
  mail(
    to: email_address_with_name(@user.email, @user.name),
    subject: '欢迎来到我的超棒网站'
  )
end

相同的技术也适用于指定发件人名称:

class UserMailer < ApplicationMailer
  default from: email_address_with_name('[email protected]', 'Example Company Notifications')
end

如果名称为空字符串,则只返回地址。

2.4 邮件视图

邮件视图位于app/views/name_of_mailer_class目录中。邮件视图之所以被类所知,是因为它的名称与邮件方法相同。在上面的示例中,welcome_email方法的邮件视图将位于app/views/user_mailer/welcome_email.html.erb(HTML版本)和welcome_email.text.erb(纯文本版本)中。

要更改操作的默认邮件视图,可以执行以下操作:

class UserMailer < ApplicationMailer
  default from: '[email protected]'

  def welcome_email
    @user = params[:user]
    @url  = 'http://example.com/login'
    mail(to: @user.email,
         subject: '欢迎来到我的超棒网站',
         template_path: 'notifications',
         template_name: 'another')
  end
end

在这种情况下,它将在app/views/notifications目录下查找名称为another的模板。您还可以为template_path指定一个路径数组,它们将按顺序进行搜索。

如果您想要更多的灵活性,还可以传递一个块并渲染特定的模板,甚至可以渲染内联或文本,而无需使用模板文件:

class UserMailer < ApplicationMailer
  default from: '[email protected]'

  def welcome_email
    @user = params[:user]
    @url  = 'http://example.com/login'
    mail(to: @user.email,
         subject: '欢迎来到我的超棒网站') do |format|
      format.html { render 'another_template' }
      format.text { render plain: '渲染文本' }
    end
  end
end

这将为HTML部分渲染模板'another_template.html.erb',并使用渲染后的文本作为文本部分。渲染命令与Action Controller中使用的相同,因此您可以使用所有相同的选项,例如:text:inline等。

如果您想要渲染位于默认的app/views/mailer_name/目录之外的模板,可以使用prepend_view_path,如下所示:

class UserMailer < ApplicationMailer
  prepend_view_path "custom/path/to/mailer/view"

  # 这将尝试加载"custom/path/to/mailer/view/welcome_email"模板
  def welcome_email
    # ...
  end
end

您还可以考虑使用append_view_path方法。

2.4.1 缓存Mailer视图

您可以像在应用程序视图中一样,在Mailer视图中使用cache方法进行片段缓存。

<% cache do %>
  <%= @company.name %>
<% end %>

要使用此功能,您需要使用以下配置应用程序:

config.action_mailer.perform_caching = true

片段缓存也支持多部分邮件。有关缓存的更多信息,请阅读Rails缓存指南

2.5 Action Mailer布局

就像控制器视图一样,您也可以拥有Mailer布局。布局名称需要与您的Mailer相同,例如user_mailer.html.erbuser_mailer.text.erb,以便被您的Mailer自动识别为布局。

要使用不同的文件,请在您的Mailer中调用layout

class UserMailer < ApplicationMailer
  layout 'awesome' # 使用awesome.(html|text).erb作为布局
end

就像控制器视图一样,使用yield在布局中渲染视图。

您还可以在格式块内的渲染调用中传递layout: 'layout_name'选项,以指定不同格式的不同布局:

class UserMailer < ApplicationMailer
  def welcome_email
    mail(to: params[:user].email) do |format|
      format.html { render layout: 'my_layout' }
      format.text
    end
  end
end

如果存在的话,将使用my_layout.html.erb文件渲染HTML部分,并使用通常的user_mailer.text.erb文件渲染文本部分。

2.6 预览邮件

Action Mailer 预览提供了一种通过访问特殊的 URL 来查看邮件外观的方式。在上面的示例中,UserMailer 的预览类应该被命名为 UserMailerPreview,并且位于 test/mailers/previews/user_mailer_preview.rb 文件中。要查看 welcome_email 的预览,请实现一个同名的方法并调用 UserMailer.welcome_email

class UserMailerPreview < ActionMailer::Preview
  def welcome_email
    UserMailer.with(user: User.first).welcome_email
  end
end

然后,预览将在 http://localhost:3000/rails/mailers/user_mailer/welcome_email 上可用。

如果你在 app/views/user_mailer/welcome_email.html.erb 或邮件本身中进行了更改,它将自动重新加载和渲染,以便你可以立即看到新的样式。预览列表也可以在 http://localhost:3000/rails/mailers 上找到。

默认情况下,这些预览类位于 test/mailers/previews 目录下。可以使用 preview_paths 选项进行配置。例如,如果你想要将 lib/mailer_previews 添加到其中,可以在 config/application.rb 中进行配置:

config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"

2.7 在 Action Mailer 视图中生成 URL

与控制器不同,邮件实例没有关于传入请求的任何上下文,因此你需要自己提供 :host 参数。

由于 :host 通常在整个应用程序中是一致的,你可以在 config/application.rb 中全局配置它:

config.action_mailer.default_url_options = { host: 'example.com' }

由于这种行为,你不能在邮件中使用任何 *_path 辅助方法。相反,你需要使用相关的 *_url 辅助方法。例如,不要使用:

<%= link_to 'welcome', welcome_path %>

而是需要使用:

<%= link_to 'welcome', welcome_url %>

通过使用完整的 URL,你的链接现在将在邮件中起作用。

2.7.1 使用 url_for 生成 URL

url_for 在模板中默认生成完整的 URL。

如果你没有全局配置 :host 选项,请确保将其传递给 url_for

<%= url_for(host: 'example.com',
            controller: 'welcome',
            action: 'greeting') %>

2.7.2 使用命名路由生成URL

电子邮件客户端没有Web上下文,因此路径没有基本URL来形成完整的Web地址。因此,您应该始终使用命名路由助手的*_url变体。

如果您没有全局配置:host选项,请确保将其传递给URL助手。

<%= user_url(@user, host: 'example.com') %>

注意:非GET链接需要rails-ujsjQuery UJS,并且在邮件模板中无法工作。它们将导致正常的GET请求。

2.8 在Action Mailer视图中添加图像

与控制器不同,邮件实例没有关于传入请求的任何上下文,因此您需要自己提供:asset_host参数。

由于:asset_host通常在整个应用程序中保持一致,您可以在config/application.rb中全局配置它:

config.asset_host = 'http://example.com'

现在,您可以在电子邮件中显示图像。

<%= image_tag 'image.jpg' %>

2.9 发送多部分邮件

如果对于同一个操作有不同的模板,Action Mailer将自动发送多部分邮件。因此,对于我们的UserMailer示例,如果在app/views/user_mailer中有welcome_email.text.erbwelcome_email.html.erb,Action Mailer将自动发送一个多部分邮件,并将HTML和文本版本设置为不同的部分。

插入部分的顺序由ActionMailer::Base.default方法中的:parts_order确定。

2.10 使用动态传递选项发送电子邮件

如果您希望在发送电子邮件时覆盖默认的传递选项(例如SMTP凭据),可以在邮件操作中使用delivery_method_options来实现。

class UserMailer < ApplicationMailer
  def welcome_email
    @user = params[:user]
    @url  = user_url(@user)
    delivery_options = { user_name: params[:company].smtp_user,
                         password: params[:company].smtp_password,
                         address: params[:company].smtp_host }
    mail(to: @user.email,
         subject: "请查看附带的条款和条件",
         delivery_method_options: delivery_options)
  end
end

2.11 发送没有模板渲染的电子邮件

可能有情况下,您希望跳过模板渲染步骤,并将电子邮件正文作为字符串提供。您可以使用:body选项来实现这一点。在这种情况下,请不要忘记添加:content_type选项。否则,Rails将默认为text/plainruby class UserMailer < ApplicationMailer def welcome_email mail(to: params[:user].email, body: params[:email_body], content_type: "text/html", subject: "已经渲染!") end end

3 Action Mailer 回调

Action Mailer 允许您指定 before_action, after_actionaround_action 来配置消息,以及 before_deliver, after_deliveraround_deliver 来控制传递。

  • 回调可以使用块或邮件类中的方法符号来指定,类似于控制器。

  • 您可以使用 before_action 来设置实例变量,使用默认值填充邮件对象,或插入默认标头和附件。

class InvitationsMailer < ApplicationMailer
  before_action :set_inviter_and_invitee
  before_action { @account = params[:inviter].account }

  default to:       -> { @invitee.email_address },
          from:     -> { common_address(@inviter) },
          reply_to: -> { @inviter.email_address_with_name }

  def account_invitation
    mail subject: "#{@inviter.name} 邀请您加入他们的 Basecamp(#{@account.name})"
  end

  def project_invitation
    @project    = params[:project]
    @summarizer = ProjectInvitationSummarizer.new(@project.bucket)

    mail subject: "#{@inviter.name.familiar} 邀请您加入 Basecamp 中的项目(#{@account.name})"
  end

  private
    def set_inviter_and_invitee
      @inviter = params[:inviter]
      @invitee = params[:invitee]
    end
end
  • 您可以使用 after_action 来执行与 before_action 类似的设置,但使用在邮件动作中设置的实例变量。

  • 使用 after_action 回调还可以通过更新 mail.delivery_method.settings 来覆盖传递方法设置。

class UserMailer < ApplicationMailer
  before_action { @business, @user = params[:business], params[:user] }

  after_action :set_delivery_options,
               :prevent_delivery_to_guests,
               :set_business_headers

  def feedback_message
  end

  def campaign_message
  end

  private
    def set_delivery_options
      # 在此处您可以访问邮件实例、@business 和 @user 实例变量
      if @business && @business.has_smtp_settings?
        mail.delivery_method.settings.merge!(@business.smtp_settings)
      end
    end

    def prevent_delivery_to_guests
      if @user && @user.guest?
        mail.perform_deliveries = false
      end
    end

    def set_business_headers
      if @business
        headers["X-SMTPAPI-CATEGORY"] = @business.code
      end
    end
end
  • 您可以使用 after_delivery 来记录消息的传递。

  • 如果将 body 设置为非 nil 值,则邮件回调会中止进一步处理。before_deliver 可以使用 throw :abort 中止。

    使用Action Mailer Helpers

Action Mailer继承自AbstractController,因此您可以像在Action Controller中一样访问大多数相同的辅助方法。

还有一些Action Mailer特定的辅助方法可在ActionMailer::MailHelper中使用。例如,这些方法允许您在视图中使用mailer访问邮件实例,并使用message访问消息:

<%= stylesheet_link_tag mailer.name.underscore %>
<h1><%= message.subject %></h1>

4 Action Mailer配置

以下配置选项最好在环境文件(environment.rb,production.rb等)中进行设置。

配置 描述
logger 如果可用,生成有关邮件运行的信息。可以将其设置为nil以禁用日志记录。与Ruby自带的LoggerLog4r日志记录器兼容。
smtp_settings 允许对:smtp传递方式进行详细配置:
  • :address - 允许您使用远程邮件服务器。只需将其从默认的"localhost"设置更改即可。
  • :port - 如果您的邮件服务器不在25号端口上运行,可以进行更改。
  • :domain - 如果需要指定HELO域,可以在此处进行设置。
  • :user_name - 如果您的邮件服务器需要身份验证,请在此设置中设置用户名。
  • :password - 如果您的邮件服务器需要身份验证,请在此设置中设置密码。
  • :authentication - 如果您的邮件服务器需要身份验证,您需要在此处指定身份验证类型。这是一个符号,可以是:plain(以明文发送密码),:login(以Base64编码发送密码)或:cram_md5(将挑战/响应机制与密码哈希的密码学消息摘要5算法相结合)。
  • :enable_starttls - 在连接到SMTP服务器时使用STARTTLS,并在不支持时失败。默认为false
  • :enable_starttls_auto - 检测SMTP服务器中是否启用了STARTTLS,并开始使用它。默认为true
  • :openssl_verify_mode - 在使用TLS时,您可以设置OpenSSL如何检查证书。如果需要验证自签名和/或通配符证书,这非常有用。您可以使用OpenSSL验证常量的名称('none'或'peer')或直接使用常量(OpenSSL::SSL::VERIFY_NONEOpenSSL::SSL::VERIFY_PEER)。
  • :ssl/:tls - 启用SMTP连接使用SMTP/TLS(SMTPS:SMTP通过直接TLS连接)
  • :open_timeout - 尝试打开连接时等待的秒数。
  • :read_timeout - 等待超时的秒数,直到读取(2)调用。
sendmail_settings 允许您覆盖:sendmail传递方式的选项。
  • :location - sendmail可执行文件的位置。默认为/usr/sbin/sendmail
  • :arguments - 要传递给sendmail的命令行参数。默认为["-i"]
raise_delivery_errors 如果电子邮件发送失败,是否应该引发错误。仅在外部电子邮件服务器配置为立即传递时有效。默认为true
delivery_method 定义传递方式。可能的值为:有关更多信息,请参阅API文档
perform_deliveries 确定在调用Mail消息的deliver方法时是否实际执行传递。默认情况下,会执行传递,但可以关闭以帮助功能测试。如果此值为false,即使delivery_method:testdeliveries数组也不会被填充。
deliveries 保留通过Action Mailer使用:test传递方式发送的所有电子邮件的数组。对于单元测试和功能测试非常有用。
delivery_job deliver_later一起使用的作业类。默认为ActionMailer::MailDeliveryJob
deliver_later_queue_name 与默认delivery_job一起使用的队列的名称。默认为默认的Active Job队列。
default_options 允许您为mail方法选项(:from:reply_to等)设置默认值。

有关可能配置的完整写作,请参阅我们的《配置Rails应用程序指南》中的配置Action Mailer部分。

4.1 Action Mailer配置示例

例如,将以下内容添加到适当的config/environments/$RAILS_ENV.rb文件中:

config.action_mailer.delivery_method = :sendmail
# 默认值为:
# config.action_mailer.sendmail_settings = {
#   location: '/usr/sbin/sendmail',
#   arguments: %w[ -i ]
# }
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_options = { from: '[email protected]' }

4.2 Gmail的Action Mailer配置

Action Mailer使用Mail gem并接受类似的配置。将以下内容添加到config/environments/$RAILS_ENV.rb文件中以通过Gmail发送邮件:

config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address:         'smtp.gmail.com',
  port:            587,
  domain:          'example.com',
  user_name:       '<username>',
  password:        '<password>',
  authentication:  'plain',
  enable_starttls: true,
  open_timeout:    5,
  read_timeout:    5 }

如果您使用的是旧版本的Mail gem(2.6.x或更早版本),请使用enable_starttls_auto而不是enable_starttls

注意:Google会阻止来自其认为不安全的应用程序的登录。您可以在此处更改Gmail设置以允许尝试登录。如果您的Gmail帐户启用了两步验证,则需要设置一个应用程序密码并使用该密码代替常规密码。

5 邮件发送测试

您可以在测试指南中找到有关如何测试邮件发送的详细说明。

6 拦截和观察邮件

Action Mailer提供了对Mail观察者和拦截器方法的钩子。这些方法允许您注册在每封发送的电子邮件的邮件传递生命周期中调用的类。

6.1 拦截邮件

拦截器允许您在将电子邮件交给传递代理之前对其进行修改。拦截器类必须实现::delivering_email(message)方法,在发送电子邮件之前将调用该方法。

class SandboxEmailInterceptor
  def self.delivering_email(message)
    message.to = ['[email protected]']
  end
end

在拦截器能够发挥作用之前,您需要使用interceptors配置选项进行注册。您可以在初始化文件(例如config/initializers/mail_interceptors.rb)中执行此操作。 ruby Rails.application.configure do if Rails.env.staging? config.action_mailer.interceptors = %w[SandboxEmailInterceptor] end end

注意:上面的示例使用了一个名为“staging”的自定义环境,用于类似生产环境但用于测试目的的服务器。您可以阅读创建Rails环境以获取有关自定义Rails环境的更多信息。

6.2 观察邮件

观察者允许您在邮件发送后访问邮件消息。观察者类必须实现:delivered_email(message)方法,在邮件发送后将被调用。

class EmailDeliveryObserver
  def self.delivered_email(message)
    EmailDelivery.log(message)
  end
end

与拦截器类似,您必须使用observers配置选项注册观察者。 您可以在初始化文件中进行此操作,例如config/initializers/mail_observers.rb

Rails.application.configure do
  config.action_mailer.observers = %w[EmailDeliveryObserver]
end

反馈

欢迎您帮助改进本指南的质量。

如果您发现任何拼写错误或事实错误,请贡献您的意见。 要开始,请阅读我们的 文档贡献 部分。

您还可能会发现不完整的内容或过时的内容。 请为主要内容添加任何缺失的文档。请先检查 Edge 指南,以验证问题是否已经修复或尚未修复。 请参阅 Ruby on Rails 指南准则 以了解样式和规范。

如果您发现需要修复但无法自行修复的问题,请 提交问题

最后但同样重要的是,欢迎您在 官方 Ruby on Rails 论坛 上讨论有关 Ruby on Rails 文档的任何问题。