1 Action Mailer คืออะไร?
Action Mailer ช่วยให้คุณสามารถส่งอีเมลจากแอปพลิเคชันของคุณโดยใช้คลาส mailer และ views
1.1 Mailer คล้ายกับ Controller
Mailer สืบทอดมาจาก ActionMailer::Base
และอยู่ใน app/mailers
นอกจากนี้ Mailer ยังทำงานอย่างคล้ายคลึงกับ Controller ตัวอย่างบางส่วนของความคล้ายคลึงคือ:
- มี Actions และยังมี views ที่เกิดขึ้นใน
app/views
- ตัวแปร Instance ที่สามารถเข้าถึงได้ใน views
- สามารถใช้ layouts และ partials ได้
- สามารถเข้าถึง params hash ได้
2 การส่งอีเมล
ส่วนนี้จะให้คำแนะนำขั้นตอนการสร้าง mailer และ views
2.1 การสร้าง Mailer
2.1.1 สร้าง Mailer
$ 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
เห็นได้ว่าคุณสามารถสร้าง mailer เหมือนกับการใช้ generator อื่น ๆ กับ Rails
หากคุณไม่ต้องการใช้ generator คุณสามารถสร้างไฟล์ของคุณเองภายใน app/mailers
แต่ต้องแน่ใจว่ามันสืบทอดมาจาก ActionMailer::Base
:
class MyMailer < ActionMailer::Base
end
2.1.2 แก้ไข Mailer
Mailer มีเมธอดที่เรียกว่า "actions" และใช้ views เพื่อกำหนดโครงสร้างเนื้อหาของมัน ที่ Controller สร้างเนื้อหาเช่น HTML เพื่อส่งกลับไปยังไคลเอนต์ Mailer สร้างข้อความเพื่อส่งผ่านทางอีเมล
app/mailers/user_mailer.rb
มี mailer ที่ว่างเปล่า:
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 user-settable attributes.
- เมธอด
default
ตั้งค่าค่าเริ่มต้นสำหรับอีเมลทั้งหมดที่ส่งจาก mailer นี้ ในกรณีนี้เราใช้มันเพื่อตั้งค่าค่า:from
สำหรับข้อความทั้งหมดในคลาสนี้ สามารถเขียนทับได้ตามแต่ละอีเมล - เมธอด
mail
สร้างข้อความอีเมลจริง ในที่นี้เราใช้มันเพื่อระบุค่าของส่วนหัวเช่น:to
และ:subject
ต่ออีเมลละ
2.1.3 สร้างมุมมองของ Mailer
สร้างไฟล์ที่เรียกว่า welcome_email.html.erb
ใน app/views/user_mailer/
นี้จะเป็นเทมเพลตที่ใช้สำหรับอีเมล รูปแบบเป็น 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 ดังนั้นการส่งทั้งสองแบบจึงเป็นที่นิยม ในการทำเช่นนี้ ให้สร้างไฟล์ที่เรียกว่า welcome_email.text.erb
ใน app/views/user_mailer/
:
ยินดีต้อนรับสู่ example.com, <%= @user.name %>
===============================================
คุณได้ลงทะเบียนเข้าใช้ example.com สำเร็จแล้ว
ชื่อผู้ใช้ของคุณคือ: <%= @user.login %>.
เพื่อเข้าสู่ระบบเว็บไซต์ โปรดตามลิงก์นี้: <%= @url %>.
ขอบคุณที่เข้าร่วมและขอให้คุณมีวันที่ดี!
เมื่อคุณเรียกใช้เมธอด mail
ตอนนี้ Action Mailer จะตรวจจับเทมเพลตสองรูปแบบ (ข้อความและ HTML) และสร้างอีเมล multipart/alternative
โดยอัตโนมัติ
2.1.4 เรียกใช้ Mailer
Mailer นั้นเป็นวิธีการแสดงผลวิวอีกวิธีหนึ่ง แตกต่างจากการแสดงผลวิวและส่งผ่านโปรโตคอล HTTP แทนที่จะส่งผ่านโปรโตคอลอีเมล ด้วยเหตุนี้ จึงเหมาะสมที่จะให้คอนโทรลเลอร์บอก Mailer ให้ส่งอีเมลเมื่อผู้ใช้ถูกสร้างสำเร็จ
การตั้งค่านี้ง่ายดาย
ก่อนอื่นเราจะสร้าง scaffold User
:
$ bin/rails generate scaffold user name email login
$ bin/rails db:migrate
ตอนนี้เรามีโมเดลผู้ใช้ที่จะใช้เล่น จากนั้นเราจะแก้ไขไฟล์ app/controllers/users_controller.rb
ให้คอนโทรลเลอร์บอก UserMailer
ให้ส่งอีเมลไปยังผู้ใช้ที่ถูกสร้างขึ้นใหม่โดยแก้ไขแอ็กชัน create และแทรกการเรียก UserMailer.with(user: @user).welcome_email
ตามหลังการบันทึกผู้ใช้สำเร็จ
เราจะเพิ่มอีเมลให้ส่งไปในคิวโดยใช้ 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_now
หรือ deliver_later
เพื่อส่งอีเมลได้เอง
ActionMailer::MessageDelivery
เป็นตัวห่อหุ้มของ Mail::Message
หากคุณต้องการตรวจสอบ แก้ไข หรือดำเนินการอื่นๆกับ Mail::Message
คุณสามารถเข้าถึงได้โดยใช้เมธอด message
บนอ็อบเจกต์ ActionMailer::MessageDelivery
2.2 การเข้ารหัสหัวข้ออัตโนมัติ
Action Mailer จัดการการเข้ารหัสอัตโนมัติของอักขระหลายไบต์ภายในหัวข้อและเนื้อหา
สำหรับตัวอย่างที่ซับซ้อนกว่า เช่นการกำหนดชุดอักขระที่แตกต่างหรือการเข้ารหัสข้อความที่เข้ารหัสเอง โปรดอ้างอิงไปที่ไลบรารี Mail library.
2.3 รายการเมธอด Action Mailer ทั้งหมด
มีเพียงสามเมธอดที่คุณต้องการส่งอีเมลเกือบทุกข้อความ:
headers
- ระบุส่วนหัวใดๆในอีเมลที่คุณต้องการ คุณสามารถส่งผ่านแฮชของชื่อฟิลด์และคู่ค่าค่าได้ หรือคุณสามารถเรียกใช้headers[:field_name] = 'value'
ได้attachments
- ช่วยให้คุณเพิ่มไฟล์แนบในอีเมลของคุณ เช่นattachments['file-name.jpg'] = File.read('file-name.jpg')
mail
- สร้างอีเมลจริงๆ คุณสามารถส่ง headers เป็นแฮชไปยังเมธอด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
และส่วนแรกเป็น multipart/alternative
ที่ประกอบด้วยข้อความอีเมลแบบข้อความธรรมดาและ HTML
หมายเหตุ: Mail จะทำการเข้ารหัส Base64 อัตโนมัติสำหรับไฟล์แนบ หากคุณต้องการอย่างอื่น คุณสามารถเข้ารหัสเนื้อหาของคุณและส่งเนื้อหาที่เข้ารหัสและการเข้ารหัสเป็น Hash
ไปยังเมธอด attachments
- ส่งชื่อไฟล์และระบุส่วนหัวและเนื้อหาใน 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 การสร้างไฟล์แนบแบบ Inline
Action Mailer 3.0 ทำให้การสร้างไฟล์แนบแบบ Inline ที่ใช้การแฮ็กกิ้งมาก่อนเวอร์ชัน 3.0 ง่ายและเรียบง่ายมากขึ้น
- ก่อนอื่น เพื่อบอก Mail ให้แปลงไฟล์แนบเป็นไฟล์แนบแบบ Inline คุณเพียงเรียกใช้
#inline
บนเมธอด attachments ภายใน Mailer ของคุณ:
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
นี้จะแสดงเทมเพลต 'another_template.html.erb' สำหรับส่วน HTML และใช้ข้อความที่แสดงผลสำหรับส่วนข้อความ คำสั่ง render เป็นคำสั่งเดียวกับที่ใช้ใน 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 การใช้งานแคชเมลเลอร์วิว
คุณสามารถทำแคชเมลเลอร์วิวเหมือนกับแคชแบบชิ้นเนื้อในมุมมองแอปพลิเคชันโดยใช้ cache
เมธอด
<% cache do %>
<%= @company.name %>
<% end %>
และในการใช้งานคุณต้องกำหนดค่าแอปพลิเคชันของคุณดังนี้:
config.action_mailer.perform_caching = true
การแคชแบบชิ้นเนื้อยังรองรับในอีเมลหลายส่วน อ่านเพิ่มเติมเกี่ยวกับการแคชในคู่มือการแคชของ Rails.
2.5 หน้าแบบ Action Mailer
เหมือนกับมุมมองควบคุม คุณยังสามารถมีเลเอาท์เมลเลอร์ได้ ชื่อเลเอาท์ต้องเหมือนกับเมลเลอร์ของคุณ เช่น user_mailer.html.erb
และ user_mailer.text.erb
เพื่อรู้จักอัตโนมัติโดยเมลเลอร์ของคุณเป็นเลเอาท์
ในการใช้ไฟล์ที่แตกต่างกัน ให้เรียกใช้ layout
ในเมลเลอร์ของคุณ:
class UserMailer < ApplicationMailer
layout 'awesome' # ใช้ awesome.(html|text).erb เป็นเลเอาท์
end
เหมือนกับมุมมองควบคุม ใช้ yield
เพื่อแสดงผลมุมมองภายในเลเอาท์
คุณยังสามารถส่ง 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
จะแสดงส่วน HTML โดยใช้ไฟล์ my_layout.html.erb
และส่วนข้อความด้วยไฟล์ 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
หรือใน mailer เอง มันจะโหลดและแสดงผลใหม่โดยอัตโนมัติเพื่อให้คุณสามารถเห็นสไตล์ใหม่ได้ทันที รายการตัวอย่างอีเมลยังมีให้เลือกดูได้ที่ 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 การสร้าง URL ใน Action Mailer Views
ไม่เหมือนกับคอนโทรลเลอร์ อินสแตนซ์เมลเลอร์ไม่มีข้อมูลเกี่ยวกับคำขอเข้ามา ดังนั้นคุณจะต้องระบุพารามิเตอร์ :host
เอง
เนื่องจาก :host
มักจะเป็นค่าที่เหมือนกันทั่วแอปพลิเคชัน คุณสามารถกำหนดค่าได้ทั่วไปใน config/application.rb
:
config.action_mailer.default_url_options = { host: 'example.com' }
เนื่องจากพฤติกรรมนี้ คุณไม่สามารถใช้เฮลเปอร์ *_path
ในอีเมลได้ แทนที่คุณจะต้องใช้เฮลเปอร์ที่เกี่ยวข้อง *_url
ตัวอย่างเช่นแทนที่จะใช้
<%= link_to 'ยินดีต้อนรับ', welcome_path %>
คุณจะต้องใช้:
<%= link_to 'ยินดีต้อนรับ', welcome_url %>
โดยใช้ URL เต็ม ลิงก์ของคุณจะทำงานในอีเมลของคุณ
2.7.1 การสร้าง URL ด้วย url_for
url_for
จะสร้าง URL เต็มโดยค่าเริ่มต้นในเทมเพลต
หากคุณไม่ได้กำหนดค่า :host
ทั่วไป โปรดตรวจสอบว่าคุณได้ส่งมันไปยัง url_for
ด้วย
<%= url_for(host: 'example.com',
controller: 'welcome',
action: 'greeting') %>
2.7.2 การสร้าง URL ด้วย Named Routes
Email clients ไม่มีเนื้อหาเว็บและเพราะฉะนั้นเส้นทางไม่มี URL หลักที่จะสร้างที่อยู่เว็บที่สมบูรณ์ ดังนั้นคุณควรใช้ช่วยเหลือของ named route helpers รุ่น *_url
เสมอ
หากคุณไม่ได้กำหนดค่าตัวเลือก :host
ในระดับทั่วโลก โปรดตรวจสอบให้แน่ใจว่าคุณส่งมันไปยัง URL helper
<%= user_url(@user, host: 'example.com') %>
หมายเหตุ: ลิงก์ที่ไม่ใช่ GET
ต้องการ rails-ujs หรือ jQuery UJS และจะไม่ทำงานในเทมเพลตของ mailer และจะส่งคำขอ GET
ตามปกติ
2.8 เพิ่มรูปภาพใน Action Mailer Views
ไม่เหมือนกับคอนโทรลเลอร์ mailer instance ไม่มีเนื้อหาเกี่ยวกับคำขอเข้ารับเพราะฉะนั้นคุณจะต้องให้พารามิเตอร์ :asset_host
เอง
เนื่องจาก :asset_host
มักจะเป็นค่าคงที่ทั่วแอปพลิเคชันคุณสามารถกำหนดค่าได้ทั่วโลกใน config/application.rb
:
config.asset_host = 'http://example.com'
ตอนนี้คุณสามารถแสดงภาพภายในอีเมลของคุณได้
<%= image_tag 'image.jpg' %>
2.9 ส่งอีเมลแบบ Multipart
Action Mailer จะส่งอีเมลแบบ Multipart โดยอัตโนมัติหากคุณมีเทมเพลตที่แตกต่างกันสำหรับการกระทำเดียวกัน ดังนั้นสำหรับตัวอย่าง UserMailer
ของเราหากคุณมี welcome_email.text.erb
และ welcome_email.html.erb
ใน app/views/user_mailer
Action Mailer จะส่งอีเมลแบบ Multipart พร้อมกับเวอร์ชัน HTML และข้อความที่ตั้งค่าเป็นส่วนที่แตกต่างกัน
ลำดับของส่วนที่ถูกแทรกจะถูกกำหนดโดย :parts_order
ภายใน ActionMailer::Base.default
method
2.10 ส่งอีเมลพร้อมตัวเลือกการส่งแบบไดนามิก
หากคุณต้องการแทนที่ตัวเลือกการส่งเริ่มต้น (เช่นข้อมูลรับ SMTP) เมื่อส่งอีเมลคุณสามารถทำได้โดยใช้ delivery_method_options
ในการกระทำของ mailer
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
2.11 ส่งอีเมลโดยไม่ต้องทำการเรนเดอร์เทมเพลต
อาจมีกรณีที่คุณต้องการข้ามขั้นตอนการเรนเดอร์เทมเพลตและให้เนื้อหาอีเมลเป็นสตริง คุณสามารถทำได้นี้โดยใช้ตัวเลือก :body
ในกรณีเช่นนี้อย่าลืมเพิ่มตัวเลือก :content_type
ระบบจะใช้ค่าเริ่มต้นเป็น text/plain
มิฉะนั้น
ruby
class UserMailer < ApplicationMailer
def welcome_email
mail(to: params[:user].email,
body: params[:email_body],
content_type: "text/html",
subject: "Already rendered!")
end
end
3 Action Mailer Callbacks
Action Mailer ช่วยให้คุณสามารถระบุ before_action
, after_action
และ around_action
เพื่อกำหนดค่าข้อความ และ before_deliver
, after_deliver
และ around_deliver
เพื่อควบคุมการส่ง
Callbacks สามารถระบุด้วยบล็อกหรือสัญลักษณ์เป็นเมธอดในคลาสเมลเลือกเหมือนกับคอนโทรลเลอร์
คุณสามารถใช้
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} 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
คุณสามารถใช้
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
เพื่อบันทึกการส่งข้อความMailer callbacks ยกเลิกการประมวลผลเพิ่มเติมหากตั้งค่า body เป็นค่าที่ไม่ใช่ nil
before_deliver
สามารถยกเลิกได้ด้วยthrow :abort
การใช้ Action Mailer Helpers
Action Mailer สืบทอดมาจาก AbstractController
ดังนั้นคุณสามารถเข้าถึง helpers เหมือนกับ Action Controller ได้เกือบทั้งหมด
นอกจากนี้ยังมีเมธอด helper ที่เฉพาะเจาะจงสำหรับ Action Mailer ที่ใช้ได้ใน ActionMailer::MailHelper
. ตัวอย่างเช่น คุณสามารถเข้าถึง instance ของ mailer จาก view ของคุณได้ด้วย mailer
, และเข้าถึงข้อความด้วย message
:
<%= stylesheet_link_tag mailer.name.underscore %>
<h1><%= message.subject %></h1>
4 การกำหนดค่า Action Mailer
ตัวเลือกการกำหนดค่าต่อไปนี้เหมาะสมที่สุดเมื่อต้องทำในไฟล์ environment (environment.rb, production.rb, เป็นต้น)
การกำหนดค่า | คำอธิบาย |
---|---|
logger |
สร้างข้อมูลเกี่ยวกับการส่งอีเมลถ้ามีข้อมูลให้ใช้งาน. สามารถกำหนดให้เป็น nil เพื่อไม่มีการบันทึก. สามารถใช้ร่วมกับ Logger ของ Ruby และ Log4r loggers ได้. |
smtp_settings |
อนุญาตให้กำหนดค่าอย่างละเอียดสำหรับวิธีการส่ง :smtp :
|
sendmail_settings |
อนุญาตให้คุณแทนที่ตัวเลือกสำหรับวิธีการส่ง :sendmail .
|
raise_delivery_errors |
ว่าควรเกิดข้อผิดพลาดหรือไม่หากอีเมลล้มเหลวในการส่ง. สิ่งนี้ทำงานเฉพาะเมื่อเซิร์ฟเวอร์อีเมลภายนอกได้กำหนดค่าให้ส่งทันที. ค่าเริ่มต้นคือ true . |
delivery_method |
กำหนดวิธีการส่ง. ค่าที่เป็นไปได้คือ:
|
perform_deliveries |
กำหนดว่าจะดำเนินการส่งจริงหรือไม่เมื่อเรียกใช้เมธอด deliver บนข้อความ Mail. ค่าเริ่มต้นคือใช่ แต่สามารถปิดการใช้งานเพื่อช่วยในการทดสอบฟังก์ชันได้. หากค่านี้เป็น false , อาร์เรย์ deliveries จะไม่ถูกเติมค่า แม้ว่า delivery_method จะเป็น :test อยู่เสมอ. |
deliveries |
เก็บอีเมลล์ทั้งหมดที่ส่งออกผ่าน Action Mailer ด้วย delivery_method เป็น :test อยู่. มีประโยชน์มากที่สุดสำหรับการทดสอบหน่วยและฟังก์ชัน. |
delivery_job |
คลาสงานที่ใช้กับ deliver_later . ค่าเริ่มต้นคือ ActionMailer::MailDeliveryJob . |
deliver_later_queue_name |
ชื่อคิวที่ใช้กับ delivery_job ค่าเริ่มต้นคือคิว Active Job ที่เป็นค่าเริ่มต้น. |
default_options |
อนุญาตให้คุณกำหนดค่าเริ่มต้นสำหรับตัวเลือกของเมธอด mail (:from , :reply_to , เป็นต้น). |
สำหรับการกำหนดค่าที่เป็นไปได้อย่างละเอียดดูที่ การกำหนดค่า Action Mailer ในเอกสาร Configuring Rails Applications ของเรา
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 การกำหนดค่า Action Mailer สำหรับ Gmail
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 การทดสอบ Mailer
คุณสามารถหาคำแนะนำอย่างละเอียดเกี่ยวกับวิธีการทดสอบ Mailer ของคุณในเอกสาร คู่มือการทดสอบ
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 การสังเกตอีเมล
Observers ช่วยให้คุณเข้าถึงข้อความอีเมลหลังจากที่ส่งไปแล้ว คลาส Observer จะต้องมีการสร้างเมธอด :delivered_email(message)
ซึ่งจะถูกเรียกใช้หลังจากที่อีเมลถูกส่ง
class EmailDeliveryObserver
def self.delivered_email(message)
EmailDelivery.log(message)
end
end
เหมือนกับ interceptors คุณต้องลงทะเบียน observers โดยใช้ตัวเลือก config observers
คุณสามารถทำได้ในไฟล์ initializer เช่น config/initializers/mail_observers.rb
:
Rails.application.configure do
config.action_mailer.observers = %w[EmailDeliveryObserver]
end
ข้อเสนอแนะ
คุณสามารถช่วยปรับปรุงคุณภาพของคู่มือนี้ได้
กรุณาช่วยเพิ่มเติมหากพบข้อผิดพลาดหรือข้อผิดพลาดทางความจริง เพื่อเริ่มต้นคุณสามารถอ่านส่วน การสนับสนุนเอกสาร ของเราได้
คุณอาจพบเนื้อหาที่ไม่สมบูรณ์หรือเนื้อหาที่ไม่ได้อัปเดต กรุณาเพิ่มเอกสารที่ขาดหายไปสำหรับเนื้อหาหลัก โปรดตรวจสอบ Edge Guides ก่อนเพื่อตรวจสอบ ว่าปัญหาได้รับการแก้ไขหรือไม่ในสาขาหลัก ตรวจสอบ คู่มือแนวทาง Ruby on Rails เพื่อดูรูปแบบและกฎเกณฑ์
หากคุณพบข้อผิดพลาดแต่ไม่สามารถแก้ไขได้เอง กรุณา เปิดปัญหา.
และสุดท้าย การสนทนาใด ๆ เกี่ยวกับ Ruby on Rails เอกสารยินดีต้อนรับที่สุดใน เว็บบอร์ดอย่างเป็นทางการของ Ruby on Rails.