おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

Rails 3 の Action Mailerまとめ

Ruby on Rails Guides: Action Mailer Basicsを読んでの自分用メモです。

Mailerを作る

rails generate mailer UserMailer

Mailer概要

class UserMailer < ActionMailer::Base
  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

viewに配置したファイル名でHTMLメール、テキストメールを判別できる。

  • welcome_email.html.erbのようなファイル名だとHTMLメールにできる。
  • welcome_email.text.erbのようにするとテキストメールにできる
  • html.erb と text.erb を両方作っていた場合、自動で multipart/alternative 形式*1にしてくれる。

mailメソッドの引数:parts_orderで挿入される順番を指定できる。または下記のように書くとhtmlが先に挿入されて、後にtextが入る。

class UserMailer < ActionMailer::Base
  def welcome_email(user)
    @user = user
    @url = user_url(@user)
    mail(:to => user.email,
         :subject => "Welcome to My Awesome Site") do |format|
      format.html
      format.text
    end
  end 
end

メール送るには、例えばcontrollerなどで下記のようにする。

UserMailer.welcome_email(@user).deliver

welcome_emailメソッドはMail::Messageオブジェクトを返す。deliverメソッドで自身を送る。

Action Mailerはメールを自動でエンコードしてくれる。UTF-8使ってるなら特別なことは何も設定しなくても良きに計らってくれる。

Action Mailerのメソッド

# headersメソッドでheaderを指定
headers["X-Spam"] = value
# 一度に複数のkey/valueの設定も出来る
headers {"X-Spam" => value, "X-Special" => another_value}
# mailメソッドの引数でもheaderを指定できる
mail("X-Spam" => value)
# デフォルトで値が設定されているheaderを削除したいときにはnilを指定する
headers["X-Spam"] = nil
# mime_typeは自動で推測してくれる、自動でBase64エンコードもしてくれる。
attachments["file-name.jpg"] = File.read("file-name.jpg")
# 添付ファイルに対してエンコード方式の指定/mime typeの指定ができる
# エンコードの指定をしたときは、既にエンコード済みと判断してBase64エンコードはしない
encoded_content = SpecialEncode(File.read('/path/to/filename.jpg'))
attachments['filename.jpg'] = {:mime_type => 'application/x-gzip',
                               :encoding => 'SpecialEncoding',
                               :content => encoded_content }

URL, layout

renderメソッドはcontrollerと同じオプションで使える。

class UserMailer < ActionMailer::Base 
  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") do |format|
      format.html { render 'another_template'  }
      format.text { render 'another_template'  }
    end
  end 
end

controllerと同じようにlayoutも使える

class UserMailer < ActionMailer::Base 
  layout 'awesome' # use awesome.(html|text).erb as the layout 
end

renderメソッドのオプションとしてもlayoutの指定が出来る

class UserMailer < ActionMailer::Base 
  def welcome_email(user)
    mail(:to => user.email) do |format|
      format.html { render :layout => 'my_layout' }
      format.text
    end
  end
end

mailerでもurl_forやnamed routeが使えるけど、mailerのurl_forはhostやcontroller、actionなどの情報を持っていないので指定してあげる必要がある

<%= url_for(:host => "example.com",
            :controller => "welcome",
            :action => "greeting") %>

named routeはhostだけ指定してあげる必要がある。メールはwebと違ってwebアドレスのコンテキストは持ってないので _pathは使っちゃダメ。

<%= user_url(@user, :host => "example.com") %>

default_url_optionsでデフォルトのhostを設定できる

class UserMailer < ActionMailer::Base
  default_url_options[:host] = "example.com"
  def welcome_email(user)
    @user = user
    @url = user_url(@user)
    mail(:to => user.email,
         :subject => "Welcome to My Awesome Site")
  end
end

Action Mailerは Abstract Controllerを継承してるので Action Controllerと同じヘルパーメソッドがつかえるらしい。

メールの受信

下記の事前準備が必要

  • mailer に receive メソッドを実装
  • emailサーバにrailsアプリに対してメールを送信するように設定する

受け取るために

rails runner 'UserMailer.receive(STDIN.read)'

のようにする。UserMailer.receiveとすると、emailオブジェクトを作ってデコードしてMailerオブジェクトをインスタンス化してreceiveメソッドを呼び出す。

下記のような感じでreceiveメソッドを実装する。

class UserMailer < ActionMailer::Base
  def receive(email)
    page = Page.find_by_address(email.to.first)
    page.emails.create(
      :subject => email.subject,
      :body => email.body
    )

    if email.has_attachments?
      for attachment in email.attachments
        page.attachments.create({
          :file => attachment,
          :description => email.subject
        })
      end
    end
  end 
end

設定

template_root
viewのrootを設定
logger
loggerを設定
delivery_method
メールを送信する方法を指定。:smtp, :sendmail, :testの三種類が指定できる。
raise_delivery_errors
メール送信が失敗したときにエラーを発生させるか否かを指定
perform_deliveries
devlierメソッドで実際にメールを送信するか否か
smtp_settings

smtpの設定。delivery_methodが:smtpのときに設定できる。

address
リモートのメールサーバのアドレス。デフォルトlocalhost
port
メールサーバのポート。デフォルト25
domain
HELOドメインを指定
user_name
認証用のユーザ名
password
認証用のパスワード
authentication
認証方法、plain, login, cram_md5の三種類が指定できる。
sendmail_settings

sendmailを使う時の設定。delivery_methodが:sendmailの時に設定できる

location
sendmailのパス。デフォルト/usr/sbin/sendmail
arguments
sendmailに渡すオプション。デフォルト -i -t

*1:txtとhtmlを両方送って、htmlが見れないときにtxtを表示する形式