お問い合わせフォームの実装
利用環境
・ruby 2.7.3
・Rails 6.1.4
前提
お問い合わせフォームでメールを受信するためのメールアドレスを作成
ここではGmailを登録する前提で進めます。
Gmailアカウントの設定
・2段階認証に設定する
・アプリで利用するためのパスワードを作成
リンク先:https://myaccount.google.com/u/3/security
ActionMailerの設定
本番環境のみでの設定とします。
開発環境でのメール確認に興味がある方はこちらを参考にしてみてください。
https://github.com/fgrehm/letter_opener_web
touch config/initializers/mail.rb
if Rails.env.production?
# 自身のドメインに置き換えてください
host = "Herokuのサブドメイン.herokuapp.com"
# メール配信に失敗した場合にエラーを発生
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.default_url_options = { host: host }
ActionMailer::Base.smtp_settings = {
port: 587,
address: "smtp.gmail.com",
user_name: Rails.application.credentials.gmail[:address],
password: Rails.application.credentials.gmail[:password],
domain: host,
authentication: "plain"
}
end
サンプルメール
先ほど作成したGmailアドレスをここへ入力します。
class ApplicationMailer < ActionMailer::Base
# 送信元として表示するメールアドレスと表示名
default from: 'アプリ名 <sample@gmail.com>'
layout 'mailer'
end
お問い合わせ用のメイラーを作成します。
rails g mailer ContactMailer user_email admin_email
上記のコマンド実行によって、HTML形式とtext形式が作成されます。
今回はtext形式のビューのみ使用するのでHTML形式のビューは削除します。
rm -f app/views/contact_mailer/user_email.html.erb app/views/contact_mailer/admin_email.html.erb
お問い合わせフォームの実装
ユーザーがお問い合わせを送信したタイミングでメールを送信できるようにします。
お問い合わせ内容をデータベースに保存できるようモデル・テーブルの作成
迷惑メール対策のためにIPアドレスを保存するカラムも作成
rails g model Contact name:string email:string content:text remote_ip:inet
rails db:migrate
モデルにバリデーションを追加
class Contact < ApplicationRecord
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :name, length: { maximum: 48 }
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, length: { maximum: 256 }
validates :content, presence: true, length: { maximum: 2000 }
validates :remote_ip, presence: true
end
ユーザーと管理者に送信するよう実装
class ContactMailer < ApplicationMailer
ADMIN_EMAIL = "自分のアドレス"
def user_email(contact)
@contact = contact
@name = contact.name.presence || contact.email
subject = "【アプリ名】お問い合わせを受付いたしました"
mail(to: contact.email, subject: subject)
end
def admin_email(contact)
@contact = contact
@name = contact.name.presence || contact.email
subject = "【アプリ名】お問い合わせがありました"
mail(to: ADMIN_EMAIL, subject: subject)
end
end
ユーザーに送信されるメール内容を入力します。
<%= @name %> 様
この度は,「アプリ名」にお問い合わせいただき,誠にありがとうございます。
回答の準備が出来次第,担当者よりご連絡いたします。
今後とも「アプリ名」をよろしくお願いいたします。
=*=*=*=*=*=*=*= お問い合わせ内容 =*=*=*=*=*=*=*=
<%= @contact.content %>
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
当メールの送信アドレスは配信専用となっております。
ご連絡は「お問い合わせフォーム」よりお願いいたします。
管理者に届くメール内容
<%= @name %> 様より,「アプリ名」にお問い合わせがありました。
=*=*=*=*=*=*=*= お問い合わせ内容 =*=*=*=*=*=*=*=
【氏名】<%= @contact.name %>
【メールアドレス】<%= @contact.email %>
<%= @contact.content %>
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
お問い合わせページの作成
不要なファイルがあれば削除してください。
rails g controller contacts index create --skip-assets --skip-helper --skip-routes
touch config/locales/ja.yml app/views/contacts/_error_messages.html.erb app/views/contacts/_submit_fields.html.erb
ルートに下記を追加
resources :contacts, only: %i[index create]
class ContactsController < ApplicationController
def index
@contact = Contact.new
end
def create
@contact = Contact.new(contact_params)
if @contact.save
# ユーザーにメールを送信
ContactMailer.user_email(@contact).deliver_now
# 管理者にメールを送信
ContactMailer.admin_email(@contact).deliver_now
redirect_to root_path
else
render :index
end
end
private
# IPアドレスをパラメータに追加
def contact_params
params.require(:contact)
.permit(:name, :email, :content)
.merge(remote_ip: request.remote_ip)
end
end
ビューはとりあえず最低限表示される程度に実装しています。
<h1>お問い合わせ</h1>
<%= form_with model: @contact, local: true do |form| %>
<%= render "error_messages", form: form %>
<%= render "submit_fields", form: form %>
<%= form.submit "送信" %>
<% end %>
<% if @contact.errors.any? %>
<div id="error_explanation">
<h2><%= @contact.errors.count %> つのエラーがあります</h2>
<ul>
<% @contact.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= form.label :name %> (任意)
<%= form.text_field :name %>
</div>
<div>
<%= form.label :email %> (必須)
<%= form.email_field :email, required: true, pattern: "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]+$" %>
</div>
<div>
<%= form.label :content %> (必須)
<%= form.text_area :content, required: true %>
</div>
最後に
とりあえず最低限こんな感じで動きました。
お問い合わせを送信する前の確認画面などを実装するといいかもしれませんね。
いやー長かった・・・。
もしおかしな点がありましたらご指摘お願いします。