Action Mailerの基本

このガイドでは、メールの送受信の機能をアプリケーションに実装するための方法と、 Action Mailerの内部構造について説明していきます。 また、開発者のメールを使用したテストについても説明します。

このガイドを読むことで、次の事が学べるはずです。

  • Railsアプリケーションでメールを送受信する方法
  • Action Mailerクラスとメールビューの生成と編集の方法
  • Action Mailerの環境設定方法
  • Action Mailerクラスのテスト方法

1. はじめに

Action Mailerは、Mailerクラスとビューを使用してアプリケーションからメールを送信する機能を提供します。 Mailerはコントローラーに非常に似ています。 app/mailers内のそれらのファイルでは、ActionMailer::Baseを継承し、app/veiws内のビューと関連付けられます。

2. メール送信

この節では、Mailerとそのビューの作成について順を追って説明していきます。

2.1 Mailerの作成のチュートリアル

2.1.1 Mailerの作成
$ rails generate mailer UserMailer
create  app/mailers/user_mailer.rb
invoke  erb
create    app/views/user_mailer
invoke  test_unit
create    test/mailers/user_mailer_test.rb

上記の通り、Railsのジェネレーターを使用して他のものと同様に、Mailerも生成します。 Mailerの概念はコントローラーに似ており、Mailerとビューのディレクトリとテストが生成されます。

ジェネレーターを使用したくないのであれば、自身でapp/mailers内にファイルを作成し、 下記のようにActionMailer::Baseを継承してください。

class MyMailer < ActionMailer::Base
end
2.1.2 Mailerの編集

MailerはRailsのコントローラーに非常に似ています。 同様に"action"と呼ばれるメソッドを持ち、コンテンツの構築にビューを使用します。 コントローラーがHTMLを作成するように、Mailerはメール配信のメッセージを作成します。

app/mailers/user_mailer.rbは、現時点では何も含んでいない状態なので追加していきます。

class UserMailer < ActionMailer::Base
  default from: 'from@example.com'
end

welcome_emailというメソッドを追加し、 ユーザーが登録しているアドレスに送信してみます。

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

ここで、上記のメソッドで使用されている項目について簡単に説明します。 利用可能な前オプションのリストを見たければ、後述する「Action Mailer完全リスト」の"ユーザー設定属性"を参照してください。

defaultハッシュ
このMailerから送信するメールの初期値のハッシュです。 このケースでは、このクラスの全てのメッセージの:fromヘッダーを設定しています。 各メール毎にこの設定を上書きすることも可能です。
mail
実際のメールメッセージで、:to:subjectヘッダーを渡しています。

コントローラーと同様に、メソッド内で定義したインスタンス変数は使用するビュー内で使用可能です。

2.1.3 Mailerビューの作成

welcome_email.html.erbというファイルをapp/views/user_mailer/内に作成します。 これはHTML形式のメールテンプレートとして使用されます。

<!DOCTYPE html>
<html>
  <head>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
  </head>
  <body>
    <h1>example.comへようこそ, <%= @user.name %></h1>
    <p>
      example.comへの登録がが完了しました。
      あなたのユーザー名は<%= @user.login %>です。<br/>
    </p>
    <p>
      このリンクをクリックして、サイトにログインしてください: <%= @url %>.
    </p>
    <p>ご参加いただき、ありがとうございます。楽しんでください!</p>
  </body>
</html>

テキストベースのメールも作成してみましょう。 全てのクライアントがHTMLメールを受け入れるわけでは無いので、両方送信するのがベストです。 welcome_email.text.erbというファイルをapp/views/user_mailer/内に作成します。

example.comへようこそ, <%= @user.name %>
===============================================

example.comの登録がが完了しました。
あなたのユーザー名は <%= @user.login %>です。

このリンクをクリックして、サイトにログインしてください: <%= @url %>.

ご参加いただき、ありがとうございます。楽しんでください!

メールメソッドを呼ぶと、Action Mailerは2つ(テキストとHTML)のテンプレートを見つけ、 自動的にmultipart/alternative形式のメールを生成します。

2.1.4 Mailerの呼び出し

