Berikut adalah tutorial lengkap untuk Email Verification dan Custom Password Reset di Laravel. Namun sebelum ke tutorlal ini, ada baiknya mengikuti tutorial sebelumnya 

Persiapan Awal

- Laravel versi terbaru (Laravel 10) harus sudah diinstal.

- Database sudah dikonfigurasi di .env dan tabel sudah dimigrasi.

- Laravel Breeze untuk scaffolding autentikasi juga disarankan. Jika belum, jalankan:

composer require laravel/breeze --dev 
php artisan breeze:install 
php artisan migrate

Langkah 1: Mengaktifkan Verifikasi Email

1.1 Mengaktifkan Middleware Verifikasi Email

Untuk data user, kita akan pakai data sebelumnya pada tutorial Membuat Multi-Authentication System di Laravel Login Admin dan User. Silahkan mengikuti tutorial sebelumnya untuk detailnya

Tambahkan middleware verified pada route yang ingin dilindungi. Buka routes/web.php:

use Illuminate\Support\Facades\Route;

Route::middleware(['auth', 'verified','role:user'])->group(function () {
    Route::get('/user/dashboard', function () {
        return view('user.dashboard');
    })->name('user.dashboard');
});

Hal ini akan melakukan verifikasi setiap melakukan login yang dikirim ke email.  

1.2 Mengaktifkan Fitur Verifikasi di Model User

Di file app/Models/User.php, implementasikan MustVerifyEmail:

use Illuminate\Contracts\Auth\MustVerifyEmail;

class User extends Authenticatable implements MustVerifyEmail
{
    // Konfigurasi verifikasi email siap digunakan
}

1.3 Menyesuaikan View Verifikasi Email

Jika ingin mengubah tampilan, buat resources/views/auth/verify-email.blade.php:

@extends('layouts.app')

@section('content')
<div>
    <h1>Email Verification</h1>
    <p>Check your email to verify your account.</p>

    @if (session('status') == 'verification-link-sent')
        <p>A new verification link has been sent to your email address.</p>
    @endif

    <form method="POST" action="{{ route('verification.send') }}">
        @csrf
        <button type="submit">Resend Verification Email</button>
    </form>
</div>
@endsection

1.4 Pengujian Verifikasi Email

Setelah pendaftaran, pengguna akan diminta verifikasi email dan diarahkan ke halaman tersebut. Verifikasi akun dengan mengklik link pada email. 

Kita akan menggunakan https://mailtrap.io untuk konfigurasi SMTP mailer nya. jika belum registrasi, silahkan registrasi dan login ke akun mailtrap. Setelah login, buka menu INBOXES lalu ada SMTP untuk kita lakukan testing seperti berikut:

Setelah dapat, edit file .env di laravel menjadi sebagai berikut:

MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=304a002842dcf4
MAIL_PASSWORD=********6a30

Sesuaikan config SMTP dengan config SMTP di mailtrap anda. Setelah itu kita akan testing login menggunakan URL berikut:

http://localhost:8000/login

Setelah itu akan muncul verifikasi sebagai sebagai berikut:

Cek di inbox mailtrap, dan akan menghasilkan seperti berikut:

Langkah 2: Mengatur Custom Password Reset

2.1 Membuat Notifikasi Reset Password

Buka file app/Notifications/ResetPasswordNotification.php atau jika belum ada, bisa dibuat dengan:

php artisan make:notification ResetPasswordNotification

Edit ResetPasswordNotification.php untuk menyesuaikan isi email:

namespace App\Notifications;

use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;

class ResetPasswordNotification extends Notification
{
    public $token;

    public function __construct($token)
    {
        $this->token = $token;
    }

    public function via(object $notifiable): array
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->subject('Reset Your Password')
                    ->line('You are receiving this email because we received a password reset request for your account.')
                    ->action('Reset Password', url(route('password.reset', $this->token, false)))
                    ->line('If you did not request a password reset, no further action is required.');
    }
}

2.2 Update Model User untuk menggunakan Notifikasi

Di app/Models/User.php, tambahkan method sendPasswordResetNotification:

use App\Notifications\ResetPasswordNotification;

public function sendPasswordResetNotification($token)
{
    $this->notify(new ResetPasswordNotification($token));
}

2.3 Membuat Route dan View untuk Password Reset

Tambahkan route untuk mengelola password reset di routes/web.php:

use Illuminate\Support\Facades\Password;
use Illuminate\Http\Request;

Route::get('/forgot-password', function () {
    return view('auth.forgot-password');
})->middleware('guest')->name('password.request');

Route::post('/forgot-password', function (Request $request) {
    $request->validate(['email' => 'required|email']);
    
    $status = Password::sendResetLink(
        $request->only('email')
    );

    return $status === Password::RESET_LINK_SENT
                ? back()->with(['status' => __($status)])
                : back()->withErrors(['email' => __($status)]);
})->middleware('guest')->name('password.email');

Route::get('/reset-password/{token}', function ($token) {
    return view('auth.reset-password', ['token' => $token]);
})->middleware('guest')->name('password.reset');

Route::post('/reset-password', function (Request $request) {
    $request->validate([
        'token' => 'required',
        'email' => 'required|email',
        'password' => 'required|min:8|confirmed',
    ]);

    $status = Password::reset(
        $request->only('email', 'password', 'password_confirmation', 'token'),
        function ($user, $password) {
            $user->forceFill([
                'password' => bcrypt($password)
            ])->save();
        }
    );

    return $status === Password::PASSWORD_RESET
                ? redirect()->route('login')->with('status', __($status))
                : back()->withErrors(['email' => [__($status)]]);
})->middleware('guest')->name('password.update');

2.4 Membuat View untuk Password Reset

Forgot Password View (resources/views/auth/forgot-password.blade.php)

@extends('layout')

@section('content')
<h1>Forgot Password</h1>
<form action="{{ route('password.email') }}" method="POST">
    @csrf
    <div class="mb-3">
        <label for="email" class="form-label">Email:</label>
        <input type="email" class="form-control" id="email" name="email" required>
        <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
        <button type="submit" class="btn btn-primary mt-50">Send Password Reset Link</button>
    </div>
</form>
@endsection

Reset Password View (resources/views/auth/reset-password.blade.php)

@extends('layout')

@section('content')
<h1>Reset Password</h1>
<form action="{{ route('password.update') }}" method="POST">
    @csrf
    <div class="mb-3">
        <input type="hidden" name="token" value="{{ $request->route('token') }}">
        <label for="email">Email:</label>
        <input type="email" id="email" class="form-control" name="email" required>
    </div>
    <div class="mb-3">
        <label for="password">New Password:</label>
        <input type="password" id="password" class="form-control" name="password" required>
    </div>
    <div class="mb-3">
        <label for="password_confirmation">Confirm Password:</label>
        <input type="password" id="password_confirmation" class="form-control" name="password_confirmation" required>
    </div>
    <button type="submit" class="btn btn-primary">Reset Password</button>
</form>
@endsection

Silahkan testing dengan akses URL login kemudian klik Forgot your password? hasilnya seperti berikut:

​​​​​​Jika berhasil, maka akan tampil seperti berikut di inboxes mailtrap:

Setelah klik Reset Password, akan diarahkan ke halaman change password berikut: