使用 ActionMailer


在Rails中,使用ActionMailer建立模型與郵件回應內容,在發送郵件之前,得先設定郵件伺服器,這主要是使用config.action_mailer.delivery_method設定,預設值為:smtp,表示使用SMTP協定傳送郵件,另外還可以設定的選項是:sendmail、:file與:test。

如果使用預設的SMTP,Gmail的設定為例:

config.action_mailer.smtp_settings = {
    :address => "smtp.gmail.com",
    :port => "587",
    :domain => "gmail.com",
    :authentication => "plain",
    :user_name => "example@gmail.com", # 你的郵件
    :password => "123456",             # 你的密碼
    :enable_starttls_auto => true
 }

接著可以產生郵件模型:

~\$ rails generate mailer UserMailer
      create  app/mailers/user_mailer.rb
      invoke  erb
      create    app/views/user_mailer
      invoke  test_unit
      create    test/functional/user_mailer_test.rb


接著可以編輯app/mailers/user_mailer.rb:
  • user_mailer.rb
class UserMailer < ActionMailer::Base
    default :from => "example@gmail.com" # 你的郵件

    def welcome(user)
        @user = user
        mail(:to => user.email, :subject => "Welcome to Openhome.cc")
    end
end

與控制器類似,實例變數在執行完welcome方法之後,可於郵件內容樣版中取用。default方法可設定mail方法中要用到的選項之預設值,:from表示郵件寄件者,:to表示收件者,:subject是郵件主題。

執行完welcome方法之後,郵件內容樣版會使用app/views/user_mailer/welcome.txt.erb或app/views/user_mailer/welcome.html.erb,如果兩者都存在,則Rails自動產生multiplepart/alternative郵件。例如想撰寫welcome.txt.erb,可以如下:
  • welcome.txt.erb
Welcome to Openhome.cc, <%= @user.name %>
Thanks for joining and have a great day!

或想撰寫welcome.html.erb,可以如下:

  • welcome.html.erb
<!DOCTYPE html>
<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
  </head>
  <body>
    <h1>Welcome to Openhome.cc, <%= @user.name %></h1>
    <p>Thanks for joining and have a great day!</p>
  </body>
</html>

如上定義之後,想要發送郵件,不需要自行實例化UserMailer,可以直接呼叫UserMailer.welcome並傳入所需的物件,UserMailer.welcome會處理郵件設定相關細節,實例化UserMailer,呼叫其welcome實例方法,然後傳回Mail::Message實例,呼叫Mail::Message實例的deliver方法,就會進行郵件傳送,也就是說,要傳送郵件只要如下就可以了:

UserMailer.welcome(user).deliver

例如在Rails console中測試一下以上程式:

~gossip\$ rails c
Loading development environment (Rails 3.1.3)
irb(main):001:0> user = Class.new {
irb(main):002:1*     def email
irb(main):003:2>         "some@gmail.com"
irb(main):004:2>     end
irb(main):005:1>     def name
irb(main):006:2>         "Some"
irb(main):007:2>     end
irb(main):008:1> }.new
=> #<#<Class:0x9f8f364>:0x9f8f300>
irb(main):009:0> UserMailer.welcome(user).deliver
=> #<Mail::Message:91566930, Multipart: true, Headers: <Date: Mon, 13 Feb 2012 10:29:42 +0800>, <From: example@gmail.com>, <To: some@gmail.com>, <Message-ID: <4f3875967ca9a_878495a5fc403bd@caterpillar-VirtualBox.mail>>, <Subject: Welcome to Openhome.cc>, <Mime-Version: 1.0>, <Content-Type: multipart/alternative; boundary="--==_mimepart_4f3875965413f_878495a5fc4004d"; charset=UTF-8>, <Content-Transfer-Encoding: 7bit>>
irb(main):010:0>

如果要附加檔案,可以使用attachments。例如:

  • user_mailer.rb
class UserMailer < ActionMailer::Base
    default :from => "example@gmail.com" # 你的郵件

    def welcome(user)
        @user = user
attachments["caterpillar.jpg"] = File.read("/path/to/caterpillar.jpg")
mail(:to => user.email, :subject => "Welcome to Openhome.cc") end end

如果要將附件內嵌在郵件之中,例如圖檔,可以如下:
  • user_mailer.rb
class UserMailer < ActionMailer::Base
    default :from => "example@gmail.com" # 你的郵件

    def welcome(user)
        @user = user
attachments.inline["caterpillar.jpg"] = File.read("/path/to/caterpillar.jpg")
mail(:to => user.email, :subject => "Welcome to Openhome.cc") end end

在HTML郵件內容中,可以使用image_tag輔助方法來顯示內嵌附件。例如:

<%= image_tag attachments["caterpillar.jpg"].url %>