Help us understand the problem. What is going on with this article?

【Laravel】ユーザ登録時にメール認証する(v5.7以上)

メールを使った登録認証

標準で用意されている auth の laravel の認証は、
ユーザ登録すると直ぐログインできてしまった。これではメアドが正しいか確認できない。
Laravel5.7以降には、ユーザ登録時に仮メールを送信し、それに記載されているリンクを踏むことで本登録され、
以後ログインできるようになる機能が用意されている。
users テーブルのマイグレーションには 'email_verified_at' というフィールドが追加されていると思うので、
認証系を作成して、dbの設定をし、マイグレーションしておく。

Userの変更

Illuminate\Contracts\Auth の MustVerifyEmail に別名を設定して、Illuminate\Auth の MustVerifyEmail を使うよう変更する。

/app/User.php
- use Illuminate\Contracts\Auth\MustVerifyEmail;
+ use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract;
+ use Illuminate\Auth\MustVerifyEmail;

- class User extends Authenticatable
+ class User extends Authenticatable implements MustVerifyEmailContract
 {
-    use Notifiable;
+    use MustVerifyEmail, Notifiable;

ルーターの変更

メール確認関連のルーティングを有効にする。

/routes/web.php
- Auth::routes();
+ Auth::routes(['verify' => true]);

ミドルウェアの認証を verified に変更する。

auth だと本登録しなくてもログインできてしまうので verified に変更する。

/app/Http/Controllers/HomeController.php
class HomeController extends Controller
{
    public function __construct()
    {
-        $this->middleware('auth');
+        $this->middleware('verified');

日本語化を考えないならば一旦ここで終了。

確認メッセージの日本語化

本登録していない場合に表示される画面は多言語化されている。
__() 部分の日本語訳を ja.json に追加するか、直接このファイルをいじって日本語化しておく。

/resources/view/auth/verify.blade.php
 :
    <div class="card-header">{{ __('Verify Your Email Address') }}</div>
        <div class="card-body">
            @if (session('resent'))
                <div class="alert alert-success" role="alert">
                    {{ __('A fresh verification link has been sent to your email address.') }}
                </div>
            @endif

            {{ __('Before proceeding, please check your email for a verification link.') }}
            {{ __('If you did not receive the email') }} <a href="{{ route('verification.resend') }}">{{ __('click here to request another') }}</a>
:

確認メールの日本語化

先ずは大元のメールのテンプレートを修正する。これを使わず、直接 view を参照するならこの作業は不要。
vendorのテンプレを publish して、こんな感じに修正する。

$ php artisan vendor:publish --tag=laravel-notifications
/resources/views/vendor/notifications/email.blade.php
@component('mail::message')
{{-- Greeting --}}
@if (! empty($greeting))
# {{ $greeting }}
@else
@if ($level === 'error')
# @lang('Whoops!')
@else
<b>こんにちは</b>
@endif
@endif

{{-- Intro Lines --}}
@foreach ($introLines as $line)
{{ $line }}

@endforeach

{{-- Action Button --}}
@isset($actionText)
<?php
    switch ($level) {
        case 'success':
        case 'error':
            $color = $level;
            break;
        default:
            $color = 'primary';
    }
?>
@component('mail::button', ['url' => $actionUrl, 'color' => $color])
{{ $actionText }}
@endcomponent
@endisset

{{-- Outro Lines --}}
@foreach ($outroLines as $line)
{{ $line }}

@endforeach

{{-- Salutation --}}
@if (! empty($salutation))
{{ $salutation }}
@else
{{ config('app.name') }}
@endif

{{-- Subcopy --}}
@isset($actionText)
@slot('subcopy')
@lang(
":actionText ボタンが利用できない場合は、以下のURLをコピー&ペーストしてブラウザから直接アクセスしてください。<br />\n" .
    '[:actionURL](:actionURL)',
    [
        'actionText' => $actionText,
        'actionURL' => $actionUrl,
    ]
)
@endslot
@endisset
@endcomponent

確認通知メールの日本語化

まずは通知クラスを生成して修正する。

$ php artisan make:notification CustomVerifyEmail
/app/Notifications/CustomVerifyEmail.php
+ use Illuminate\Auth\Notifications\VerifyEmail;
:
- class CustomVerifyEmail extends Notification
+ class CustomVerifyEmail extends VerifyEmail
{
    :
    public function toMail($notifiable) {
        return (new MailMessage)
            ->subject(__('Verify Your Email Address'))
            ->line(__('Please click the link below to verify your email address.'))
            ->action(__('Verify Email Address'), $this->verificationUrl($notifiable))
            ->line(__('If you did not create an account, no further action is required.'));
    }

確認通知メールを User に紐づける

/app/User.php
+ use App\Notifications\CustomVerifyEmail;

class User extends Authenticatable implements MustVerifyEmailContract
{
    :
+    public function sendEmailVerificationNotification()
+    {
+        $this->notify(new CustomVerifyEmail());
+    }

パスワードリセットメールの日本語化

まずは通知クラスを生成して修正する。

$ php artisan make:notification CustomResetPassword
/app/Notifications/CustomResetPassword.php
+ use Illuminate\Auth\Notifications\ResetPassword;
:
- class CustomResetPassword extends Notification
+ class CustomResetPassword extends ResetPassword
{
+   public $token;
:
    public function __construct($token)
    {
+       $this->token = $token;
    }
:
    public function toMail($notifiable)
    {
        return (new MailMessage)
-           ->line('The introduction to the notification.')
-           ->action('Notification Action', url('/'))
-           ->line('Thank you for using our application!');
+           ->subject(__('Reset Password'))
+           ->line(__('Click button below and reset password.'))
+           ->action(__('Reset password'), url(route('password.reset', $this->token, false)))
+           ->line(__('If you did not request a password reset, no further action is required.'));
:
    }

パスワードリセットメールを User に紐づける

/app/User.php
+ use App\Notifications\CustomResetPassword;

class User extends Authenticatable implements MustVerifyEmailContract
{
    :
+    public function sendPasswordResetNotification($token) {
+        $this->notify(new CustomResetPassword($token));
+    }

ja.json 参考

/resouces/lang/ja.json
{
    "Login":"ログイン",
    "E-Mail Address":"メールアドレス",
    "Password":"パスワード",
    "Remember Me":"ログイン状態を保存する",
    "Forgot Your Password?":"パスワードをお忘れですか ?",
    "Register":"登録",
    "Name":"お名前",
    "Confirm Password":"パスワード(確認用)",
    "Reset Password":"パスワードリセット",
    "Send Password Reset Link":"パスワードリセットリンク送信",
    "Logout":"ログアウト",

    "Verify Your Email Address":"ユーザ登録を完了してください",
    "A fresh verification link has been sent to your email address.":"新しいリンクをあなたのメールアドレスに送信しました。",
    "Before proceeding, please check your email for a verification link.":"メールに記載されているリンクをクリックして、登録手続きを完了してください。",
    "If you did not receive the email":"メールが届いていなければ、",
    "click here to request another":"こちらをクリックして再送信してください。",

    "Please click the link below to verify your email address.":"メールアドレスを確認するために下のリンクをクリックしてください。",
    "Verify Email Address":"メールアドレス確認",
    "If you did not create an account, no further action is required.":"心当たりがない場合は、本メッセージは破棄してください。",

    "Reset Password":"パスワードリセット",
    "Click button below and reset password.":"下のボタンをクリックしてパスワードを再設定してください。",
    "Reset password":"パスワードリセット",
    "If you did not request a password reset, no further action is required.":"心当たりがない場合は、本メッセージは破棄してください。"
}

メール送信エラー

メール送信の設定が正しくないと以下の様なエラーが発生する。

Swift_TransportException with message 'Expected response code 250 but got code "530", with message "530 5.7.1 Authentication required

その場合は、GMail を使うなど工夫してみてください。
例えば .env でとか

MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=あなたのGMailアドレス@gmail.com
MAIL_PASSWORD=パスワード
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=あなたのGMailアドレス@gmail.com
MAIL_FROM_NAME=名前

参考:Nekyo@Laravel関連

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした