【Rails7】Devise + SendGrid を利用し、Heroku(本番環境)でメール認証を使えるようにする

SendGridというメールサーバー(SMTPサーバー)を利用し、Herokuにデプロイしたアプリにメール認証機能を実装するまでの手順について書き残そうと思います。

昨年ごろからSendGridのセキュリティ強化により、なかなかアカウントに登録できなかったり、登録できてもメールが送れなかったりと大変でしたが、なんとかアカウント登録し、本番環境でもメール認証機能を使えるようになりました。丸3日、、、長かったw

あわせて読みたい
【Rails7】開発環境、本番環境でメール送信できるようにする(SendGrid, Gmail) Railsで作ったアプリからメールを送信したい場合、外部のメールサーバーを利用してメールを送ることになります。 今回は、Railsのアプリ制作でよく取り上げられているメ...

【追記】Rails7のTurboに対応した実装手順についてまとめました↓

あわせて読みたい
【Rails7】Deviseを導入する方法(Turbo対応済み, メールサーバー設定込み) 【重要】Rails7でDeviseを導入される方へ2023年2月17日に最新版Devise(v4.9.0)がリリースされ、Rails7のTurboに対応するようになりました。それに伴い、当記事で紹介...
目次

開発環境

  • Ruby 3.1.2
  • Ruby on Rails 7.0.3
  • Devise 4.8.1
  • M1 Macbook Air 2020
  • mac OS Monterey (ver. 12.4)
  • ターミナル bash (Rosetta 2 使用)

Devise のインストールと各種設定を済ませておく

Deviseのインストールや設定方法についてはこちらの記事を参考にしました。

【Rails】 deviseの使い方とは?ログイン認証機能を実装しよう

以下、僕がDeviseをインストール、各種設定するまでの流れを書き残しておきます。

まずはGemfileに下記のように記述します。

gem 'devise'
# ↓パスワードなどを環境変数するgem
gem 'dotenv-rails'

dotenv-railsはメールアドレスやパスワードなど、gitに載せたくない情報を環境変数化するためのgemです。

$ bundle installを実行後、Devise本体をインストールします。

$ rails g devise:install

Deviseのインストールに成功したら、以下のようなメッセージが表示されます。

===============================================================================

Depending on your application's configuration some manual setup may be required:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

     * Required for all applications. *

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"
     
     * Not required for API-only Applications *

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

     * Not required for API-only Applications *

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views
       
     * Not required *

===============================================================================

必要に応じて各項目の設定、追加等をしていきます。

1. 新規登録などで認証メールを送った際、メールの文中にある認証リンクのURLを設定

開発環境でメール認証を行う場合は、

config/environments/development.rb内に下記のように記述します。

config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

また、本番環境でメール認証を行う場合は、

config/environments/production.rb内に下記のように記述します。

config.action_mailer.default_url_options = { host: 'https://Herokuのアプリ名.herokuapp.com' }

2. ルートを設定する

deviseでは会員登録完了後などにルートに飛ぶ設定になっているため、

あらかじめconfig/routes.rbにルートを設定しておく必要があります。

root "home#index"

3. フラッシュメッセージ用のタグをapplication.html.erbに埋め込む。

<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

4. deviseのカスタマイズ用のビューファイル作成

$ rails g devise:views

Deviseのビューをカスタマイズする時は、app/views/devise以下のファイルを編集する。

Userモデルの作成

以下のコマンドを実行し、Userモデルを作成します。

$ rails g devise user

Deviseはデフォルトでは:usernameカラムの設定がないため、必要であれば付け加えておきます。

メール認証を導入する場合は、マイグレーションファイルの## Confirmable の部分をコメントアウトしておきます。

# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :username
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable ←コメントアウトを解除する(メール認証用のカラム)
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

Userモデルに:confirmableを追記します。

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable
end

最後に、以下のコマンドを実行し、データベースを作成します。

$ rails db:migrate

このコマンドよく忘れるので注意!(自分への注意書きですw)

メール送信用サーバー(開発環境)の設定

config/environments/development.rbに下記のように記述します。

  config.action_mailer.perform_caching = false
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.delivery_method = :smtp
  # SendGrid の場合
  config.action_mailer.smtp_settings = {
    :address => 'smtp.sendgrid.net',
    :port => 587,
    :domain => 'localhost',
    :user_name => 'apikey',
    :password => ENV['SENDGRID_API_KEY'],
    :authentication => :plain,
    :enable_starttls_auto => true
  }

こちらはSendGrid用の設定です。

Gmailを送信用サーバーにする場合は下記のように記述します。

  # Gmail の場合
  config.action_mailer.smtp_settings = {
  :enable_starttls_auto => true,
  :address => "smtp.gmail.com",

  :port => 587,
  :domain => 'smtp.gmail.com',
  :user_name => ENV['GMAIL_ADDRESS'],
  :password => ENV['GMAIL_PASSWORD'],
  :authentication => 'login'
}

Gmailのパスワードについては、2段階認証を設定している場合はアプリパスワードというものを取得し、それを入力する必要があります(2段階認証推奨)。

2 段階認証プロセスを有効にする | Googleアカウントヘルプ

アプリパスワードの取得方法はこちらの記事が参考になります。

パスワードやAPIキーなどgitにアップしたくない情報は.envファイルを作成し、環境変数化しておきます。

# Gmail
GMAIL_ADDRESS = "Gmailのメールアドレス"
GMAIL_PASSWORD = "Gmailのパスワード"

# 送信元のメールアドレス
SENDER_ADDRESS = "送信元のメールアドレス"

# SendGrid
SENDGRID_API_KEY = "SendGridのAPIキー"

ただ、このままだと$ git pushした時にコードがそのままアップされてしまうので、それを防ぐために.gitignoreファイルに/.envを追記します。

