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と同じヘルパーメソッドがつかえるらしい。
メールの受信
下記の事前準備が必要
受け取るために
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
*1:txtとhtmlを両方送って、htmlが見れないときにtxtを表示する形式