Mailerは、ビューを描画するもう1つの方法です。 ビューを描画し、HTTPプロトコルを送る代わりに、Emailプロトコルを通してそれを送信しています。 コントローラー内でユーザーの作成が成功した際に、その事をメールで通知するのはよくある処理だと思われます。

この設定を行うのは、非常に簡単です。

まず、シンプルなUserのスキャフォールドを作成しましょう。

$ rails generate scaffold user name email login
$ rake db:migrate

Usrモデルが用意できたので、app/controllers/users_controller.rbの createアクションを編集し、UserMailer.welcome_emailの呼び出しの追加して、 ユーザーの保存が完了した後に、UserMailerに新しくユーザーが作成されたことをメールで伝えるように指示します。

class UsersController < ApplicationController
  # POST /users
  # POST /users.json
  def create
    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
        # 保存後にUserMailerにウェルカムメールを送信するように指示
        UserMailer.welcome_email(@user).deliver

        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

welcome_emailメソッドは、自身が配信したもの伝えることが出来るMail::Messageオブジェクトを返します。

2.2 ヘッダー値の自動エンコーディング

Action Mailerは、headerとbody内のマルチバイト文字列の自動エンコーディングを扱います。

自己のエンコーディングテキストや最初の代替文字セット定義ような、より複雑な例についてはメールライブラリを参照してください。

2.3 Action Mailerメソッドの完全リスト

Eメールを送信する際に必要とされるメソッドを3つ説明します。

headers
メールヘッダーの指定を行います。 ヘッダーフィールド名と値のペアのハッシュを渡すか、 またはheaders[:field_name] = 'value'と指定を行います。
attachments
メールへの添付ファイルを追加指定します。 例えば、attachments['file-name.jpg'] = File.read('file-name.jpg')のように指定します。
mail
実際に送信されるメール自身です。 メールのパラメーターとしてヘッダー内にハッシュを渡すことが可能で、 プレーンテキストでもマルチパートでも、定義したメールテンプレートによってメールが生成されます。

2.3.1 添付ファイルの追加

Action Mailerで添付ファイルを追加することは、とても簡単です。

  • ファイル名、内容、Action Mailer、Mail Gemを渡すと、 自動的にmime_typeを推測し、エンコーディングを設定して添付ファイルを作成します。

    attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
    

Mailは添付ファイルを自動的にBase64にエンコードします。 別の事をしたい場合は、コンテンツをエンコードし、 attachmentsにハッシュでエンコードされたコンテンツとエンコーディングを渡します。

  • ファイル名とヘッダーの指定、コンテンツを渡すと、Action MailerとMailは渡された設定を使用します。
  • encoded_content = SpecialEncode(File.read('/path/to/filename.jpg'))
    attachments['filename.jpg'] = {mime_type: 'application/x-gzip',
                                   encoding: 'SpecialEncoding',
                                   content: encoded_content }
    

もし、エンコーディングを指定した場合、Mailは渡されたコンテンツは既にエンコード済みであるとして、 Base64のエンコードを行いません。

2.3.2 インラインの添付ファイルの作成

Action Mailer 3.0は、インラインの添付ファイルを作成することが出来ます。

  • はじめにMailに添付ファイルをインラインにすることを伝えるために、 Mailer内のattachments上で、inlineメソッドを呼び出します。

    def welcome
      attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
    end
    
  • ビュー上で、ハッシュで添付ファイルを参照することが出来るので、表示したい添付ファイルを指定してurlメソッドを呼び出し、 それをimage_tagメソッドに渡します。

    <p>Hello there, this is our image</p>
    
    <%= image_tag attachments['image.jpg'].url %>
    
    
  • これは通常のimage_taguの呼び出しなので、オプションのハッシュを添付ファイルのURLの後に指定することが出来ます。

    <p>Hello there, this is our image</p>
    
    <%= image_tag attachments['image.jpg'].url, alt: 'My Photo',
                                                class: 'photos' %>
    
2.3.3 メールの複数の宛先への送信

:toキーにメールのリストを設定することで、1つのメールを複数人に配信することが可能です。 (例: 新しく登録されたユーザーの情報を全管理者に伝えるなど) メールのリストは、メールアドレスの配列またはカンマ区切りの文字列を指定することが出来ます。

