1 什麼是 Action Mailer?
Action Mailer 可讓您從 Rails 應用程式傳送電子郵件。它是 Rails 框架中兩個與電子郵件相關的元件之一。另一個是 Action Mailbox,用於處理接收電子郵件。
Action Mailer 使用類別(稱為「郵件程式」)和視圖來建立和設定要傳送的電子郵件。郵件程式是繼承自 ActionMailer::Base
的類別。郵件程式類別與控制器類別類似。兩者都有
- 可在視圖中存取的實例變數。
- 使用版面配置和局部視圖的能力。
- 存取 params 雜湊的能力。
app/views
中的動作和相關視圖。
2 建立郵件程式和視圖
本節將提供使用 Action Mailer 傳送電子郵件的逐步指南。以下是每個步驟的詳細資訊。
2.1 產生郵件程式
首先,您可以使用「郵件程式」產生器來建立郵件程式相關類別
$ bin/rails generate mailer User
create app/mailers/user_mailer.rb
invoke erb
create app/views/user_mailer
invoke test_unit
create test/mailers/user_mailer_test.rb
create test/mailers/previews/user_mailer_preview.rb
如下面的 UserMailer
所示,所有產生的郵件程式類別都繼承自 ApplicationMailer
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
end
ApplicationMailer
類別繼承自 ActionMailer::Base
,可用於定義所有郵件程式通用的屬性
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
default from: "from@example.com"
layout "mailer"
end
如果您不想使用產生器,也可以手動將檔案新增至 app/mailers
目錄。請確保您的類別繼承自 ApplicationMailer
# app/mailers/custom_mailer.rb
class CustomMailer < ApplicationMailer
end
2.2 編輯郵件程式
app/mailers/user_mailer.rb
中的 UserMailer
最初沒有任何方法。因此,接下來,我們將方法(又稱動作)新增至郵件程式,以傳送特定的電子郵件。
郵件程式有稱為「動作」的方法,它們使用視圖來組織其內容,類似於控制器。控制器產生 HTML 內容以傳回給用戶端,而郵件程式則建立要透過電子郵件傳遞的訊息。
讓我們將一個名為 welcome_email
的方法新增至 UserMailer
,該方法會將電子郵件傳送至使用者的註冊電子郵件地址
class UserMailer < ApplicationMailer
default from: "notifications@example.com"
def welcome_email
@user = params[:user]
@url = "http://example.com/login"
mail(to: @user.email, subject: "Welcome to My Awesome Site")
end
end
郵件程式中的方法名稱不必以 _email
結尾。
以下是對上面使用的郵件程式相關方法的快速說明
default
方法會為從此郵件程式傳送的所有電子郵件設定預設值。在這種情況下,我們使用它來設定此類別中所有訊息的:from
標頭值。這可以針對每個電子郵件覆寫。mail
方法會建立實際的電子郵件訊息。我們使用它來指定每個電子郵件的標頭值,例如:to
和:subject
。
還有 headers
方法(上面未使用),用於使用雜湊或呼叫 headers[:field_name] = 'value'
來指定電子郵件標頭。
可以直接在使用產生器時指定動作,如下所示
$ bin/rails generate mailer User welcome_email
上面會產生具有空的 welcome_email
方法的 UserMailer
。
您也可以從單一郵件程式類別傳送多封電子郵件。將相關電子郵件分組在一起可能很方便。例如,除了 welcome_email
之外,上面的 UserMailer
還可以有一個 goodbye_email
(以及相應的視圖)。
2.3 建立郵件程式視圖
接下來,對於 welcome_email
動作,您需要在 app/views/user_mailer/
目錄中建立一個名為 welcome_email.html.erb
的相符視圖檔案。以下是可以為歡迎電子郵件使用的範例 HTML 範本
<h1>Welcome to example.com, <%= @user.name %></h1>
<p>
You have successfully signed up to example.com,
your username is: <%= @user.login %>.<br>
</p>
<p>
To login to the site, just follow this link: <%= link_to 'login`, login_url %>.
</p>
<p>Thanks for joining and have a great day!</p>
上面是 <body>
標籤的內容。它將會嵌入預設郵件程式版面配置中,其中包含 <html>
標籤。請參閱 郵件程式版面配置 以了解更多資訊。
您也可以建立上述電子郵件的文字版本,並將其儲存在 app/views/user_mailer/
目錄中的 welcome_email.text.erb
中(請注意 .text.erb
副檔名與 html.erb
不同)。傳送這兩種格式被認為是最佳做法,因為如果 HTML 呈現出現問題,文字版本可以作為可靠的備案。以下是一個範例文字電子郵件
Welcome to example.com, <%= @user.name %>
===============================================
You have successfully signed up to example.com,
your username is: <%= @user.login %>.
To login to the site, just follow this link: <%= @url %>.
Thanks for joining and have a great day!
請注意,在 HTML 和文字電子郵件範本中,您都可以使用實例變數 @user
和 @url
。
現在,當您呼叫 mail
方法時,Action Mailer 會偵測到這兩個範本(文字和 HTML),並自動產生 multipart/alternative
電子郵件。
2.4 呼叫郵件程式
設定郵件程式類別和視圖後,下一步是實際呼叫呈現電子郵件視圖(即傳送電子郵件)的郵件程式方法。郵件程式可以被認為是呈現視圖的另一種方式。控制器動作會呈現要透過 HTTP 通訊協定傳送的視圖。郵件程式動作會呈現視圖,並改為透過電子郵件通訊協定傳送。
讓我們看看使用 UserMailer
在使用者成功建立時傳送歡迎電子郵件的範例。
首先,讓我們建立一個 User
樣板
$ bin/rails generate scaffold user name email login
$ bin/rails db:migrate
接下來,我們編輯 UserController
中的 create
動作,以便在建立新使用者時傳送歡迎電子郵件。我們在使用者成功儲存後插入對 UserMailer.with(user: @user).welcome_email
的呼叫來執行此操作。
我們使用 deliver_later
來將電子郵件加入佇列,以便稍後傳送。這樣一來,控制器動作將會繼續執行,而無需等待電子郵件傳送程式碼執行。 deliver_later
方法的底層是 Active Job。
class UsersController < ApplicationController
# ...
def create
@user = User.new(user_params)
respond_to do |format|
if @user.save
# Tell the UserMailer to send a welcome email after save
UserMailer.with(user: @user).welcome_email.deliver_later
format.html { redirect_to user_url(@user), notice: "User was successfully created." }
format.json { render :show, status: :created, location: @user }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
# ...
end
任何傳遞給 with
的鍵值對都會成為郵件程式動作的 params
。例如,with(user: @user, account: @user.account)
會使 params[:user]
和 params[:account]
在郵件程式動作中可用。
設定好上述郵件程式、視圖和控制器後,如果您建立新的 User
,您可以檢查日誌,查看歡迎電子郵件是否已傳送。日誌檔案將會顯示傳送的文字和 HTML 版本,如下所示:
[ActiveJob] [ActionMailer::MailDeliveryJob] [ec4b3786-b9fc-4b5e-8153-9153095e1cbf] Delivered mail 6661f55087e34_1380c7eb86934d@Bhumis-MacBook-Pro.local.mail (19.9ms)
[ActiveJob] [ActionMailer::MailDeliveryJob] [ec4b3786-b9fc-4b5e-8153-9153095e1cbf] Date: Thu, 06 Jun 2024 12:43:44 -0500
From: notifications@example.com
To: test@gmail.com
Message-ID: <6661f55087e34_1380c7eb86934d@Bhumis-MacBook-Pro.local.mail>
Subject: Welcome to My Awesome Site
Mime-Version: 1.0
Content-Type: multipart/alternative;
boundary="--==_mimepart_6661f55086194_1380c7eb869259";
charset=UTF-8
Content-Transfer-Encoding: 7bit
----==_mimepart_6661f55086194_1380c7eb869259
Content-Type: text/plain;
...
----==_mimepart_6661f55086194_1380c7eb869259
Content-Type: text/html;
...
您也可以從 Rails 控制台呼叫郵件程式並傳送電子郵件,這在您設定控制器動作之前可能作為測試很有用。以下將傳送與上述相同的 welcome_email
:
irb> user = User.first
irb> UserMailer.with(user: user).welcome_email.deliver_later
如果您想要立即傳送電子郵件 (例如從 cronjob),您可以呼叫 deliver_now
class SendWeeklySummary
def run
User.find_each do |user|
UserMailer.with(user: user).weekly_summary.deliver_now
end
end
end
UserMailer
中的 weekly_summary
等方法會傳回一個 ActionMailer::MessageDelivery
物件,該物件具有 deliver_now
或 deliver_later
方法,可立即或稍後傳送自身。ActionMailer::MessageDelivery
物件是 Mail::Message
的包裝器。如果您想要檢查、變更或對 Mail::Message
物件執行其他操作,可以使用 ActionMailer::MessageDelivery
物件上的 message
方法來存取它。
以下是從上述 Rails 控制台範例中取得的 MessageDelivery
物件範例:
irb> UserMailer.with(user: user).weekly_summary
#<ActionMailer::MailDeliveryJob:0x00007f84cb0367c0
@_halted_callback_hook_called=nil,
@_scheduled_at_time=nil,
@arguments=
["UserMailer",
"welcome_email",
"deliver_now",
{:params=>
{:user=>
#<User:0x00007f84c9327198
id: 1,
name: "Bhumi",
email: "hi@gmail.com",
login: "Bhumi",
created_at: Thu, 06 Jun 2024 17:43:44.424064000 UTC +00:00,
updated_at: Thu, 06 Jun 2024 17:43:44.424064000 UTC +00:00>},
:args=>[]}],
@exception_executions={},
@executions=0,
@job_id="07747748-59cc-4e88-812a-0d677040cd5a",
@priority=nil,
3 多部分電子郵件和附件
multipart
MIME 類型表示一個由多個組成部分組成的文件,每個部分可能都有自己的 MIME 類型 (例如 text/html
和 text/plain
)。multipart
類型封裝了在一個交易中一起傳送多個檔案,例如將多個檔案附加到電子郵件中。
3.1 新增附件
您可以透過將檔案名稱和內容傳遞給 attachments 方法,使用 Action Mailer 新增附件。Action Mailer 會自動猜測 mime_type
、設定 encoding
並建立附件。
attachments["filename.jpg"] = File.read("/path/to/filename.jpg")
當觸發 mail
方法時,它會傳送帶有附件的多部分電子郵件,並正確地巢狀配置,頂層為 multipart/mixed
,而第一部分為 multipart/alternative
,其中包含純文字和 HTML 電子郵件訊息。
傳送附件的另一種方式是指定檔案名稱、MIME 類型和編碼標頭以及內容。Action Mailer 將使用您傳入的設定。
encoded_content = SpecialEncode(File.read("/path/to/filename.jpg"))
attachments["filename.jpg"] = {
mime_type: "application/gzip",
encoding: "SpecialEncoding",
content: encoded_content
}
Action Mailer 會自動以 Base64 編碼附件。如果您想要不同的編碼方式,您可以編碼您的內容,並將編碼後的內容以及 Hash
中的編碼傳遞給 attachments
方法。如果您指定編碼,Action Mailer 將不會嘗試以 Base64 編碼附件。
3.2 建立內嵌附件
有時,您可能想要內嵌傳送附件 (例如影像),使其顯示在電子郵件正文中。
為了執行此操作,首先,您需要透過呼叫 #inline
將附件轉換為內嵌附件
def welcome
attachments.inline["image.jpg"] = File.read("/path/to/image.jpg")
end
然後在視圖中,您可以將 attachments
作為雜湊參照,並指定要內嵌顯示的檔案。您可以在雜湊上呼叫 url
,並將結果傳遞給 image_tag
方法
<p>Hello there, this is the image you requested:</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' %>
3.3 多部分電子郵件
如 建立郵件程式視圖 中所示,如果您對同一個動作使用不同的範本,Action Mailer 將會自動傳送多部分電子郵件。例如,如果您的 UserMailer
在 app/views/user_mailer
中有 welcome_email.text.erb
和 welcome_email.html.erb
,則 Action Mailer 將自動傳送多部分電子郵件,其中 HTML 和文字版本都作為單獨的部分包含在內。
Mail gem 具有輔助方法,可為 text/plain
和 text/html
MIME 類型 製作 multipart/alternate
電子郵件,而且您可以手動建立任何其他類型的 MIME 電子郵件。
插入部分的順序由 ActionMailer::Base.default
方法內的 :parts_order
決定。
當您使用電子郵件傳送附件時,也會使用多部分。
4 郵件程式視圖和版面配置
Action Mailer 使用視圖檔案來指定要在電子郵件中傳送的內容。郵件程式視圖預設位於 app/views/name_of_mailer_class
目錄中。與控制器視圖類似,檔案的名稱與郵件程式方法的名稱相符。
郵件程式視圖會在版面配置中呈現,與控制器視圖類似。郵件程式版面配置位於 app/views/layouts
中。預設版面配置為 mailer.html.erb
和 mailer.text.erb
。本節涵蓋有關郵件程式視圖和版面配置的各種功能。
4.1 設定自訂視圖路徑
可以透過各種方式變更動作的預設郵件程式視圖,如下所示。
mail
方法具有 template_path
和 template_name
選項
class UserMailer < ApplicationMailer
default from: "notifications@example.com"
def welcome_email
@user = params[:user]
@url = "http://example.com/login"
mail(to: @user.email,
subject: "Welcome to My Awesome Site",
template_path: "notifications",
template_name: "hello")
end
end
上述程式碼會設定 mail
方法在 app/views/notifications
目錄中尋找名為 hello
的範本。您也可以為 template_path
指定路徑陣列,它們將會依序搜尋。
如果您需要更大的彈性,您也可以傳遞區塊並呈現特定的範本。您也可以不使用範本檔案而內嵌呈現純文字
class UserMailer < ApplicationMailer
default from: "notifications@example.com"
def welcome_email
@user = params[:user]
@url = "http://example.com/login"
mail(to: @user.email,
subject: "Welcome to My Awesome Site") do |format|
format.html { render "another_template" }
format.text { render plain: "hello" }
end
end
end
這會為 HTML 部分呈現範本 another_template.html.erb
,並為文字部分呈現 "hello"。 render 方法與 Action Controller 內部使用的方法相同,因此您可以使用所有相同的選項,例如 :plain
、:inline
等。
最後,如果您需要呈現位於預設 app/views/mailer_name/
目錄外的範本,您可以套用 prepend_view_path
,如下所示
class UserMailer < ApplicationMailer
prepend_view_path "custom/path/to/mailer/view"
# This will try to load "custom/path/to/mailer/view/welcome_email" template
def welcome_email
# ...
end
end
還有一個 append_view_path
方法。
4.2 在 Action Mailer 視圖中產生 URL
為了將 URL 新增至您的郵件程式,您需要先將 host
值設定為應用程式的網域。這是因為與控制器不同,郵件程式執行個體沒有關於傳入請求的任何內容。
您可以在 config/application.rb
中設定整個應用程式的預設 host
config.action_mailer.default_url_options = { host: "example.com" }
設定 host
後,建議電子郵件視圖使用包含完整 URL 的 *_url
,而不是包含相對 URL 的 *_path
輔助程式。由於電子郵件用戶端沒有 Web 請求內容,因此 *_path
輔助程式沒有形成完整網址的基礎 URL。
例如,不要使用
<%= link_to 'welcome', welcome_path %>
請使用
<%= link_to 'welcome', welcome_url %>
透過使用完整的 URL,您的連結將在電子郵件中正確運作。
4.2.1 使用 url_for
產生 URL
url_for
輔助程式預設會在範本中產生完整的 URL。
如果您尚未全域設定 :host
選項,則需要將其傳遞給 url_for
。
<%= url_for(host: 'example.com',
controller: 'welcome',
action: 'greeting') %>
4.2.2 使用具名路由產生 URL
與其他 URL 類似,您也需要在電子郵件中使用具名路由輔助程式的 *_url
變體。
您可以全域設定 :host
選項,或確保將其傳遞給 URL 輔助程式
<%= user_url(@user, host: 'example.com') %>
4.3 在 Action Mailer 視圖中新增影像
為了在電子郵件中使用 image_tag
輔助程式,您需要指定 :asset_host
參數。這是因為郵件程式執行個體沒有關於傳入請求的任何內容。
通常 :asset_host
在整個應用程式中是一致的,因此您可以在 config/application.rb
中全域設定它
config.action_mailer.asset_host = "http://example.com"
由於我們無法從請求推斷協定,因此您需要在 :asset_host
設定中指定協定,例如 http://
或 https://
。
現在您可以在電子郵件中顯示影像。
<%= image_tag 'image.jpg' %>
4.4 快取郵件程式視圖
您可以使用 cache
方法,在郵件程式視圖中執行片段快取,與應用程式視圖類似。
<% cache do %>
<%= @company.name %>
<% end %>
若要使用此功能,您需要在應用程式的 config/environments/*.rb
檔案中啟用它
config.action_mailer.perform_caching = true
多部分電子郵件也支援片段快取。請閱讀 Rails 快取指南中關於快取的更多資訊。
4.5 Action Mailer 版面配置
與控制器版面配置一樣,您也可以擁有郵件程式版面配置。郵件程式版面配置位於 app/views/layouts
中。以下是預設版面配置
# app/views/layouts/mailer.html.erb
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
/* Email styles need to be inline */
</style>
</head>
<body>
<%= yield %>
</body>
</html>
上述版面配置位於檔案 mailer.html.erb
中。預設版面配置名稱是在 ApplicationMailer
中指定的,如我們稍早在 產生郵件程式 一節中看到的 layout "mailer"
行。與控制器版面配置類似,您可以使用 yield
在版面配置中呈現郵件程式視圖。
若要對指定的郵件程式使用不同的版面配置,請呼叫 layout
class UserMailer < ApplicationMailer
layout "awesome" # Use awesome.(html|text).erb as the layout
end
若要對指定的電子郵件使用特定的版面配置,您可以將 layout: 'layout_name'
選項傳遞至格式區塊內的 render 呼叫
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
檔案呈現文字部分。
5 傳送電子郵件
5.1 將電子郵件傳送給多個收件者
可以透過將 :to
欄位設定為電子郵件地址清單,將電子郵件傳送給多個收件者。電子郵件清單可以是陣列,也可以是逗號分隔地址的單一字串。
例如,通知所有管理員有新的註冊
class AdminMailer < ApplicationMailer
default to: -> { Admin.pluck(:email) },
from: "notification@example.com"
def new_registration(user)
@user = user
mail(subject: "New User Signup: #{@user.email}")
end
end
相同的格式可用於新增多個副本 (cc) 和密件副本 (bcc) 收件者,方法分別是設定 :cc
和 :bcc
金鑰 (與 :to
欄位類似)。
5.2 寄送帶有名稱的電子郵件
除了電子郵件地址之外,也可以顯示電子郵件收件人或寄件人的名稱。
若要在收件人收到電子郵件時顯示其名稱,您可以在 to:
中使用 email_address_with_name
方法。
def welcome_email
@user = params[:user]
mail(
to: email_address_with_name(@user.email, @user.name),
subject: "Welcome to My Awesome Site"
)
end
在 from:
中使用相同的方法可以顯示寄件人的名稱。
class UserMailer < ApplicationMailer
default from: email_address_with_name("notification@example.com", "Example Company Notifications")
end
如果名稱為空白(nil
或空字串),則會傳回電子郵件地址。
5.3 寄送帶有主旨翻譯的電子郵件
如果您沒有將主旨傳遞給 mail 方法,Action Mailer 將會嘗試在您的翻譯中找到它。請參閱國際化指南以了解更多資訊。
5.4 寄送不需樣板渲染的電子郵件
在某些情況下,您可能會想要跳過樣板渲染步驟,而是將電子郵件內文以字串形式提供。您可以使用 :body
選項來達成此目的。請記得設定 :content_type
選項,例如在下方設定為 text/html
。Rails 會預設內容類型為 text/plain
。
class UserMailer < ApplicationMailer
def welcome_email
mail(to: params[:user].email,
body: params[:email_body],
content_type: "text/html",
subject: "Already rendered!")
end
end
5.5 寄送帶有動態傳遞選項的電子郵件
如果您希望在傳遞電子郵件時覆寫預設的傳遞設定(例如 SMTP 憑證),您可以在 mailer 動作中使用 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: "Please see the Terms and Conditions attached",
delivery_method_options: delivery_options)
end
end
6 Action Mailer 回呼
Action Mailer 允許您指定 before_action
、 after_action
和 around_action
來設定訊息,以及 before_deliver
、 after_deliver
和 around_deliver
來控制傳遞。
回呼可以使用區塊或代表 mailer 類別中方法名稱的符號來指定,與其他回呼(在控制器或模型中)類似。
以下是一些您可能在 mailer 中使用這些回呼的範例。
6.1 before_action
您可以使用 before_action
來設定實例變數、以預設值填入 mail 物件,或插入預設標頭和附件。
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} invited you to their Basecamp (#{@account.name})"
end
def project_invitation
@project = params[:project]
@summarizer = ProjectInvitationSummarizer.new(@project.bucket)
mail subject: "#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})"
end
private
def set_inviter_and_invitee
@inviter = params[:inviter]
@invitee = params[:invitee]
end
end
6.2 after_action
您可以使用與 before_action
類似設定的 after_action
回呼,但也可以存取在 mailer 動作中設定的實例變數。
您也可以使用 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
# You have access to the mail instance,
# @business and @user instance variables here
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
6.3 after_deliver
您可以使用 after_deliver
來記錄訊息的傳遞。它也允許類似觀察者/攔截器的行為,但可以存取完整的 mailer 內容。
class UserMailer < ApplicationMailer
after_deliver :mark_delivered
before_deliver :sandbox_staging
after_deliver :observe_delivery
def feedback_message
@feedback = params[:feedback]
end
private
def mark_delivered
params[:feedback].touch(:delivered_at)
end
# An Interceptor alternative.
def sandbox_staging
message.to = ["sandbox@example.com"] if Rails.env.staging?
end
# A callback has more context than the comparable Observer example.
def observe_delivery
EmailDelivery.log(message, self.class, action_name, params)
end
end
如果 body
設定為非 nil 值,Mailer 回呼會中止進一步處理。before_deliver
可以使用 throw :abort
中止。
7 Action Mailer 檢視輔助方法
Action Mailer 檢視可以存取與一般檢視相同的大部分輔助方法。
在 ActionMailer::MailHelper
中也有一些 Action Mailer 特有的輔助方法可用。例如,這些方法允許您從檢視中透過 mailer
存取 mailer 實例,並透過 message
存取訊息。
<%= stylesheet_link_tag mailer.name.underscore %>
<h1><%= message.subject %></h1>
8 Action Mailer 設定
本節顯示 Action Mailer 的一些範例設定。
如需各種設定選項的更多詳細資訊,請參閱設定 Rails 應用程式指南。您可以在環境特定的檔案中指定設定選項,例如 production.rb。
8.1 Action Mailer 設定範例
以下是使用 :sendmail
傳遞方法的範例,已新增至 config/environments/$RAILS_ENV.rb
檔案。
config.action_mailer.delivery_method = :sendmail
# Defaults to:
# 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: "no-reply@example.com" }
8.2 Gmail 的 Action Mailer 設定
將此新增至您的 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: Rails.application.credentials.dig(:smtp, :user_name),
password: Rails.application.credentials.dig(:smtp, :password),
authentication: "plain",
enable_starttls: true,
open_timeout: 5,
read_timeout: 5 }
Google 會封鎖來自其認為安全性較低的應用程式的登入。您可以變更您的 Gmail 設定以允許嘗試。如果您的 Gmail 帳戶已啟用兩步驟驗證,則您需要設定一個應用程式密碼,並使用該密碼而不是您的常規密碼。
9 預覽和測試 Mailer
您可以在測試指南中找到有關如何測試 mailer 的詳細說明。
9.1 預覽電子郵件
您可以透過造訪特殊的 Action Mailer 預覽 URL 來視覺化預覽呈現的電子郵件範本。若要為 UserMailer
設定預覽,請在 test/mailers/previews/
目錄中建立一個名為 UserMailerPreview
的類別。若要查看 UserMailer
中 welcome_email
的預覽,請在 UserMailerPreview
中實作一個具有相同名稱的方法,並呼叫 UserMailer.welcome_email
class UserMailerPreview < ActionMailer::Preview
def welcome_email
UserMailer.with(user: User.first).welcome_email
end
end
現在,預覽將可在 https://127.0.0.1:3000/rails/mailers/user_mailer/welcome_email 上取得。
如果您在 app/views/user_mailer/welcome_email.html.erb
的 mailer 檢視或 mailer 本身中變更任何內容,預覽將會自動更新。預覽的清單也可以在 https://127.0.0.1:3000/rails/mailers 中取得。
預設情況下,這些預覽類別位於 test/mailers/previews
中。這可以使用 preview_paths
選項進行設定。例如,如果您想要將 lib/mailer_previews
新增至其中,您可以在 config/application.rb
中進行設定。
config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"
9.2 救援錯誤
mailer 方法內部的 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
10 攔截和觀察電子郵件
Action Mailer 提供進入 Mail 觀察器和攔截器方法的掛鉤。這些掛鉤允許您註冊在傳送每封電子郵件的郵件傳遞生命週期中呼叫的類別。
10.1 攔截電子郵件
攔截器允許您在電子郵件轉交給傳遞代理程式之前對其進行修改。攔截器類別必須實作 .delivering_email(message)
方法,該方法將在傳送電子郵件之前被呼叫。
class SandboxEmailInterceptor
def self.delivering_email(message)
message.to = ["sandbox@example.com"]
end
end
需要使用 interceptors
設定選項來註冊攔截器。您可以在初始化程式檔案中執行此操作,例如 config/initializers/mail_interceptors.rb
Rails.application.configure do
if Rails.env.staging?
config.action_mailer.interceptors = %w[SandboxEmailInterceptor]
end
end
上面的範例使用稱為「staging」的自訂環境,用於類似生產的伺服器,但用於測試目的。您可以閱讀建立 Rails 環境以了解有關自訂 Rails 環境的更多資訊。
10.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