はじめに
お問い合わせフォームの実装手順をいつも忘れてしまうので、完全な実装手順をまとめます。
メーラー作成
以下のコマンドを実行し、メーラーを作成します。
$ rails g mailer ContactMailer
作成されたメーラー「app/mailers/contact_mailer.rb」を編集します。
class ContactMailer < ApplicationMailer default from: 'noreply@example.com' default to: 'admin@example.com' layout 'mailer' def send_mail(contact) @contact = contact mail(from: contact.email, to: ENV['MAIL_ADDRESS'], subject: 'Webサイトより問い合わせが届きました') do |format| format.text end end end
メール本文になるテンプレートファイル「app/views/contact_mailer/send_mail.text.erb」を編集します。
<%= @contact.content %> <%= @contact.name %> (<%= @contact.email %>)
コントローラー作成
以下のコマンドを実行し、コントローラーを作成します。
$ rails g controller Contacts
作成されたコントローラー「app/controllers/contacts_controller.rb」を編集します。
class ContactsController < ApplicationController def index @contact = Contact.new end def confirm @contact = Contact.new(contact_params) if @contact.valid? render :action => 'confirm' else render :action => 'index' end end def done @contact = Contact.new(contact_params) if params[:back] render :action => 'index' else ContactMailer.send_mail(@contact).deliver_now render :action => 'done' end end private def contact_params params.require(:contact).permit(:name, :email, :content) end end
モデル作成
メールを送信するだけならDBは必要ないので、ActiveModelを使います。
「app/models/contact.rb」を手動作成(rails generateは使わない)し、編集します。
「app/models/contact.rb」を手動作成(rails generateは使わない)し、編集します。
class Contact include ActiveModel::Model attr_accessor :name, :email, :content validates :name, presence: true, length: { maximum: 20 } VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :email, presence: true, length: { maximum: 30 }, format: { with: VALID_EMAIL_REGEX } validates :content, presence: true, length: { maximum: 500 } end
ビュー作成
以下の3ファイルを作成します。
app/views/contacts/index.html.erb
app/views/contacts/index.html.erb
<% provide :title, 'お問い合わせ' %> <div class="container mt-4"> <div class="row"> <div class="col-md-12 col-lg-6 offset-lg-3"> <h2><%= icon('fas', 'envelope') %> お問い合わせ</h2> <nav aria-label="パンくずリスト" class="small"> <ol class="breadcrumb"> <li class="breadcrumb-item"><%= link_to 'トップページ', root_path %></li> <li class="breadcrumb-item active" aria-current="page">お問い合わせ</li> </ol> </nav> <hr /> <%= form_with model: @contact, local: true, url: contact_confirm_path do |form| %> <% if @contact.errors.any? %> <div class="alert alert-danger" role="alert"> <h5><strong>入力内容にエラーがあります。</strong></h5> <ul> <% @contact.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <div class="form-group"> <%= form.label :name, '名前' %> <span class="badge badge-info rounded-0">必須</span> <%= form.text_field :name, id: 'name', class: 'form-control', :placeholder => '名前' %> </div> <div class="form-group"> <%= form.label :email, 'メールアドレス' %> <span class="badge badge-info rounded-0">必須</span> <small class="text-muted">例:user@example.com</small> <%= form.text_field :email, id: 'email', class: 'form-control', :placeholder => 'メールアドレス' %> </div> <div class="form-group"> <%= form.label :content, 'お問い合わせ内容' %> <span class="badge badge-info rounded-0">必須</span> <small class="text-muted">パスワードなどの機密情報を含めないでください。</small> <%= form.text_area :content, id: 'content', class: 'form-control', :placeholder => 'お問い合わせ内容', :rows => '5' %> </div> <div class="float-right"> <%= form.submit "確認", class: "btn btn-dark" %> </div> <% end %> </div> </div> </div>
app/views/confirm.html.erb
<% provide :title, 'お問い合わせ' %> <div class="container mt-4"> <div class="row"> <div class="col-md-12 col-lg-6 offset-lg-3"> <h2><%= icon('fas', 'envelope') %> お問い合わせ</h2> <nav aria-label="パンくずリスト" class="small"> <ol class="breadcrumb"> <li class="breadcrumb-item"><%= link_to 'トップページ', root_path %></li> <li class="breadcrumb-item active" aria-current="page">お問い合わせ</li> </ol> </nav> <hr /> <%= form_with model: @contact, local: true, url: contact_done_path do |form| %> <div class="form-group"> <%= form.label :name, '名前' %> <%= form.text_field :name, value: @contact.name, id: 'name', class: 'form-control-plaintext', :placeholder => '名前' %> </div> <div class="form-group"> <%= form.label :email, 'メールアドレス' %> <%= form.text_field :email, value: @contact.email, id: 'email', class: 'form-control-plaintext', :placeholder => 'メールアドレス' %> </div> <div class="form-group"> <%= form.label :content, 'お問い合わせ内容' %> <%= form.text_area :content, value: @contact.content, id: 'content', class: 'form-control-plaintext', :placeholder => 'お問い合わせ内容', :rows => '5' %> </div> <p>この内容で送信します。よろしいですか?</p> <div class="float-right"> <%= form.submit "戻る", name: 'back', class: "btn btn-dark" %> <%= form.submit "送信", class: "btn btn-dark" %> </div> <% end %> </div> </div> </div>
app/views/done.html.erb
<% provide :title, 'お問い合わせ' %> <div class="container mt-4"> <div class="row"> <div class="col-md-12 col-lg-6 offset-lg-3"> <h2><%= icon('fas', 'envelope') %> お問い合わせ</h2> <nav aria-label="パンくずリスト" class="small"> <ol class="breadcrumb"> <li class="breadcrumb-item"><%= link_to 'トップページ', root_path %></li> <li class="breadcrumb-item active" aria-current="page">お問い合わせ</li> </ol> </nav> <hr /> <p>ありがとうございます。お問い合わせ内容を送信しました。</p> </div> </div> </div>
メール送信設定
本番環境と開発環境で手順が異なります。
開発環境
開発環境
「config/environments/development.rb」に以下を追記します。
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: 'localhost', port: 1025 } config.action_mailer.raise_delivery_errors = true
本番環境
「config/environments/development.rb」に以下を追記します。
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } config.action_mailer.delivery_method = :smtp config.action_mailer.raise_delivery_errors = true config.action_mailer.smtp_settings = { :address => "smtp.gmail.com", :port => 587, :user_name => ENV['MAIL_ADDRESS'], :password => ENV['MAIL_PASSWORD'], :authentication => :plain, :enable_starttls_auto => true }
環境変数の設定
送信先メールアドレスやパスワードをソースに直書きしてしまうとセキュリティ的に問題があるので、通常は環境変数に設定しておきます。
Gemfileに以下を追加し、bundle installを実行します。
Gemfileに以下を追加し、bundle installを実行します。
gem 'dotenv-rails'
dotenv-railsを導入することで、.envに記載されている環境変数をENV['variable name']の形式で参照できるようになります。
.envを作成し以下を追加します。
「MAIL_ADDRESS」には送信先のメールアドレス(今回はGmail)、「MAIL_PASSWORD」にはGoogleのアプリパスワードを設定します。
.envを作成し以下を追加します。
「MAIL_ADDRESS」には送信先のメールアドレス(今回はGmail)、「MAIL_PASSWORD」にはGoogleのアプリパスワードを設定します。
MAIL_ADDRESS=Your mail address MAIL_PASSWORD=Your mail password
.envをGithubなどのリモートサーバーにアップロードしてしまうと、やはりセキュリティ的に問題があるので、.envをコミット対象から除外します。
.gitignoreに以下を追記します。
.gitignoreに以下を追記します。
/.env
.envをコミット対象から除外してしまうと、将来クローンしたときにどういう環境変数を設定したらいいかわからなくなってしまうので、環境変数名だけ記載したファイルを作成しておきます。
.env.sampleを作成し以下を追加します。
.env.sampleを作成し以下を追加します。
MAIL_ADDRESS= MAIL_PASSWORD=
メール送信確認
ここまで行えばメール送信ができるようになっているはずです。最後にメール送信確認を行いましょう。
開発環境
開発環境
開発環境では実際に設定したGmail宛に送信するのではなく、MailCatcherというGemが構築してくれるメールサーバー宛に送信します。
Gemfileに以下を追加し、bundle installを実行します。
Gemfileに以下を追加し、bundle installを実行します。
gem 'mailcatcher'
ターミナルで以下のコマンドを実行します。
$ mailcatcher
ブラウザで「http://localhost:1080/」にアクセスすると、MailCatcherのメールボックスが表示されます。
この状態でお問い合わせフォームからメール送信するとMailCatcherのメールボックスにメールが届きます。
この状態でお問い合わせフォームからメール送信するとMailCatcherのメールボックスにメールが届きます。
本番環境
デプロイ先がHerokuの場合、Herokuに環境変数を設定する必要があります。
ターミナルで以下を実行します。
$ heroku config:set MAIL_ADDRESS=Your mail address $ heroku config:set MAIL_PASSWORD=Your mail password
本番環境では設定したGmail宛にメールが送信されるので、Gmailのメールボックスにメールが届くが確認します。