+5

Action Mailer Basics

Introduction

Trong bài này các bạn sẽ cung cấp tất cả những gì cần thiết để có thể gửi và nhận mail từ rails app của bạn.

  1. Làm thế nào để có thể gửi và nhận mail với rails app
  2. Làm thế nào để tạo và edit Action mailer class

Send email

Tạo mailer

$ bin/rails generate mailer UserMailer
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: "from@example.com"
  layout 'mailer'
end
 
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
end

Có thể thấy, bạn có thể tạo mailer giống như là generator khác trong Rails. Mailer được xem giống như là Controller và có thể tạo mailer, tạo thư mục để view và test.

Edit mailer

Mailer thì nó rất giống với Controller. Nó cũng có các method gọi "action" và sử dụng view để xây dựng nội dung, nơi mà controller tạo ra nội dung html để send đến client thì cũng tương tự tại đó mailer sẽ tạo nội dung để gửi qua mail.

class UserMailer < ApplicationMailer
end

Hãy add method gọi welcome mailer welcome_email. Nó sẽ gửi email đến mail đã đăng ký


class UserMailer < ApplicationMailer
  default from: 'notifications@example.com'
 
  def welcome_email(user)
    @user = user
    @url  = 'http://example.com/login'
    mail(to: @user.email, subject: 'Welcome to My Awesome Site')
  end
end

Tạo mailer view

Tạo file welcome_email.html.erb trong app/views/user_mailer/. Nó sẽ trở thành template để view mail và sử dụng format html.


<!DOCTYPE html>
<html>
  <head>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
  </head>
  <body>
    <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: <%= @url %>.
    </p>
    <p>Thanks for joining and have a great day!</p>
  </body>
</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!

Gọi bạn gọi call mail method. Action mail sẽ detect ra 2 template (text & html) và tự động tạo ra multipart/alternative email

Gọi mailer

Mailers thật ra là một cách khác để render một view, thay vì render một view và gửi nó thông qua phương thức HTTP, mailer sẽ gửi nó thông qua "phương thức email". Do đó, sẽ rất tiện cho controller có thể ra lệnh cho Mailer gửi một email khi user được tạo thành công Giờ chúng ta thử cài nào. Đầu tiên cần tạo một scaffold cho model User:

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

Sau khi chạy lệnh xong thì chúng ta đã có model User để vọc rồi, chúng ta chỉ cần edit file users_controller.rb để nó bảo UserMailer gửi một email tới thằng user vừa mới được tạo bằng cách sửa hàm create và insert một lời gọi vào trong UserMailer.welcome_mail ngay sau khi save user đó thành công. Action Mailer họat động rất ổn với Active Job nên bạn có thể gửi mail ngay bên ngoài "vòng lặp" request-response, do đó user không cần phải đợi lâu


class UsersController < ApplicationController
  # POST /users
  # POST /users.json
  def create
    @user = User.new(params[:user])
 
    respond_to do |format|
      if @user.save
        # Tell the UserMailer to send a welcome email after save
        UserMailer.welcome_email(@user).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

Nếu bạn muốn gửi email một cách chuẩn (chẳng hạn từ cronjob) thì chỉ cần gọi hàm deliver_now

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

Method welcome_email sẽ trả về object ActionMailler::MessageDelivery và nó có tác dụng bảo deliver_now hoặc deliver_later gửi mail đi. Object ActionMailer::MessageDelivery chỉ là một lớp bọc bên ngoài của object Mail::Message. Nếu bạn muốn tìm hiểu sâu hơn hoặc làm cái gì đó với thằng Mail::Message thì có thể sử dụng hàm mesage trong object ActionMailer::MessageDelivery.

Receiving Emails

Trước khi email đến Rails App, bạn cần phải cấu hình hệ thống để forward cái email đó đến App. Vì vậy, để app có thể nhận được mail bạn cần phải: Implement method receive trong mailer Config server để forward email từ chỗ muốn nhận đến app . Dưới đây là ví dụ đơn giản:

class UserMailer < ApplicationMailer
  def receive(email)
    page = Page.find_by(address: email.to.first)
    page.emails.create(
      subject: email.subject,
      body: email.body
    )
 
    if email.has_attachments?
      email.attachments.each do |attachment|
        page.attachments.create({
          file: attachment,
          description: email.subject
        })
      end
    end
  end
end

Hi vọng thông qua bài viết này, bạn có thể hiểu được phần nào cơ chế gửi và nhận mail trong rails app. Để xem thông tin bài viết hơn, bạn có thể tham khảo link bài viết bên dưới: http://guides.rubyonrails.org/action_mailer_basics.html Thanks for reading!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí