Send an email through Laravel
1. Configure Mail Settings
To send an email in Laravel, start by configuring the mail settings in your .env file. Here, I’m using Mailtrap to test email delivery.
Create an account on Mailtrap, then navigate to the Inbox section and click Add Inbox to create a new one. Once the inbox is created, you’ll be directed to the Integration page, where you can find your username and password.
Update your .env file as follows:
MAIL_DRIVER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=tls
2. Create a Mailable Class
Run the following artisan command:
php artisan make:mail ProjectCompleteAdminMail
This creates a file like app/Mail/ProjectCompleteAdminMail.php
.
3. Define Email Content
Open app/Mail/ProjectCompleteAdminMail.php
file :
<?php namespace App\Http\Controllers; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Queue\ShouldQueue; use App\Models\User; class ProjectCompleteAdminMail extends Mailable { use Queueable, SerializesModels; public $userName; public $projectName; public $projectLink; / * Create a new message instance. * * @return void */ public function __construct($mailInfo) { $data = (object) $mailInfo; $this->userName = $data->userName; $this->projectName = $data->projectName; $this->projectLink = config('app.url').sprintf('/projects/%d', $data->project_id); } / * Build the message. * * @return $this */ public function build() { return $this->from('your_email@gmail.com') ->subject(sprintf('Project Released - %s', $this->projectName)) ->view('emails.project-released') ->with([ 'userName' => $this->userName, 'projectName' => $this->projectName, 'projectLink' => $this->projectLink ]); } }
sprintf() function: Replace the percent (%) sign by a variable passed as an argument
– The public variables ($userName
, $projectName
, $projectLink
) are passed to the Blade file using the with()
method.
– Inside the Blade file, you can access them directly using {{ $variable_name }}
.
As a result, when you receive the email, the subject will be properly formatted. like this:
Project Released- Mail Marvel
“Marvel” is the project name
4. Create an Email View
Create a Blade view in resources/views/emails/project-released.blade.php
:
<!DOCTYPE html> <html> <head> <title>Project Released</title> </head> <body> <h1>Hello, {{ $userName }}</h1> <p>User project "<strong>{{ $projectName }}</strong>" has been released.</p> <p>You can check it here: <a href="{{ $projectLink }}">{{ $projectLink }}</a></p> </body> </html>
5. Send an Email from the Controller
In your controller (app/Http/Controllers/MailController.php
), send the email:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Mail\ProjectCompleteAdminMail; use Mail; use Log; class MailController extends Controller { public function sendEmail() { $project_id = 123; // Example project ID $data = [ 'userName' => 'John Doe', 'projectName' => 'Marvel', 'project_id' => $project_id, ]; try { Mail::to('admin@example.com')->send(new ProjectCompleteAdminMail($data)); } catch (\Exception $e) { Log::error('Email Failed: Project Complete Mail'.$project_id, [$e]); } return "Email Sent Successfully!"; } }
6. Define a Route to Trigger the Email
In routes/web.php
:
use App\Http\Controllers\MailController; Route::get('/send-email', [MailController::class, 'sendEmail']);
7. Test the Email
Now, test the email by hitting this route and check your Mailtrap account—you should receive an email.
Run your Laravel application and visit:
http://localhost:8000/send-email
IMPORTANT
Refactored Email with Job Implementation:
To send multiple emails efficiently, use the queue system. Simply create a separate job file to handle the email sending process.
In this implementation, we are sending an email to all users who have the admin role, which could be around 10 to 15 users. If we send emails synchronously (in the normal way), the website may freeze until all emails are sent. Additionally, if the page is refreshed in the middle of the process, some admins might never receive the email.
To prevent this issue, we use jobs and queues. By dispatching the email-sending process to a background job, the website remains responsive, and every admin receives the email one by one. Even if the page is refreshed, the emails will still be sent because the job entries exist in the jobs table and are processed sequentially in the background.
Add this line to your .env
file to ensure the queue works properly.
QUEUE_CONNECTION=database
You create a job :
In your controller (app/Http/Controllers/MailController.php
), send the email job:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Mail\ProjectCompleteAdminMail; use App\Jobs\ProjectCompleteAdminEmailJob; use Mail; class MailController extends Controller { public function sendEmail() { $project_id = 123; $mailInfo = array( 'userName' => 'John Doe', 'projectName' => 'Marvel', 'project_id' => $project_id, ); ProjectCompleteAdminEmailJob::dispatch($mailInfo); return "Email Sent Successfully!"; } }
This creates a file under the app/Job
app/Job/ProjectCompleteAdminEmailJob.php
.
<?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Support\Facades\Mail; use App\Models\User; use Illuminate\Support\Facades\Log; class ProjectCompleteAdminEmailJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; private $mailInfo; / * Create a new job instance. * * @return void */ public function __construct($mailInfo = []) { $this->mailInfo = (object) $mailInfo; } / * Execute the job. * * @return void */ public function handle() { $mailInfo = $this->mailInfo; $project_id = $mailInfo->project_id; $adminUsers = User::where('is_admin', 1)->get(); foreach ($adminUsers as $key => $adminUser) { try { $mailInfo->userName = "Admin"; Mail::to($adminUser->email)->send(new ProjectCompleteAdminMail($mailInfo)); Log::info('Email Send: Project Complete Mail'); } catch (\Exception $e) { Log::error('Email Failed: Project Complete Mail'.$project_id, [$e]); } } } }