/public/assets

# Ignore master key for decrypting credentials and more.
/config/master.key

# ↓最下部に追記
/.env

開発環境用の設定はこれで完了です。

メール送信用サーバー(本番環境)の設定

本番環境の設定は、config/environments/production.rb内に下記のように記述します。

  config.action_mailer.default_url_options = { host: 'https://Herokuのアプリ名.herokuapp.com' }
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.perform_deliveries = true
  config.action_mailer.default :charset => "utf-8"
  config.action_mailer.smtp_settings = {
    :address => 'smtp.sendgrid.net',
    :port => 587,
    :domain => 'heroku.com',
    :user_name => 'apikey',
    :password => ENV['SENDGRID_API_KEY'],
    :authentication => :plain,
    :enable_starttls_auto => true
  }

ここで、:passwordの設定はHerokuに環境変数として設定します。

設定方法は次の項目で説明します。

メールの差出人(送信元)情報の設定

送信元となるメールアドレスを入力します。

デフォルトでは “from@example.com” となっているので、ここに送信元にしたいメールアドレスを入力します。

app/mailers/application_mailer.rb内には以下のように環境変数に設定したメールアドレスを記述します。

class ApplicationMailer < ActionMailer::Base
  default from: ENV['SENDER_ADDRESS']
  layout "mailer"
end

また、同じくdevise側の設定にも送信元メールアドレスを明記する必要があります。

Devise.setup do |config|
  ・・・
  # config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
  # ↓以下のように変更
  config.mailer_sender = ENV['SENDER_ADDRESS']
 ・・・
end

(アプリケーション側で設定した送信元メールアドレスは、SendGrid側でも登録・認証しておく必要があります。詳しくは後ほど)

また、本番環境でも環境変数の値が適用されるよう、Heroku側で環境変数の設定を行います。

HerokuのSettingタブ > Config Varsへ進み、以下のように環境変数のキーと値を入力します。

SendGridのAPIキーはSendGridであらかじめ作成しておきます。

まずはSendGridにアクセスしてアカウント登録する必要があります。(アカウント登録についてはこちら

また、送信元メールアドレスについても、Heroku側だけでなくSendGrid側でもあらかじめ登録しておく必要があります。(詳しくはこちら

Deviseを日本語化する

config/application.rbに下記のコードを記述。

config.i18n.default_locale = :ja

ついでにタイムゾーンも "Tokyo" に設定しておきます(デフォルトではUSになっている)。

# 変更前
config.time_zone = "Central Time (US & Canada)"
# 変更後
config.time_zone = "Tokyo"

次にconfig/locales内にdevise.ja.ymlおよびja.ymlファイルを作成します。

作成したファイルに翻訳データをコピーします。

devise.ja.ymlの翻訳ファイルはこちらから、ja.ymlの翻訳ファイルはこちらからそれぞれコピーさせていただきました。

(作成していただいた方には感謝です)

Heroku経由でSendGridを使おうとするとアカウント凍結される

「Heroku SendGrid」と検索すると、Heroku経由でSendGridにアカウント登録し、その後 APIキーを取得して、、

という記事が多く見られるが、ここ最近SendGridのセキュリティが一段と厳しくなったことに伴い、

Heroku経由でSendGridを使おうとすると一瞬でアカウント凍結される(可能性が高い)。

【重要】APIキー認証および二要素認証が必須に変更されます | SendGridサポートチーム

Heroku Add-onsのSendGridトラブルシューティング

実際に僕もHeroku経由でSendGridに登録しようとしてみたのですが、何回やっても接続拒否(アカウント凍結)されてしまいます。

アカウント凍結されたらサポートに問い合わせてアカウントを有効化してもらう必要があるのですが、

Heroku経由の問題についてはどうやら日本ではサポート対象外とのこと。

Heroku経由で作成したアカウントが凍結されました。どうすればよいですか? | SendGridサポートチーム

なので、米国のSendGrid社に直接問い合わせなければなりません(もちろん英語で)。

英語での問い合わせに関しては下記の記事がとても参考になります。

Heroku Add-onのSendGridにログインできないトラブル

ちなみに、僕はHeroku経由でSendGridに登録するのを諦め、下記の方法で進めたらうまく登録できました。

SendGrid はHeroku経由ではなく、公式ページで直接登録する

SendGridにアクセスし、「Start for free」ボタンからアカウント登録を進めます。

アカウント登録の手順については下記記事がとても参考になります。

Heroku で SENDGRID を使って メール送信できるようにする

メールの差出人(送信元)情報をSendGridに登録する

SendGridを利用する場合、メールの差出人情報(メールアドレス、名前、住所など)をあらかじめ登録しておく必要があります。

登録していない場合、メールの送信ができません。

差出人情報の登録は下記の公式ドキュメントがとても参考になるので、こちらを参考に進めてみてください。(画像付き、日本語説明でとてもわかりやすかった)

差出人情報の作成 | SendGrid公式ドキュメント

以上の手順を実行すれば本番環境(Heroku)でSendGridを使ったメール認証が問題なく行えるはずです。

SendGridはセキュリティにとてもうるさい厳しいので、例えばアカウント登録後に(コードの入力ミスなどで)メールの送信に失敗しまくるとサポート側から警告メールが来ることがあります。警告メールが来たら慌てず落ち着いて利用目的等を伝えれば垢BANされることはないと思いますが(僕も一度警告メールが来ましたw)、放置すると垢BANされるのでご注意ください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

愛知の34歳。無職で暇になり始めたプログラミング(Ruby on Rails)の忘備録をまとめたブログです。最近は別にやりたいことができたのでプログラミングほぼやっていません。気が向いたらまた再開するかも。僕の日常はメインブログの方で更新しています。

コメント

コメントする

目次