Action Mailer 基础
Action Mailer 允许你使用邮件模型和视图从你的应用程序发送电子邮件。
邮件模型
要使用 Action Mailer,你需要创建一个邮件模型。
$ bin/rails generate mailer Notifier
生成的模型继承自 ApplicationMailer
,而 ApplicationMailer
又继承自 ActionMailer::Base
。邮件模型定义用于生成电子邮件消息的方法。在这些方法中,你可以设置要在邮件视图中使用的变量、邮件本身的选项(如 :from
地址)和附件。
class ApplicationMailer < ActionMailer::Base
default from: 'from@example.com'
layout 'mailer'
end
class NotifierMailer < ApplicationMailer
default from: 'no-reply@example.com',
return_path: 'system@example.com'
def welcome(recipient)
@account = recipient
mail(to: recipient.email_address_with_name,
bcc: ["bcc@example.com", "Order Watcher <watcher@example.com>"])
end
end
在邮件方法中,你可以访问以下方法
-
attachments[]=
- 允许你以直观的方式向电子邮件添加附件;attachments['filename.png'] = File.read('path/to/filename.png')
-
attachments.inline[]=
- 允许你以与attachments[]=
相同的方式向电子邮件添加内联附件 -
headers[]=
- 允许你在电子邮件中指定任何标头字段,如headers['X-No-Spam'] = 'True'
。请注意,多次声明标头会添加多个同名字段。阅读headers
文档以了解更多信息。 -
headers(hash)
- 允许你在电子邮件中指定多个标头,如headers({'X-No-Spam' => 'True', 'In-Reply-To' => '1234@message.id'})
-
mail
- 允许你指定要发送的电子邮件。
传递给邮件方法的哈希允许你指定 Mail::Message
将接受的任何标头(包括可选字段的任何有效电子邮件标头)。
如果未传递块,mail
方法将检查你的视图并发送与方法同名的所有视图,因此上述操作将发送 welcome.text.erb
视图文件以及 welcome.html.erb
视图文件,作为 multipart/alternative
电子邮件。
如果你只想显式呈现某些模板,请传递一个块
mail(to: user.email) do |format|
format.text
format.html
end
块语法还可用于提供特定于某个部分的信息
mail(to: user.email) do |format|
format.text(content_transfer_encoding: "base64")
format.html
end
甚至可以呈现特殊视图
mail(to: user.email) do |format|
format.text
format.html { render "some_other_template" }
end
邮件视图
与 Action Controller 一样,每个邮件类都有一个对应的视图目录,其中类的每个方法都查找一个与其名称同名的模板。
要定义与邮件程序一起使用的模板,请使用与邮件程序模型中的方法同名的 .erb
文件。例如,在上面定义的邮件程序中,app/views/notifier_mailer/welcome.text.erb
处的模板将用于生成电子邮件。
在邮件程序模型的方法中定义的变量可作为实例变量在它们对应的视图中访问。
默认情况下,电子邮件以纯文本形式发送,因此我们的模型示例的示例视图可能如下所示
Hi <%= @account.name %>,
Thanks for joining our service! Please check back often.
您甚至可以在这些视图中使用 Action View 帮助器。例如
You got a new note!
<%= truncate(@note.body, length: 25) %>
如果您需要在视图中访问主题、发件人或收件人,可以通过消息对象来实现
You got a new note from <%= message.from %>!
<%= truncate(@note.body, length: 25) %>
生成 URL
可以使用 url_for
或命名路由在邮件程序视图中生成 URL。与 Action Pack 中的控制器不同,邮件程序实例没有任何关于传入请求的上下文,因此您需要提供生成 URL 所需的所有详细信息。
在使用 url_for
时,您需要提供 :host
、:controller
和 :action
<%= url_for(host: "example.com", controller: "welcome", action: "greeting") %>
在使用命名路由时,您只需提供 :host
<%= users_url(host: "example.com") %>
您应该使用 named_route_url
样式(它生成绝对 URL),并避免使用 named_route_path
样式(它生成相对 URL),因为阅读邮件的客户端不会有任何当前 URL 的概念,无法从中确定相对路径。
还可以通过在 config/application.rb
中将 :host
选项设置为配置选项,为所有邮件程序设置将用于其中的默认主机。
config.action_mailer.default_url_options = { host: "example.com" }
您还可以在各个邮件程序上定义 default_url_options
方法,以按邮件程序覆盖这些默认设置。
默认情况下,当 config.force_ssl
为 true
时,为主机生成的 URL 将使用 HTTPS 协议。
发送邮件
一旦定义了邮件程序操作和模板,您就可以传递您的消息或推迟其创建和传递以供以后使用
NotifierMailer.welcome(User.first).deliver_now # sends the email
mail = NotifierMailer.welcome(User.first) # => an ActionMailer::MessageDelivery object
mail.deliver_now # generates and sends the email now
ActionMailer::MessageDelivery
类是委托的包装器,它将调用您的方法来生成邮件。如果您想要直接访问委托或 Mail::Message
,可以在 ActionMailer::MessageDelivery
对象上调用 message
方法。
NotifierMailer.welcome(User.first).message # => a Mail::Message object
Action Mailer 与 Active Job 很好的集成,因此您可以在后台生成和发送电子邮件(示例:在请求-响应周期之外,这样用户不必等待它)
NotifierMailer.welcome(User.first).deliver_later # enqueue the email sending to Active Job
请注意,deliver_later
将从后台作业执行您的方法。
您永远不会实例化您的邮件程序类。相反,您只需调用您在类本身上定义的方法。所有实例方法都应返回要发送的消息对象。
多部分电子邮件
多部分消息也可以隐式使用,因为 Action Mailer 将自动检测并使用多部分模板,其中每个模板都以操作的名称命名,后跟内容类型。每个此类检测到的模板都将作为单独的部分添加到消息中。
例如,如果存在以下模板
-
signup_notification.text.erb
-
signup_notification.html.erb
-
signup_notification.xml.builder
-
signup_notification.yml.erb
每个模板都将被呈现并作为单独的部分添加到消息中,并具有相应的内容类型。整个消息的内容类型自动设置为 multipart/alternative
,这表示电子邮件包含同一封电子邮件正文的多个不同表示形式。操作中定义的相同实例变量传递给所有电子邮件模板。
如果已将任何附件或部分添加到电子邮件中,则不会执行隐式模板呈现。这意味着您必须手动将每个部分添加到电子邮件,并将电子邮件的内容类型设置为 multipart/alternative
。
附件
在电子邮件中发送附件很容易
class NotifierMailer < ApplicationMailer
def welcome(recipient)
attachments['free_book.pdf'] = File.read('path/to/file.pdf')
mail(to: recipient, subject: "New account information")
end
end
如果在视图目录中同时包含 welcome.text.erb
和 welcome.html.erb
模板,则将发送一个完整的 multipart/mixed
电子邮件,其中包含两个部分,第一部分是 multipart/alternative
,其中包含内部的文本和 HTML 电子邮件部分,第二部分是 application/pdf
,其中包含文件 file.pdf 的 Base64 编码副本,文件名 free_book.pdf
。
如果您需要发送没有内容的附件,则需要为其创建一个空视图,或添加一个空正文参数,如下所示
class NotifierMailer < ApplicationMailer
def welcome(recipient)
attachments['free_book.pdf'] = File.read('path/to/file.pdf')
mail(to: recipient, subject: "New account information", body: "")
end
end
您还可以发送带有 HTML 模板的附件,在这种情况下,您需要添加正文、附件和自定义内容类型,如下所示
class NotifierMailer < ApplicationMailer
def welcome(recipient)
attachments["free_book.pdf"] = File.read("path/to/file.pdf")
mail(to: recipient,
subject: "New account information",
content_type: "text/html",
body: "<html><body>Hello there</body></html>")
end
end
内联附件
您还可以指定应将文件与其他 HTML 内联显示。如果您想显示公司徽标或照片,这将非常有用。
class NotifierMailer < ApplicationMailer
def welcome(recipient)
attachments.inline['photo.png'] = File.read('path/to/photo.png')
mail(to: recipient, subject: "Here is what we look like")
end
end
然后,要在视图中引用图像,您创建一个 welcome.html.erb
文件,并调用 image_tag
,传入您要显示的附件,然后调用附件上的 url
以获取图像源的相对内容 ID 路径
<h1>Please Don't Cringe</h1>
<%= image_tag attachments['photo.png'].url -%>
由于我们正在使用 Action View 的 image_tag
方法,因此可以传入任何其他所需的选项
<h1>Please Don't Cringe</h1>
<%= image_tag attachments['photo.png'].url, alt: 'Our Photo', class: 'photo' -%>
观察和拦截邮件
Action Mailer 提供了 Mail
观察器和拦截器方法的钩子。这些方法允许你注册在邮件传递生命周期中调用的类。
观察器类必须实现 :delivered_email(message)
方法,该方法将在发送每封电子邮件后调用一次。
拦截器类必须实现 :delivering_email(message)
方法,该方法将在发送电子邮件之前调用,允许你在电子邮件到达传递代理之前对其进行修改。你的类应直接对传入的 Mail::Message
实例进行任何必要的修改。
默认哈希
Action Mailer 为你的电子邮件提供了一些智能默认值,这些值通常在类定义中的默认方法中指定
class NotifierMailer < ApplicationMailer
default sender: 'system@example.com'
end
你可以传入 Mail::Message
接受的任何标头值。开箱即用,ActionMailer::Base
设置以下内容
-
mime_version: "1.0"
-
charset: "UTF-8"
-
content_type: "text/plain"
-
parts_order: [ "text/plain", "text/enriched", "text/html" ]
parts_order
和 charset
实际上不是有效的 Mail::Message
标头字段,但 Action Mailer 会适当地转换它们并设置正确的值。
由于你可以传入任何标头,因此需要将标头作为字符串引用,或将其作为下划线符号传入,因此以下内容将起作用
class NotifierMailer < ApplicationMailer
default 'Content-Transfer-Encoding' => '7bit',
content_description: 'This is a description'
end
最后,Action Mailer 还支持将 Proc
和 Lambda
对象传递到默认哈希中,因此你可以定义在生成消息时求值的方法
class NotifierMailer < ApplicationMailer
default 'X-Special-Header' => Proc.new { my_method }, to: -> { @inviter.email_address }
private
def my_method
'some complex call'
end
end
请注意,proc/lambda 会在邮件消息生成开始时立即求值,因此如果你使用 proc 在默认哈希中设置了某些内容,然后在邮件程序方法中设置了相同的内容,它将被邮件程序方法覆盖。
还可以通过 config/application.rb
中的 default_options=
配置设置将在所有邮件程序中使用的这些默认选项。
config.action_mailer.default_options = { from: "no-reply@example.org" }
回调
你可以使用 before_action
和 after_action
指定回调以配置消息,并使用 before_deliver
和 after_deliver
包装传递过程。例如,当你想为某个邮件程序类发送的所有消息添加默认内联附件并记录传递时
class NotifierMailer < ApplicationMailer
before_action :add_inline_attachment!
after_deliver :log_delivery
def welcome
mail
end
private
def add_inline_attachment!
attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg')
end
def log_delivery
Rails.logger.info "Sent email with message id '#{message.message_id}' at #{Time.current}."
end
end
Action Mailer 中的动作回调使用 AbstractController::Callbacks
实现,因此您可以按照在从 ActionController::Base
继承的类中使用回调的方式来定义和配置回调。
请注意,除非您有特定原因这样做,否则您应该在 Action Mailer 类中优先使用 before_action
而非 after_action
,以便正确解析标头。
抢救错误
邮件程序方法中的 rescue
块无法抢救发生在渲染之外的错误,例如,后台作业中的记录反序列化错误或第三方邮件传递服务中的错误。
要抢救邮件处理过程中的任何部分发生的错误,请使用 rescue_from
class NotifierMailer < ApplicationMailer
rescue_from ActiveJob::DeserializationError do
# ...
end
rescue_from "SomeThirdPartyService::ApiError" do
# ...
end
def notify(recipient)
mail(to: recipient, subject: "Notification")
end
end
预览电子邮件
您可以通过将邮件程序预览文件添加到 ActionMailer::Base.preview_paths
来直观地预览您的电子邮件模板。由于大多数电子邮件会对数据库数据执行一些有趣的操作,因此您需要编写一些方案来加载带有伪造数据的消息
class NotifierMailerPreview < ActionMailer::Preview
def welcome
NotifierMailer.welcome(User.first)
end
end
方法必须返回一个 Mail::Message
对象,该对象可以通过调用邮件程序方法(不带额外的 deliver_now
/ deliver_later
)来生成。邮件程序预览目录的位置可以使用 preview_paths
选项进行配置,该选项的默认值为 test/mailers/previews
config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"
可以在正在运行的开发服务器实例上的 http://localhost:3000/rails/mailers
中访问所有预览的概述。
Previews
也可以通过注册具有 previewing_email
方法的预览拦截器的方式拦截,类似于传递可以被拦截的方式。
class CssInlineStyler
def self.previewing_email(message)
# inline CSS styles
end
end
config.action_mailer.preview_interceptors :css_inline_styler
请注意,如果拦截器要在发送和预览电子邮件时运行,则需要使用 register_interceptor
和 register_preview_interceptor
注册拦截器。
配置选项
这些选项在类级别指定,例如 ActionMailer::Base.raise_delivery_errors = true
-
default_options
- 您可以在类级别以及类本身中传入此选项,如上文所述。 -
logger
- 如果可用,则记录器用于生成有关邮件运行的信息。可以将其设置为nil
以不记录。与 Ruby 自身的Logger
和 Log4r 记录器兼容。 -
smtp_settings
- 允许对:smtp
传递方法进行详细配置-
:address
- 允许您使用远程邮件服务器。只需将其从默认的“localhost”设置更改即可。 -
:port
- 如果您的邮件服务器没有在端口 25 上运行,您可以更改它。 -
:domain
- 如果您需要指定 HELO 域,您可以在此处执行此操作。 -
:user_name
- 如果您的邮件服务器需要身份验证,请在此设置中设置用户名。 -
:password
- 如果您的邮件服务器需要身份验证,请在此设置中设置密码。 -
:authentication
- 如果您的邮件服务器需要身份验证,您需要在此处指定身份验证类型。这是一个符号,可以是:plain
(将以 Base64 编码发送密码)、:login
(将以 Base64 编码发送密码)或:cram_md5
(结合质询/响应机制来交换信息和加密消息Digest
5 算法来哈希重要信息) -
:enable_starttls
- 在连接到 SMTP 服务器时使用 STARTTLS,如果不受支持则失败。默认为false
。需要Mail
gem 的至少 2.7 版本。 -
:enable_starttls_auto
- 检测 SMTP 服务器中是否启用了 STARTTLS,并开始使用它。默认为true
。 -
:openssl_verify_mode
- 使用 TLS 时,您可以设置 OpenSSL 如何检查证书。如果您需要验证自签名和/或通配符证书,这非常有用。您可以使用 OpenSSL 验证常量('none'
或'peer'
)的名称或直接使用常量(OpenSSL::SSL::VERIFY_NONE
或OpenSSL::SSL::VERIFY_PEER
)。 -
:ssl/:tls
启用 SMTP 连接以使用 SMTP/TLS(SMTPS:通过直接 TLS 连接的 SMTP) -
:open_timeout
尝试打开连接时等待的秒数。 -
:read_timeout
等待 read(2) 调用超时之前的秒数。
-
-
sendmail_settings
- 允许您覆盖:sendmail
传递方法的选项。-
:location
- sendmail 可执行文件的位置。默认为/usr/sbin/sendmail
。 -
:arguments
- 命令行参数。默认为%w[ -i ]
,在发送邮件之前自动添加-f sender@address
。
-
-
file_settings
- 允许您覆盖:file
传递方法的选项。-
:location
- 将写入电子邮件的目录。默认为应用程序tmp/mails
。
-
-
raise_delivery_errors
- 无论电子邮件是否无法传递,都应引发错误。 -
delivery_method
- 定义传递方法。可能的值为:smtp
(默认值)、:sendmail
、:test
和:file
。或者,你可以提供自定义传递方法对象,例如MyOwnDeliveryMethodClass
。请参阅Mail
gem 文档,了解为自定义传递代理实现所需的接口。 -
perform_deliveries
- 确定当你在电子邮件消息或 Action Mailer 方法上调用.deliver
时,电子邮件是否实际上从 Action Mailer 发送。默认情况下,此功能已开启,但可以关闭以帮助进行功能测试。 -
deliveries
- 保存通过 Action Mailer 发送的所有电子邮件的数组,其中delivery_method :test
。最适用于单元和功能测试。 -
delivery_job
- 与deliver_later
一起使用的作业类。邮件程序可以将其设置为使用自定义传递作业。默认为ActionMailer::MailDeliveryJob
。 -
deliver_later_queue_name
-deliver_later
与默认delivery_job
一起使用的队列名称。邮件程序可以将其设置为使用自定义队列名称。
- A
- C
- D
- E
- H
- M
- N
- R
- S
- U
- ActionMailer::Callbacks
- ActionMailer::DeliveryMethods
- ActionMailer::QueuedDelivery
- ActionMailer::Rescuable
- ActionMailer::Parameterized
- ActionMailer::Previews
- ActionMailer::FormBuilder
- AbstractController::Rendering
- AbstractController::Helpers
- AbstractController::Translation
- AbstractController::Callbacks
- AbstractController::Caching
- ActionView::Layouts
常量
PROTECTED_IVARS | = | AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [:@_action_has_layout] |
属性
[W] | mailer_name | 允许设置当前邮件程序的名称。 |
类公共方法
default(value = nil) Link
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 582 def default(value = nil) self.default_params = default_params.merge(value).freeze if value default_params end
default_options=(value = nil) 链接
允许通过应用程序配置设置默认值
config.action_mailer.default_options = { from: "no-reply@example.org" }
email_address_with_name(address, name) 链接
返回“姓名 <email@example.com>”格式的电子邮件。
如果姓名为空字符串,则只返回地址。
源代码:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 607 def email_address_with_name(address, name) Mail::Address.new.tap do |builder| builder.address = address builder.display_name = name.presence end.to_s end
mailer_name() 链接
返回当前邮件发送器的名称。此方法还用作视图查找的路径。如果这是一个匿名邮件发送器,此方法将返回 anonymous
。
源代码:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 570 def mailer_name @mailer_name ||= anonymous? ? "anonymous" : name.underscore end
new() 链接
源代码:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 644 def initialize super() @_mail_was_called = false @_message = Mail.new end
register_interceptor(interceptor) 链接
注册一个拦截器,该拦截器将在发送邮件之前被调用。可以将类、字符串或符号作为拦截器传入。如果传入字符串或符号,它将被驼峰化并常量化。
源代码:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 547 def register_interceptor(interceptor) Mail.register_interceptor(observer_class_for(interceptor)) end
register_interceptors(*interceptors) 链接
注册一个或多个拦截器,这些拦截器将在发送邮件之前被调用。
源代码:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 521 def register_interceptors(*interceptors) interceptors.flatten.compact.each { |interceptor| register_interceptor(interceptor) } end
register_observer(observer) 链接
注册一个在邮件发送时会收到通知的观察者。可以将类、字符串或符号作为观察者传入。如果传入的是字符串或符号,它将被驼峰化并常量化。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 533 def register_observer(observer) Mail.register_observer(observer_class_for(observer)) end
register_observers(*observers) 链接
注册一个或多个在邮件发送时会收到通知的观察者。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 511 def register_observers(*observers) observers.flatten.compact.each { |observer| register_observer(observer) } end
unregister_interceptor(interceptor) 链接
取消注册先前注册的拦截器。可以将类、字符串或符号作为拦截器传入。如果传入的是字符串或符号,它将被驼峰化并常量化。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 554 def unregister_interceptor(interceptor) Mail.unregister_interceptor(observer_class_for(interceptor)) end
unregister_interceptors(*interceptors) 链接
取消注册一个或多个先前注册的拦截器。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 526 def unregister_interceptors(*interceptors) interceptors.flatten.compact.each { |interceptor| unregister_interceptor(interceptor) } end
unregister_observer(observer) 链接
取消注册先前注册的观察者。可以将类、字符串或符号作为观察者传入。如果传入的是字符串或符号,它将被驼峰化并常量化。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 540 def unregister_observer(observer) Mail.unregister_observer(observer_class_for(observer)) end
unregister_observers(*observers) 链接
取消注册一个或多个先前注册的观察者。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 516 def unregister_observers(*observers) observers.flatten.compact.each { |observer| unregister_observer(observer) } end
类私有方法
supports_path?() 链接
电子邮件不支持相对路径链接。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 943 def self.supports_path? # :doc: false end
实例公共方法
attachments() 链接
允许您向电子邮件添加附件,如下所示
mail.attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
如果您执行此操作,则Mail
将获取文件名并计算 MIME 类型。它还将设置Content-Type
、Content-Disposition
和Content-Transfer-Encoding
,并使用 Base64 对附件内容进行编码。
您还可以通过传递哈希而不是字符串来指定覆盖项
mail.attachments['filename.jpg'] = {mime_type: 'application/gzip',
content: File.read('/path/to/filename.jpg')}
如果您想使用 Base64 以外的编码,则需要将编码类型与预编码内容一起传递,因为Mail
不知道如何解码数据
file_content = SpecialEncode(File.read('/path/to/filename.jpg'))
mail.attachments['filename.jpg'] = {mime_type: 'application/gzip',
encoding: 'SpecialEncoding',
content: file_content }
您还可以搜索特定附件
# By Filename
mail.attachments['filename.jpg'] # => Mail::Part object or nil
# or by index
mail.attachments[0] # => Mail::Part (first attachment)
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 761 def attachments if @_mail_was_called LateAttachmentsProxy.new(@_message.attachments) else @_message.attachments end end
email_address_with_name(address, name) 链接
返回“姓名 <email@example.com>”格式的电子邮件。
如果姓名为空字符串,则只返回地址。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 685 def email_address_with_name(address, name) self.class.email_address_with_name(address, name) end
headers(args = nil) 链接
允许您将随机和不寻常的标头传递给新的Mail::Message
对象,该对象会将它们添加到自身。
headers['X-Special-Domain-Specific-Header'] = "SecretValue"
您还可以将哈希传递到标头字段名称和值的标头中,然后将其设置在Mail::Message
对象上
headers 'X-Special-Domain-Specific-Header' => "SecretValue",
'In-Reply-To' => incoming.message_id
生成的Mail::Message
将在其标头中包含以下内容
X-Special-Domain-Specific-Header: SecretValue
关于替换已定义标头的说明
-
主题
-
发件人
-
发件人
-
收件人
-
抄送
-
密件抄送
-
回复
-
原始日期
-
消息 ID
-
引用
字段只能在电子邮件标头中出现一次,而其他字段(如X-Anything
)可以出现多次。
如果您想替换任何已存在的标头,请首先将其设置为nil
以重置该值,否则将为同一标头添加另一个字段。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 723 def headers(args = nil) if args @_message.headers(args) else @_message end end
mail(headers = {}, &block) 链接
创建消息并呈现电子邮件模板的主要方法。有两种调用此方法的方式,一种是使用块,另一种是不使用块。
它接受一个标头哈希。此哈希允许您指定电子邮件消息中最常用的标头,这些标头是
-
:subject
- 消息的主题,如果省略此项,Action Mailer 将要求 Rails I18n 类在[mailer_scope, action_name]
范围内翻译:subject
,如果缺少此项,将翻译action_name
的人性化版本 -
:to
- 消息的目标接收者,可以是地址字符串或地址数组。 -
:from
- 消息的发送者 -
:cc
- 您希望在此电子邮件中抄送的人员,可以是地址字符串或地址数组。 -
:bcc
- 您希望在此电子邮件中密件抄送的人员,可以是地址字符串或地址数组。 -
:reply_to
- 将电子邮件的Reply-To
标头设置为谁。 -
:date
- 发送电子邮件的日期。
您可以使用 ::default
类方法为上述任何标头(:date
除外)设置默认值
class Notifier < ActionMailer::Base
default from: 'no-reply@test.lindsaar.net',
bcc: 'email_logger@test.lindsaar.net',
reply_to: 'bounces@test.lindsaar.net'
end
如果您需要上面未列出的其他标头,您可以将它们作为标头哈希的一部分传递,或使用 headers['name'] = value
方法。
当 :return_path
被指定为标头时,该值将用作 Mail
消息的“信封发件人”地址。当您希望将送达通知发送到与 :from
中的地址不同的地址时,设置此项非常有用。Mail
实际上会优先使用 :return_path
,其次是 :sender
,最后是 :from
字段作为“信封发件人”值。
如果您没有将块传递给 mail
方法,它将使用默认的邮件发送者名称和调用它的方法名称在视图路径中查找所有模板,然后它将为其中每个模板智能地创建部分,对正确的内容类型和顺序进行合理的猜测,并返回一个完全准备好的 Mail::Message
,准备好调用 :deliver
以发送。
例如
class Notifier < ActionMailer::Base
default from: 'no-reply@test.lindsaar.net'
def welcome
mail(to: 'mikel@test.lindsaar.net')
end
end
将在“app/views/notifier”中查找所有名为“welcome”的模板。如果不存在欢迎模板,它将引发 ActionView::MissingTemplate 错误。
但是,可以自定义这些模板
mail(template_path: 'notifications', template_name: 'another')
现在它将在“app/views/notifications”中查找所有名为“another”的模板。
如果您确实传递了一个块,则可以呈现您选择的特定模板
mail(to: 'mikel@test.lindsaar.net') do |format|
format.text
format.html
end
您甚至可以直接呈现纯文本,而无需使用模板
mail(to: 'mikel@test.lindsaar.net') do |format|
format.text { render plain: "Hello Mikel!" }
format.html { render html: "<h1>Hello Mikel!</h1>".html_safe }
end
它将呈现一个包含 text/plain
和 text/html
部分的 multipart/alternative
电子邮件。
如果需要,块语法还允许您自定义部分标题
mail(to: 'mikel@test.lindsaar.net') do |format|
format.text(content_transfer_encoding: "base64")
format.html
end
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 870 def mail(headers = {}, &block) return message if @_mail_was_called && headers.blank? && !block # At the beginning, do not consider class default for content_type content_type = headers[:content_type] headers = apply_defaults(headers) # Apply charset at the beginning so all fields are properly quoted message.charset = charset = headers[:charset] # Set configure delivery behavior wrap_delivery_behavior!(headers[:delivery_method], headers[:delivery_method_options]) assign_headers_to_message(message, headers) # Render the templates and blocks responses = collect_responses(headers, &block) @_mail_was_called = true create_parts_from_responses(message, responses) wrap_inline_attachments(message) # Set up content type, reapply charset and handle parts order message.content_type = set_content_type(message, content_type, headers[:content_type]) message.charset = charset if message.multipart? message.body.set_sort_order(headers[:parts_order]) message.body.sort_parts! end message end
mailer_name() 链接
返回邮件对象名称。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 678 def mailer_name self.class.mailer_name end
实例私有方法
default_i18n_subject(interpolations = {}) 链接
使用 Rails I18n 类在 [mailer_scope, action_name]
范围内翻译 subject
。如果在指定范围内找不到 subject
的翻译,它将默认为 action_name
的人性化版本。如果 subject 有插值,您可以通过 interpolations
参数传递它们。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 937 def default_i18n_subject(interpolations = {}) # :doc: mailer_scope = self.class.mailer_name.tr("/", ".") I18n.t(:subject, **interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize)) end
set_content_type(m, user_content_type, class_default) 链接
由 mail
用于设置邮件的内容类型。
它将使用给定的 user_content_type
,或者如果邮件消息有任何附件,则使用 multipart。如果附件是内联的,则内容类型将为“multipart/related”,否则为“multipart/mixed”。
如果没有通过标头传递任何内容类型,并且没有附件,或者邮件是 multipart,则使用默认内容类型。
来源:显示 | 在 GitHub 上
# File actionmailer/lib/action_mailer/base.rb, line 915 def set_content_type(m, user_content_type, class_default) # :doc: params = m.content_type_parameters || {} case when user_content_type.present? user_content_type when m.has_attachments? if m.attachments.all?(&:inline?) ["multipart", "related", params] else ["multipart", "mixed", params] end when m.multipart? ["multipart", "alternative", params] else m.content_type || class_default end end