メールを使った登録認証
標準で用意されている auth の laravel の認証は、
ユーザ登録すると直ぐログインできてしまった。これではメアドが正しいか確認できない。
Laravel5.7以降には、ユーザ登録時に仮メールを送信し、それに記載されているリンクを踏むことで本登録され、
以後ログインできるようになる機能が用意されている。
users テーブルのマイグレーションには 'email_verified_at' というフィールドが追加されていると思うので、
認証系を作成して、dbの設定をし、マイグレーションしておく。
Userの変更
Illuminate\Contracts\Auth の MustVerifyEmail に別名を設定して、Illuminate\Auth の MustVerifyEmail を使うよう変更する。
- 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;
ルーターの変更
メール確認関連のルーティングを有効にする。
- Auth::routes();
+ Auth::routes(['verify' => true]);
ミドルウェアの認証を verified に変更する。
auth だと本登録しなくてもログインできてしまうので verified に変更する。
class HomeController extends Controller
{
public function __construct()
{
- $this->middleware('auth');
+ $this->middleware('verified');
日本語化を考えないならば一旦ここで終了。
確認メッセージの日本語化
本登録していない場合に表示される画面は多言語化されている。
__() 部分の日本語訳を ja.json に追加するか、直接このファイルをいじって日本語化しておく。
:
<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
@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
+ 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 に紐づける
+ use App\Notifications\CustomVerifyEmail;
class User extends Authenticatable implements MustVerifyEmailContract
{
:
+ public function sendEmailVerificationNotification()
+ {
+ $this->notify(new CustomVerifyEmail());
+ }
パスワードリセットメールの日本語化
まずは通知クラスを生成して修正する。
$ php artisan make:notification CustomResetPassword
+ 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 に紐づける
+ use App\Notifications\CustomResetPassword;
class User extends Authenticatable implements MustVerifyEmailContract
{
:
+ public function sendPasswordResetNotification($token) {
+ $this->notify(new CustomResetPassword($token));
+ }
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=名前