Sending emails using laravel mail queue reduces the response time of application. Suppose you need to send multiple emails, you need to wait for some time for a server to respond. Some peoples using a job class to send mail using a queue. But it’s the not correct way. Laravel provides queue API, especially for mails.
I’m using mailtrap for receiving mail. If you don’t know how to use mailtrap for sending mail, please click here.
Post Contents
# Requirements
- Laravel installed in your system. Click Here to know how to install Laravel Framework.
- Mailtrap account. You can create it here. Of course, you can use your SMTP credentials too.
Configure your smtp settings in .env file situated in root folder.
/* .env */
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your-username
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=null
Let’s setup simple mail functionality before understanding queue.
Update welcome.blade.php to create simple email input.
/* resources > views > welcome.blade.php */
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Laravel Mail With Queue</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container my-5 align-center">
@if(session()->has('msg'))
<div class="alert alert-info">
{{ session()->get('msg') }}
</div>
@endif
<form action="{{ route('send.email') }}" method="post">
{{ csrf_field() }}
<div class="form-group">
<label>Email Address</label>
<input type="email" class="form-control" name="email" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Send</button>
</div>
</form>
</div>
</body>
</html>
Create a mailable class with the following command and replace the following code.
php artisan make:mail SignupMail
/* app > Mail > SignupMail.php */
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class SignupMail extends Mailable
{
use Queueable, SerializesModels;
protected $email;
public function __construct($email)
{
$this->email = $email;
}
public function build()
{
return $this->from("admin@example.com")->subject('Signup Mail')->view('emails.signup')->with(['email' => $this->email]);
}
}
For email body, create email page template in recources > views > emails > signup.blade.php
/* recources > views > emails > signup.blade.php */
<p>Welcome, <b>{{ $email }}</b></p>
Update routes and controller to submit input to send an email.
/* routes > web.php */
<?php
Route::get('/', 'WelcomeController@index');
Route::post('send/email', 'WelcomeController@sendEmail')->name('send.email');
/* app > Http > Controllers > WelcomeController.php */
<?php
namespace App\Http\Controllers;
use App\Mail\SignupMail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class WelcomeController extends Controller
{
public function index()
{
return view('welcome');
}
public function sendEmail(Request $request)
{
Mail::to($request->email)->send(new SignupMail($request->email));
return redirect()->back()->with(['msg' => 'Email sent successfully']);
}
}
Start PHP development server with the following command.
php artisan serve
This will start server at locahost:8000.
Try sending some mails and check the response time.
# Mail With Queue
Open .env, find QUEUE_CONNECTION or QUEUE_DRIVER according to laravel version.
Replace queue driver to sync to database. Database driver need jobs table to handle queues.
Create and migrate jobs table with following commands.
php artisan queue:table
php artisan migrate
Now, reopen WelcomeController.php and update sendEmail function as below.
public function sendEmail(Request $request)
{
Mail::to($request->email)->queue(new SignupMail($request->email));
return redirect()->back()->with(['msg' => 'Email sent successfully']);
}
As you can see I just changed one function send to queue.
Start queue worker with the following command and keep it running.
php artisan queue:listen
Thats it! Try to send mail again, and you will see all emails now using queue and will be sent in background, and you will get instant response.