Rails có sẵn một số lớp hỗ trợ gửi email, chúng ta sẽ tìm hiểu cách sử dụng các lớp này.
Chúng ta sẽ gửi mail thông báo xác nhận đã nhận được đơn hàng do người dùng đặt, bạn có thể sử dụng mail server của riêng mình hoặc có thể sử dụng dịch vụ mail nào khác đều được, ở đây mình sẽ sử dụng GMail cho đơn giản.
Có một lưu ý là vào năm 2014 Google đã quyết định khóa tính năng thao tác với email thông qua các ứng dụng kém bảo mật, do đó bạn phải truy cập vào https://www.google.com/settings/security/lesssecureapps và click chọn Turn on để cho phép các ứng dụng bên ngoài có thể truy cập từ xa được, ngoài ra nếu tài khoản của bạn có sử dụng xác thực 2 bước thì bạn cũng phải tắt tính năng này đi mới sử dụng được.
Cấu hình email
Thao tác cấu hình cũng không có gì nhiều để làm, trong thư mục config/environments
có 3 file là development.rb, test.rb
và production.rb
dùng để khai báo cấu hình tương ứng với từng môi trường mà chúng ta đã tìm hiểu. Chúng ta đang cấu hình cho môi trường phát triển nên sửa lại file development.rb
như sau:
Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. config.cache_classes = false # Do not eager load code on boot. config.eager_load = false # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. config.assets.debug = true # Asset digests allow you to set far-future HTTP expiration dates on all assets, # yet still be able to expire them through the digest params. config.assets.digest = true # Adds additional error checking when serving assets at runtime. # Checks for improperly declared sprockets dependencies. # Raises helpful error messages. config.assets.raise_runtime_errors = true # Raises error for missing translations # config.action_view.raise_on_missing_translations = true config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :address => 'smtp.gmail.com', :port => 587, :domain => 'phocode.com', :authentication => 'plain', :user_name => 'phocode7@gmail.com', :password => '<mật khẩu>', :enable_starttls_auto => true } end
Việc gửi mail sẽ sử dụng phương thức SMTP, các thông số khác như địa chỉ server,
port...
của GMail là smtp.gmail.com trên cổng 587…
Tạo ActionMailer
Đầu tiên chúng ta chạy lệnh rails generate mailer
như sau:
C:\Projects\Rails\depot>rails generate mailer Notifier order_received ...
Lệnh trên sẽ tạo một lớp có tên Notifier
kế thừa từ lớp ActionMailer::Base
, nằm trong file notifier.rb
trong thư mục app/mailers
. Trong lớp này có phương thức order_received
do chúng ta khai báo. Mặc định file này có nội dung như sau:
class Notifier < ApplicationMailer # Subject can be set in your I18n file at config/locales/en.yml # with the following lookup: # # en.notifier.order_received.subject # def order_received @greeting = "Hi" mail to: "to@example.org" end end
Chúng ta chỉnh sửa lại một chút như sau:
class Notifier < ApplicationMailer default :from => "Pho Code <phocode7@gmail.com>" def order_received(order) @order = order mail :to => @order.email, :subject => "We've received your order" end end
Chúng ta cho phương thức này nhận vào tham số là một đối tượng Order
vì chỉ có lớp này mới lưu các thông tin về người đặt hàng.
Phương thức mail
sẽ thực sự thực hiện việc gửi email, phương thức này nhận vào các tham số:
to:
địa chỉ người nhậnfrom:
địa chỉ người gửisubject:
tiêu đềcc:
Carbon copy (không bắt buộc)
Tuy nhiên ở đây chúng ta chỉ truyền vào 2 tham số là to
và subject
thôi, còn from
thì chúng ta khai báo là ở dòng default :from...
ở đầu file. Ý nghĩa của dòng này là bất kỳ phương thức mail
nào cũng sẽ sử dụng tham số :from
được khai báo trong dòng default
.
Mail Template
Tuy nhiên bạn sẽ nhận ra thành phần còn thiếu đó là nội dung mail. Nội dung sẽ nằm trong file có tên order_received.text.erb
hoặc order_received.html.erb
trong thư mục app/views/notifier,
2 file này được tạo tự động khi chúng ta chạy lệnh rails generate mailer
.
Các file này cũng được gọi là file template giống như Controller thì có View vậy, chỉ khác là ở đây các file này dùng để hiển thị nội dung cho email. File có đuôi .text.erb
dùng để hiển thị email dạng text, tức là không thể dùng các thẻ HTML để làm cho có màu mè được.
Mặc định thì Rails sẽ sử dụng template trong file .html.erb
.
Chúng ta sửa lại file order_received.html.erb
như sau:
<h3>Books Store</h3> <p> Dear <b><%= @order.name %></b>, </p> <p> Thank you for your order, your items: </p> <table> <tr> <th colspan="2">Quantity</th> <th>Description</th> </tr> <%= render @order.line_items %> </table> <p>Your payment type: <b><%= @order.pay_type %></b></p> <p>Thanks for shopping with <b>Books Store<b> and best regards.</p>
Chúng ta có thể gọi các hàm helper, gọi hàm render
như bình thường.
Gửi email
Chúng ta sẽ cho gửi email khi người dùng tạo Order
thành công, do đó chúng ta sửa lại phương thức create
trong lớp OrdersController
như sau:
class OrdersController < ApplicationController . . . # POST /orders # POST /orders.json def create @order = Order.new(order_params) @order.add_line_items_from_cart(current_cart) respond_to do |format| if @order.save Cart.destroy(session[:cart_id]) session[:cart_id] = nil Notifier.order_received(@order).deliver format.html { redirect_to '/', notice: 'Thank you for your order' } format.json { render :show, status: :created, location: @order } else format.html { render :new } format.json { render json: @order.errors, status: :unprocessable_entity } end end end . . . end
Để thực hiện việc gửi mail thì chúng ta gọi phương thức order_received()
đã định nghĩa ở trên,
sau đó gọi phương thức deliver()
.
Vậy là xong, bây giờ mỗi khi người dùng đặt hàng thì sẽ có mail gửi tới người dùng đó.