okochangの馬鹿でありがとう

ふらふら適当に世間を生きる日々でございます

Railsの問い合わせフォームからSESでメールを送信する

こんにちは。
以前Amazon SESをSMTPインターフェースで使う時のまとめというエントリを書きましたが、遊びでRailsのお問い合わせフォームからSESでメールを送信させていたのでログとして残しておきます。
内容はほぼこちらの内容のまんまです。

環境

以下の環境で動作確認をしています。

手順

最初にRailsのプロジェクト(infra-apps)を作ります。

$ rails new infra-apps
$ cd infra-apps/

application.rbにSESのSMTP情報を入力します。
以下の例ではSMTP情報を環境変数から取得しているので、.bashrcやら.rvmrcで別途設定をしておいて下さい。

$ emacs config/application.rb 
require File.expand_path('../boot', __FILE__)

require 'rails/all'

if defined?(Bundler)
  Bundler.require(*Rails.groups(:assets => %w(development test)))
end

module InfraApps
  class Application < Rails::Application
    config.encoding = "utf-8"
    config.filter_parameters += [:password]
    config.active_support.escape_html_entities_in_json = true
    config.active_record.whitelist_attributes = true
    config.assets.enabled = true
    config.assets.version = '1.0'
    config.action_mailer.smtp_settings = {
      :address => "email-smtp.us-east-1.amazonaws.com",
      :port => 587,
      :user_name => ENV["SMTP_USERNAME"],
      :password => ENV["SMTP_PASSWORD"],
      :authentication => :login
    }
    config.action_mailer.default_url_options = {
      :host => ENV["SMTP_DOMAIN"]
    }
  end
end

問い合わせ内容のバリデーションをするためにmessage.rbを作ります。

$ emacs app/models/message.rb
class Message
  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming
  attr_accessor :name, :email, :subject, :body

  validates :name, :email, :subject, :body, :presence => true
  validates :email, :format => { :with => %r{.+@.+\..+} }

  def initialize(attributes = {})
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end

  def persisted?
    false
  end

end

以下のコマンドを実行してMailerを作ります。

$ rails g mailer NotificationsMailer

notifications_mailer.rbを編集します。
from:のアドレスにはSESのVerified Senderに登録したメールアドレスを設定し、to:のアドレスは適宜変更します。

$ emacs app/mailers/notifications_mailer.rb
class NotificationsMailer < ActionMailer::Base
  default from: "noreply@okochang.com"
  default to: "okochang@example.com"
  def new_message(message)
    @message = message
    mail(:cc => message.email, :subject => "#{message.subject}")
  end
end

送信されるメールのテンプレートを作成します。

$ emacs app/views/notifications_mailer/new_message.text.erb 
Name: <%= @message.name %>
Body: <%= @message.body %>

contactコントローラを作成します。

$ rails g controller contact

contact_controllerを編集します。

$ emacs app/controllers/contact_controller.rb
# -*- coding: utf-8 -*-
class ContactController < ApplicationController
  def new
    @message = Message.new
  end

  def create
    @message = Message.new(params[:message])

    if @message.valid?
      NotificationsMailer.new_message(@message).deliver
      flash.now.alert = "メッセージを送信しました。"
      render :action => 'result', :notice => "Message was successfully sent."
    else
      flash.now.alert = "必要項目を入力して下さい。"
      render :new
    end
  end

  def result
  end
end

ルーティングの設定をします。

$ emacs config/routes.rb
InfraApps::Application.routes.draw do
  match 'contact' => 'contact#new', :as => 'contact', :via => :get
  match 'contact' => 'contact#create', :as => 'contact', :via => :post
end

問い合わせ内容の入力フォームを作成します。

$ emacs app/views/contact/new.html.erb 
<h1>お問い合わせ内容入力画面</h1>
<%= form_for @message, :url => contact_path do |form| %>
  <fieldset class="fields">
    <div class="field">
      <%= form.label :name %>
      <%= form.text_field :name %>
    </div>

    <div class="field">
      <%= form.label :email %>
      <%= form.text_field :email %>
    </div>
    
    <div class="field">
      <%= form.label :subject %>
      <%= form.text_field :subject %>
    </div>

    <div class="field">
      <%= form.label :body %>
      <%= form.text_area :body %>
    </div>
  </fieldset>
  
  <fieldset class="actions">
    <%= form.submit "Send" %>
  </fieldset>
<% end %>
<%= flash[:alert] %>

送信完了画面を作成します。

$ emacs app/views/contact/result.html.erb 
<h1>送信結果</h1>
<%= flash[:alert] %>

以下のコマンドでWebサーバを起動してhttp://localhost:3000/contactにアクセスすると問い合わせフォームが表示されます。

$ rails s

まとめ

SMTPで接続出来るのでGmailなどに接続する場合とあまり変わりませんでした。
ちなみにSMTP接続ではない場合はこちらにあるように設定するみたいです。