Password reset mailer method

發送重設密碼的郵件程式碼會長這樣:

UserMailer.password_reset(self).deliver_now

重設密碼的郵件的運作方式其實幾乎跟帳號啟動一樣,我們先在 UserMailer 建立一個 password_reset 方法,然後定義純文字和 HTML email 的 view template:

app/mailers/user_mailer.rb

class UserMailer < ApplicationMailer

  def account_activation(user)
    @user = user
    mail to: user.email, subject: "Account activation"
  end

  def password_reset(user)
    @user = user
    mail to: user.email, subject: "Password reset"
  end
end

app/views/user_mailer/password_reset.text.erb

To reset your password click the link below:

<%= edit_password_reset_url(@user.reset_token, email: @user.email) %>

This link will expire in two hours.

If you did not request your password to be reset, please ignore this email and
your password will stay as it is.

app/views/user_mailer/password_reset.html.erb

<h1>Password reset</h1>

<p>To reset your password click the link below:</p>

<%= link_to "Reset password", edit_password_reset_url(@user.reset_token,
                                                      email: @user.email) %>

<p>This link will expire in two hours.</p>

<p>
If you did not request your password to be reset, please ignore this email and
your password will stay as it is.
</p>

跟啟動帳號的郵件一樣,我們可以透過 Rails email previewer 來預覽郵件:

test/mailers/previews/user_mailer_preview.rb

# Preview all emails at http://localhost:3000/rails/mailers/user_mailer
class UserMailerPreview < ActionMailer::Preview

  # Preview this email at
  # http://localhost:3000/rails/mailers/user_mailer/account_activation
  def account_activation
    user = User.first
    user.activation_token = User.new_token
    UserMailer.account_activation(user)
  end

  # Preview this email at
  # http://localhost:3000/rails/mailers/user_mailer/password_reset
  def password_reset
    user = User.first
    user.reset_token = User.new_token
    UserMailer.password_reset(user)
  end
end

預覽畫面如下:

純文字 email:

HTML email:

參考帳號啟動 email 的測試,重設密碼郵件的測試如下:

test/mailers/user_mailer_test.rb

require 'test_helper'

class UserMailerTest < ActionMailer::TestCase

  test "account_activation" do
    user = users(:michael)
    user.activation_token = User.new_token
    mail = UserMailer.account_activation(user)
    assert_equal "Account activation", mail.subject
    assert_equal [user.email], mail.to
    assert_equal ["[email protected]"], mail.from
    assert_match user.name,               mail.body.encoded
    assert_match user.activation_token,   mail.body.encoded
    assert_match CGI::escape(user.email), mail.body.encoded
  end

  test "password_reset" do
    user = users(:michael)
    user.reset_token = User.new_token
    mail = UserMailer.password_reset(user)
    assert_equal "Password reset", mail.subject
    assert_equal [user.email], mail.to
    assert_equal ["[email protected]"], mail.from
    assert_match user.reset_token,        mail.body.encoded
    assert_match CGI::escape(user.email), mail.body.encoded
  end
end

執行測試應該會通過(Green):

$ bundle exec rake test

提交有效的 email 之後,呈現的畫面如下:

也可以在 server log 看到郵件內容:

Sent mail to [email protected] (24.3ms)
Date: Mon, 04 Apr 2016 18:26:19 +0800
From: [email protected]
To: [email protected]
Message-ID: <[email protected]>
Subject: Password reset
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="--==_mimepart_5702414be69a0_7a43fef52cad2401009f";
 charset=UTF-8
Content-Transfer-Encoding: 7bit


----==_mimepart_5702414be69a0_7a43fef52cad2401009f
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

To reset your password click the link below:

https://localhost:3000/password_resets/TMTshEIj-gAvp9_nos8Log/edit?email=example%40railstutorial.org

This link will expire in two hours.

If you did not request your password to be reset, please ignore this email and
your password will stay as it is.


----==_mimepart_5702414be69a0_7a43fef52cad2401009f
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

<html>
  <body>
    <h1>Password reset</h1>

<p>
  To reset your password click the link below:
</p>

<a href="https://localhost:3000/password_resets/TMTshEIj-gAvp9_nos8Log/edit?email=example%40railstutorial.org">Reset password</a>

<p>This link will expire in two hours.</p>

<p>
If you did not request your password to be reset, please ignore this email and
your password will stay as it is.
</p>

  </body>
</html>

----==_mimepart_5702414be69a0_7a43fef52cad2401009f--