In this article, I’ll show you how to custom email verification system in laravel 9. You can understand the concept of the laravel 9 auth verify email laravel 9 email verification tutorial step by step. I explained step by step laravel 9 auth verify email. Let’s see below the example laravel 9 authentication email verification.
Laravel old version, we are doing the email verification process manually. Still, in laravel 9, they provide a build email verification setup for newly registered users to verify their email before proceeding. You need to make some basic setup with a need to use middleware, routes, and mail configuration.
Let’s follow the below step for custom email verification.
Laravel 9 Custom Email Verification Tutorial
1. Install Laravel Project
First, open Terminal and run the following command to create a fresh laravel project:
composer create-project --prefer-dist laravel/laravel custom-email
or, if you have installed the Laravel Installer as a global composer dependency:
laravel new custom-email
2. Create a Migration Table
We will create a users_verify
table and If the email_verified_at
column exists in the user’s table, then there is no need to add it.
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class UsersVerify extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users_verify', function (Blueprint $table) {
$table->integer('user_id');
$table->string('token');
$table->timestamps();
});
// Already column exist in users table then skip this add new column
Schema::table('users', function (Blueprint $table) {
$table->boolean('email_verified_at')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users_verify');
// Already column exist in users table then skip this add new column
Schema::table('users', function (Blueprint $table) {
if (Schema::hasColumn('users', 'email_verified_at')) {
$table->dropColumn('email_verified_at');
}
});
}
}
3. Create a Model and Update Model
In this step, we need to add the email_verified_at
field on the fillable array in the User model and create a new model called UserVerify
, as like below:
app/Models/User.php
<?php
namespace AppModels;
use IlluminateContractsAuthMustVerifyEmail;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
'email_verified_at'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
app/Models/UserVerify.php
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class UserVerify extends Model
{
use HasFactory;
protected $table = "users_verify";
/**
* Write code on Method
*
* @return response()
*/
protected $fillable = [
'user_id',
'token',
];
/**
* Write code on Method
*
* @return response()
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
4. Create Routes
In this step, we need to create a custom route for email verification. So open your routes/web.php
file and add the following route.
routes/web.hp
<?php
use IlluminateSupportFacadesRoute;
use AppHttpControllersAuthAuthController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('login', [AuthController::class, 'index'])->name('login');
Route::post('post-login', [AuthController::class, 'postLogin'])->name('login.post');
Route::get('registration', [AuthController::class, 'registration'])->name('register');
Route::post('post-registration', [AuthController::class, 'postRegistration'])->name('register.post');
Route::get('logout', [AuthController::class, 'logout'])->name('logout');
/* New Added Routes */
Route::get('dashboard', [AuthController::class, 'dashboard'])->middleware(['auth', 'verify_email']);
Route::get('account/verify/{token}', [AuthController::class, 'verifyAccount'])->name('user.verify');
5. Create a Controller
In this step, we need to create AuthController. We updated the code on the postRegistration()
and verifyAccount()
methods. Let’s copy as below:
app/Http/Controllers/Auth/AuthController.php
<?php
namespace AppHttpControllersAuth;
use AppHttpControllersController;
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;
use Session;
use AppModelsUser;
use AppModelsUserVerify;
use Hash;
use IlluminateSupportStr;
use Mail;
class AuthController extends Controller
{
/**
* Write code on Method
*
* @return response()
*/
public function index()
{
return view('auth.login');
}
/**
* Write code on Method
*
* @return response()
*/
public function registration()
{
return view('auth.registration');
}
/**
* Write code on Method
*
* @return response()
*/
public function postLogin(Request $request)
{
$request->validate([
'email' => 'required',
'password' => 'required',
]);
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
return redirect()->intended('dashboard')
->withSuccess('You have Successfully loggedin');
}
return redirect("login")->withSuccess('Oppes! You have entered invalid credentials');
}
/**
* Write code on Method
*
* @return response()
*/
public function postRegistration(Request $request)
{
$request->validate([
'name' => 'required',
'email' => 'required|email|unique:users',
'password' => 'required|min:6',
]);
$data = $request->post();
$createUser = $this->create($data);
$token = Str::random(64);
UserVerify::create([
'user_id' => $createUser->id,
'token' => $token
]);
Mail::send('email.emailVerificationEmail', ['token' => $token], function($message) use($request){
$message->to($request->email);
$message->subject('Email Verification Mail');
});
return redirect("dashboard")->withSuccess('Great! You have Successfully loggedin');
}
/**
* Write code on Method
*
* @return response()
*/
public function dashboard()
{
if(Auth::check()){
return view('dashboard');
}
return redirect("login")->withSuccess('Opps! You do not have access');
}
/**
* Write code on Method
*
* @return response()
*/
public function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password'])
]);
}
/**
* Write code on Method
*
* @return response()
*/
public function logout() {
Session::flush();
Auth::logout();
return Redirect('login');
}
/**
* Write code on Method
*
* @return response()
*/
public function verifyAccount($token)
{
$verifyUser = UserVerify::where('token', $token)->first();
$message = 'Sorry your email cannot be identified.';
if(!is_null($verifyUser) ){
$user = $verifyUser->user;
if(!$user->email_verified_at) {
$verifyUser->user->email_verified_at = 1;
$verifyUser->user->save();
$message = "Your e-mail is verified. You can now login.";
} else {
$message = "Your e-mail is already verified. You can now login.";
}
}
return redirect()->route('login')->with('message', $message);
}
}
6. Create Blade File
Here, we need to create blade files for email only. So let’s create one by one file:
resources/views/emails/emailVerificationEmail.blade.php
<h1>Email Verification Mail</h1>
Please verify your email with bellow link:
<a href="{{ route('user.verify', $token) }}">Verify Email</a>
7. Create Middleware
Here, we need to create middleware for verifying whether the user email is verified. So let’s create as like below:
php artisan make:middleware VerifyEmail
app/Http/Middleware/IsVerifyEmail.php
<?php
namespace AppHttpMiddleware;
use Closure;
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;
class VerifyEmail
{
/**
* Handle an incoming request.
*
* @param IlluminateHttpRequest $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if (!Auth::user()->email_verified_at) {
auth()->logout();
return redirect()->route('login')
->with('message', 'You need to confirm your account. We have sent you an activation code, please check your email.');
}
return $next($request);
}
}
app/Http/Kernel.php
protected $routeMiddleware = [
....
'verify_email' => AppHttpMiddlewareVerifyEmail::class,
];
8. Email Configuration
In this step, we will add email configuration on the .env
file, because we will send an email to reset the password link from the controller:
.env
MAIL_DRIVER=smtp
MAIL_HOST=<YOUR SMTP HOST>
MAIL_PORT=<YOUR SMTP PORT>
MAIL_USERNAME=<YOUR SMTP USERNAME>
MAIL_PASSWORD=<YOUR SMTP PASSWORD>
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=<YOUR MAIL FROM ADDRESS>
That’s It.
Thank you for reading this article.