開発環境
- PHP 8.3.22
- Laravel Framework 12.23.1
- Docker
メールアドレス認証の実装方法
Breeze はすでに導入済みと仮定して進めます。
app/Models/User.php
の変更
// 以下を削除
- use Illuminate\Contracts\Auth\MustVerifyEmail;
// 以下を追加・編集
+ use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract;
+ use Illuminate\Auth\MustVerifyEmail;
class User extends Authenticatable implements MustVerifyEmailContract
{
use HasFactory, MustVerifyEmail, Notifiable;
}
ルーターを編集
middlewareにverifiedを追加することで、メールアドレスを認証していないユーザーはアクセス出来なくなる。
※authはログインの有無
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/profile', [ProfileController::class, 'show'])->name('profile.show');
Route::get('/profile/edit', [ProfileController::class, 'edit'])->name('profile.edit');
Route::post('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
メール認証の動作確認とローカル環境でのメール受信方法
これでメールアドレスを認証しないと、任意の機能に制限がかかるように設定することが出来ました。
次はそれが実際にきちんと動作しているかを確認する方法を説明します。
アクセスに制限がかかることは、設定したページに行けばすぐに確認できます。
次はメールアドレスを認証して、正常にそのページへアクセス出来るようになるか確認していきます。
しかしここで一つ問題があります。
それは、ローカル環境では実際に登録したメールアドレスに認証メールは届かないという点です。
Mailpit を使ったローカルメール確認
今回は「Mailpit」という開発環境用のメールキャッチャーツールを使用します。
これにより、アプリケーションから送信されたメールを外部に送信せず、Web UIで内容を確認できます。
docker-compose.yml
に Mailpit サービスを追加
mailpit:
image: 'axllent/mailpit:latest'
ports:
- '${FORWARD_MAILPIT_PORT:-1025}:1025'
- '${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025'
networks:
- sail
.env
を編集
MAIL_MAILER=smtp
MAIL_SCHEME=null
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
Mailpit による認証メールの確認
これにより http://localhost:8025 で Mailpit を使用することができるようになります。
ユーザー登録をするか、認証メール再送ページ(例:http://localhost/auth/verify-email)で再送すると、Mailpit 上で以下のような認証メールが確認できます。
「Verify Email Address」ボタンを押して、メールアドレスが認証されたか確認してください。
認証前にアクセス出来なかったページへアクセス出来たら、正常に動作しています。
認証メールの日本語化
認証メールは日本語化することも可能です。
私は以下の記事を参考にしました。
認証メールのカスタマイズ方法
以下のコマンドで CustomVerifyEmail.php
verify_email.blade.php
を作成します。
php artisan make:notification CustomVerifyEmail --markdown=emails.verify_email
verify_email.blade.php(例)
マークダウン形式で自由にメール内容を指定できます。
@component('mail::message')
# ご登録ありがとうございます
この度はご登録いただき、ありがとうございます。
メールアドレスを確認するため、下記のボタンをクリックしてください。
@component('mail::button', ['url' => $verify_url])
メールアドレス確認
@endcomponent
もしこのサービスへのアカウント登録に心当たりがない場合は、本メールは破棄してください。
---
<br/>
※「メールアドレス確認」ボタンがクリックできない場合、下記URLをコピーしてブラウザに貼り付けてください。
[{{ $verify_url }}]({{ $verify_url }})
<br/>
※このメールは送信専用アドレスから送信されています。ご返信いただいても対応できませんのでご了承ください。
<br/>
---
{{ config('app.name') }}
@endcomponent
CustomVerifyEmail.php
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Lang;
use Illuminate\Auth\Notifications\VerifyEmail;
class CustomVerifyEmail extends VerifyEmail
{
use Queueable;
/**
* Create a new notification instance.
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* @return array<int, string>
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*/
public function toMail($notifiable)
{
$verificationUrl = app(VerifyEmail::class)->verificationUrl($notifiable);
return (new MailMessage)
->subject(Lang::get('Verify Email Address'))
->markdown('emails.verify_email', [
'verify_url' => $verificationUrl
]);
}
/**
* Get the array representation of the notification.
*
* @return array<string, mixed>
*/
public function toArray(object $notifiable): array
{
return [
//
];
}
}
User.php に通知メソッドを追加
メールアドレスの確認メールを送信する際に、作成した CustomVerifyEmail
クラスを使用するようにします。
app/Models/User.php
にて sendEmailVerificationNotification
メソッドをオーバーライドします。
// 以下を追加
use App\Notifications\CustomVerifyEmail;
class User extends Authenticatable implements MustVerifyEmailContract
{
// 以下を追加
public function sendEmailVerificationNotification()
{
$this->notify(new CustomVerifyEmail());
}
}