class AdminMailer < ActionMailer::Base
  default to: Proc.new { Admin.pluck(:email) },
          from: 'notification@example.com'

  def new_registration(user)
    @user = user
    mail(subject: "New User Signup: #{@user.email}")
  end
end

同じフォーマットがCc:とBcc:が:cc:bccのそれぞれで、 使用することが出来ます。

2.3.4 名前付きのメール送信

受け取り先のメールに表示されるメールアドレスの代わりに、名前を表示したいことがあるかもしれません。 これをするには、メールアドレスのフォーマットを"名前 <email>"のように変更します。

def welcome_email(user)
  @user = user
  email_with_name = "#{@user.name} <#{@user.email}>"
  mail(to: email_with_name, subject: 'Welcome to My Awesome Site')
end

2.4 Mailerのビュー

Mailerのビューは、app/views/name_of_mailer_class(メーラーのクラス名)のディレクトリに配置されます。 Mailerのビューのファイル名は、Mailerのメソッドと名前が同じであるため、クラスはそれを知ることが出来ます。 上記の例では、welcome_emailメソッド用のMailerビューは、HTMLであればapp/views/user_mailer/welcome_email.html.erbとなり、 テキストであれば、welcome_email.text.erbとなります。

デフォルトのビューを変更したければ、アクションを次のようにします。

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',
         template_path: 'notifications',
         template_name: 'another')
  end
end

このケースでは、app/views/notificationsのテンプレートが参照されるようになります。 また、template_pathに配列でパスを指定すると、順にそれらを参照させる事ができます。

もし、より柔軟な処理をしたい場合、ブロックと描画したいテンプレートまたは、 テンプレートを使用しないテキストやインラインを渡すことも可能です。

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 text: 'Render text' }
    end
  end
end

HTMLでは、'another_template.html.erb'のテンプレート描画され、 テキストでは、指定されたテキストが使用されます。 renderは、Action Controller内で使用されるものと同じで、 :text:inlineなど、使用出来るオプションも全て同じです。

2.5 アクションメーラーのレイアウト

レイアウトが使用出来ることも、コントローラーのビューと同じです。 レイアウト名は、Mailerと同じ名前にする必要があり、 user_mailer.html.erbuser_mailer.text.erbが、 Mailerのレイアウトとして自動的に認識されます。

異なるファイルを使用したい場合は、layoutに次のように指定します。

class UserMailer < ActionMailer::Base
  layout 'awesome' # awesome.(html|text).erbをレイアウトとして使用
end

コントローラーのビューのように、yieldを使用して、 レイアウト内部にビューを描画します。

また、formatブロック内で異なるレイアウトをlayout: 'layout_name'のようにして渡すことが可能です。

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

HTMLの場合は、my_layout.html.erbを使用し、 テキストの場合は通常使用されるuser_mailer.text.erbが存在すれば、それを使用します。

Action Mailer ViewsでのURL生成

コントローラーと違って、Mailerのインスタンスは、やって来るリクエストの情報を持っていないため、 :hostパラメーターに情報を提供してあげる必要があります。

config/application.rbに設定して、:hostがアプリケーション全体で一貫性のあるものにします。

config.action_mailer.default_url_options = { host: 'example.com' }
2.6.1 url_forを使用してURLを生成

url_forを使用する場合、only_path: falseオプションを渡す必要があります。 url_forビューヘルパーは、デフォルトで:hostオプションが明確に指定されていないと、 相対URLを生成してしまうので、絶対URLが生成されるために指定します。

<%= url_for(controller: 'welcome',
            action: 'greeting',
            only_path: false) %>
2.6.2 生成するURLのRoute名について

メールクライアントで表示されることを考慮して、ヘルパーでRoute名のパスを出力する際には、 完全なアドレスを出力するために、"_url"のヘルパーメソッドを使用すべきです。

もし、:hostオプションをグローバル空間で設定していない場合、 URLヘルパーにそれを渡すようにしてください。

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

 Back to top

© 2010 - 2017 STUDIO KINGDOM