Rails7 Gmailでのメール認証機能の追加実装（メモ書き）

作成日　　　　　　　 : 2024年11月16日 

最終編集日　　　　　 : 2024年11月17日 

---

# rails7 devise を使用したメール認証機能の導入
- Gmailでのメール認証機能の追加実装
    ※ローカル環境での導入試験
    
    - 前提条件：deviseを事前に設定済みである状態
        `rails g devise:install`
        `rails g devise user`
        `rails db:migrate` 実行済み

    - 下記の２パターンに共通して、環境変数の設定が必要
        - Gmailアカウントのパスワードを環境変数に設定

        ```bash
        # 環境変数の内容確認
        cat ~/.zshrc
        # 環境変数にパスワードの追加
        echo export GMAIL_PASSWORD="Gmailのパスワード" >> ~/.zshrc
        # 設定の反映
        source ~/.zshrc
        # 設定の確認
        echo $GMAIL_PASSWORD
        
        # 直接編集する場合
        vim ~/.zshrc
        i # を押してインサートモードに
        # 末尾に下記を追記
        export GMAIL_PASSWORD=Gmailのパスワード
        esc # でインサートモードを閉じる
        :wq # 保存して終了
        Enter # 確定
        # 設定の確認
        echo $GMAIL_PASSWORD
        ```
        
    - Confirmableオプションの追加（通常の場合）
        
        本来、deviseの実装時に最初に追加しておくべき設定。
        
        Confirmableオプションを追加する場合、通常は、`rails g devise user` 実行時に作成されるマイグレーションファイルのコメントアウトを`rails db:migrate` を実行する前に解除する。
        
        - デフォルトで生成されるマイグレーションファイルの設定
            
            ```ruby
            # frozen_string_literal: true
            
            class DeviseCreateUsers < ActiveRecord::Migration[7.0]
              def change
                create_table :users do |t|
                  ## Database authenticatable
                  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
            
            ```
            
        
        下記コードをコメントインする。
        
        ```ruby
              ## Confirmable
              # t.string   :confirmation_token
              # t.datetime :confirmed_at
              # t.datetime :confirmation_sent_at
              # t.string   :unconfirmed_email # Only if using reconfirmable
        ```
        
    - Confirmableオプションの追加（後から追加する場合）
        1. Userモデルの修正
            - `app/models/user.rb`ファイルに`confirmable` の追加
            
            ```ruby
            class User < ApplicationRecord
              # Include default devise modules. Others available are:
              # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
              devise :database_authenticatable, :registerable,
                     :recoverable, :rememberable, :validatable, :confirmable
            end
            ```
            
        2. マイグレーションファイルを作成
            - ターミナルからマイグレーションファイルの作成
            
            ```bash
            # アプリケーションのルートディレクトリで実行
            cd アプリケーション名
            rails g migration AddConfirmableToDevise
            ```
            
            - 生成されるマイグレーションファイルを変更
            
            ```ruby
            class AddConfirmableToDevise < ActiveRecord::Migration[7.0]
              def up
                add_column :users, :confirmation_token, :string
                add_column :users, :confirmed_at, :datetime
                add_column :users, :confirmation_sent_at, :datetime
                add_column :users, :unconfirmed_email, :string
                add_index :users, :confirmation_token, unique: true
              
                # 既存のユーザーを確認済みとしてマークする
                User.update_all confirmed_at: DateTime.now
                # 上記コードが無いと、既に登録しているuserが存在する場合、
                # メール認証のトークンが無いのでエラーが発生する。
              end
              
              def down
                remove_columns :users, :confirmation_token, :confirmed_at, :confirmation_sent_at
                remove_columns :users, :unconfirmed_email
              end
            end
            ```
            
            - `rails db:migrate` を実行
        3. SMTPの設定
            - `config/environments/development.rb`ファイルの編集
            
            ```ruby
            require "active_support/core_ext/integer/time"
            
            Rails.application.configure do
            
              # 省略
            
              # Don't care if the mailer can't send.
              config.action_mailer.raise_delivery_errors = true # false → true に変更
            
              config.action_mailer.perform_caching = false
            
              # 追加
              config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
              config.action_mailer.delivery_method = :smtp
              config.action_mailer.smtp_settings = {
                address: 'smtp.gmail.com',       # SMTPサーバーのアドレス
                port: 587,                       # 使用するポート番号
                domain: 'gmail.com',             # ドメイン名
                user_name: 'メールアドレス',       # Gmailアカウントのユーザー名
                password: ENV['GMAIL_PASSWORD'], # 環境変数から取得するGmailアカウントのパスワード
                authentication: 'plain',         # 認証方式
                enable_starttls_auto: true       # STARTTLSを有効にする
              }
            
              # 省略
              
            end
            ```
            
        4. 未確認のユーザーがログイン出来る期間の設定
            - `config/initializers/devise.rb`ファイルの編集
            
            ```ruby
            # frozen_string_literal: true
            
            # 省略
            
            Devise.setup do |config|
            
              # 省略
              
              # confirming their account.
            
              # コメントアウトの解除
              # 未確認のユーザーがログインできる期間を設定する。
              # 0.daysは、メール確認前のログインを完全に禁止
              config.allow_unconfirmed_access_for = 0.days
            
              # 省略
            
            end
            ```
            
    

---