Step-by-Step Guide to Sending Emails in Laravel Using Multiple SMTP Servers
Shahrukh A. Khan
Posted on August 7, 2024
Sending emails is a crucial feature in many web applications, from user notifications to marketing campaigns. In Laravel, a popular PHP framework, configuring email delivery is straightforward. However, ensuring reliable email delivery often requires the use of multiple SMTP servers. By setting up multiple SMTP servers, you can create a fallback mechanism that enhances the reliability and efficiency of your email delivery system.
In this article, we will explore the process of configuring Laravel to send emails using multiple SMTP servers. Whether you're dealing with high-volume email campaigns or ensuring redundancy for mission-critical notifications, mastering this setup will help you maintain seamless communication with your users. We'll walk you through the necessary steps, offering tips and best practices along the way. Let's dive in and make your Laravel email system robust and dependable!
First we need to create config option inside config/mail.php inside mailer array there is a default smtp array like below
'smtp' => [
'transport' => 'smtp',
'url' => env('MAIL_URL'),
'host' => env('MAIL_HOST', '127.0.0.1'),
'port' => env('MAIL_PORT', 2525),
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
],
so we can create similar array with only required field env variables and we wil name it as backup_smtp
'backup_smtp' => [
'transport' => 'smtp',
'host' => env('MAIL_BACKUP_HOST', '127.0.0.1'),
'port' => env('MAIL_BACKUP_PORT', 2525),
'encryption' => env('MAIL_BACKUP_ENCRYPTION', 'tls'),
'username' => env('MAIL_BACKUP_USERNAME'),
'password' => env('MAIL_BACKUP_PASSWORD'),
],
Than we will update our .env files with real SMTP server settings like below
Default SMTP Server
MAIL_HOST=mail.example.com
MAIL_PORT=587
MAIL_USERNAME=primary@example.com
MAIL_PASSWORD=YOUR_SUPER_SECURE_PASSWORD
MAIL_ENCRYPTION=tls
Backup SMTP Server
MAIL_BACKUP_HOST=mail.backup-server.com
MAIL_BACKUP_PORT=587
MAIL_BACKUP_USERNAME=backup@email.com
MAIL_BACKUP_PASSWORD=YOUR_SUPER_SECURE_PASSWORD
MAIL_BACKUP_ENCRYPTION=tls
Until now we have created our Main SMTP Server and Backup STMP Server its time to configure our application to send email with the mail service for this we need to create an abstract class from the command line.
php artisan make:class Services/MailService
Above command will create a MailService class inside app/Service/MailService.php
The next step to create a public function with sendMail()
mail which will require 2 arguments the first argument will be mailable so we can use different mailable classes from laravel Mail and the second argument will be the recipient to whom we are sending email to.
MailService.php
<?php
namespace App\Services;
use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
class MailService
{
public function sendEmail($mailable, $recipient)
{
try {
// Primary SMTP Server
Mail::mailer('smtp')
->to($recipient)
->send($mailable);
Log::info("Email sent with Primary SMTP Server.");
} catch (Exception $e) {
Log::error("Primary SMTP Server failed to send email" . $e->getMessage());
try {
// Primary SMTP Server
Mail::mailer('backup_smtp')
->to($recipient)
->send($mailable);
Log::info("Email sent with Backup SMTP Server.");
} catch (Exception $e) {
Log::error("Backup SMTP Server failed to send email" . $e->getMessage());
Log::error("Both SMTP Server failed to send email" . $e->getMessage());
}
}
}
}
To connect this MailService class with our application we will create MailServiceProvider to make things easier and scalable so we will create provider via artisan command as below.
php artisan make:provider MailServiceProvider
Which will be created inside app/Providers/MailServiceProvider.php
and we will register our MailService class within laravel container but we do not want this to boot every time.
<?php
namespace App\Providers;
use App\Services\MailService;
use Illuminate\Support\ServiceProvider;
class MailServiceProvider extends ServiceProvider
{
/**
* Register services.
*/
public function register(): void
{
$this->app->singleton(MailService::class, function($app){
return new MailService();
});
}
/**
* Bootstrap services.
*/
public function boot(): void
{
//
}
}
Now we'll create a mailable with markdown to send email for this we need to use an artisan command as below since this tutorial is dedicated to enhance the functionality for SMTP I will not be covering mailable here but to sake of this tutorial we will create mailable and controller to send email via artisan command
php artisan make:mail SendEmail --markdown=emails.send-email
Above artisan command will create a mailable inside app/Mail
directory as below.
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class SendEmail extends Mailable
{
use Queueable, SerializesModels;
public $mailData;
/**
* Create a new message instance.
*/
public function __construct($mailData)
{
$this->mailData = $mailData;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Send Email',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
markdown: 'emails.send-email',
with: [
'mailData' => $this->mailData
],
);
}
}
We can send email in different ways within laravel i.e. Observer or Jobs but to keep things simple we will create controller via artisan command for this tutorial and we will use a protected
variable and construct function to load our MailService class when it is being called and I am assuming you are aware of how to create views and validate the post request in laravel.
php artisan make:controller EmailController
<?php
namespace App\Http\Controllers;
use App\Mail\SendEmail;
use App\Services\MailService;
use Exception;
use Illuminate\Http\Request;
class EmailController extends Controller
{
protected $mailService;
public function __construct(MailService $mailService)
{
$this->mailService = $mailService;
}
public function myForm()
{
return view('my-form');
}
public function myFormPost(Request $request)
{
// validate the request
$emailData = [
'name' => $request->name,
'email' => $request->email,
];
$mailable = new SendEmail($emailData);
try{
$this->mailService->sendEmail($mailable, $emailData['email']);
return response()->json(['message' => 'Email has been sent']);
}catch(Exception $e){
return response()->json(['message' => $e->getMessage()]);
}
}
}
For this tutorial we have created a minimal form fields just name and email.
<form action="{{ route('post.form') }}" method="POST">
@csrf
<input type="text" name="name">
<input type="email" name="email">
<input type="submit" value="Send Email">
</form>
Now will create routes inside web.php to send emails in laravel using multiple SMTP Servers.
Route::get('/send', [EmailController::class, 'myForm'])->name('post.form');
Route::post('/send', [EmailController::class, 'myFormPost']);
It's time to go on the browser and send emails using our codes which we have done so far so open up your browser and test route /send in my case.
http://laravel.test/send
If everything works you should be able to see in browser after filling out the form and click send button you should see as below.
{"message":"Email has been sent"}
Since we are logging messages inside laravel.log with Log::info();
and Log::error();
inside our MailService class we should also see the following message if the mail sent from Primary SMTP server.
local.INFO: Email sent with Primary SMTP Server.
Once everything works as expected we will change the password for our primary SMTP server email to check if the email is being sent from backup SMTP server.
local.ERROR: Primary SMTP Server failed to send email (along with actual message)
local.INFO: Email sent with Backup SMTP Server
Now we can make sure if the email failed for any reason from primary SMTP server it will be send via backup SMTP server but if the backup SMTP server couldn't send email user/admin will not receive an email.
We hope you enjoyed this guide and learned something new about sending emails in Laravel using multiple SMTP servers. If you found this article helpful, feel free to follow us on X, Instagram.
This blog post was written by the awesome team at diligentcreators.com.
Posted on August 7, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.