Transactional email sending using ZeptoMail in Laravel applications
- Published : December 28, 2025
- Last Updated : December 28, 2025
- 2 Views
- 7 Min Read
Laravel is a popular PHP framework that makes it easy to build efficient web applications. It provides a clean structure and rich built-in features that developers can use from the get-go.
One such feature is its robust email system. Using Laravel’s mail component, you can send emails via SMTP or API providers, test your mail configurations, send rich HTML templates, include attachments, deliver messages to multiple recipients, and even schedule emails to go out at a desired time.

Email-sending in Laravel using SMTP
Laravel integrates with popular email services to send emails directly from your application. It uses Symfony Mailer, which supports multiple delivery methods including SMTP, API-based sending, and even a log driver for safe testing during development.
You can use Laravel’s mail system for any kind of communication including transactional messages like password resets and order updates, or promotional campaigns like newsletters. The setup remains mostly the same—the only thing that changes is the provider you configure.
This guide will walk you through how to set up ZeptoMail as your email service in a Laravel application.
Step 1: ZeptoMail setup
Before sending emails from Laravel, you should set up ZeptoMail. This involves creating an account, adding your domain, and verifying DNS records so messages can be delivered correctly. Here's a quick link to a video explaining that:
Once you verify your domain, you can use the SMTP credentials to send emails from your Laravel application. To generate the credentials:
- Navigate to the desired Mail Agent and go to the SMTP/API section.
- You will be using these values in the next step.
Go to the SMTP tab and copy the user name and password.
Note: Ensure you match the correct port value with the certification:
465--> SSL; 587 --> TLS
For better security, ZeptoMail supports TLS v1.2 and above only.
Step 2: Configure Laravel mailer
The email settings can be configured in the config/mail.php file of the application. As a first step, you should add the SMTP credentials in the .env file available in the application's directory.
To configure SMTP, add the following details to the .env file:
MAIL_MAILER=smtp
MAIL_HOST=smtp.zeptomail.com
MAIL_PORT=587
MAIL_USERNAME=//SMTP username
MAIL_PASSWORD=// SMTP password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=welcome@zylker.com
MAIL_FROM_NAME=//Application nameThis will set up the email driver which defines the email-sending method—either SMTP or email APIs.
Step 3: Set up mailable class
A mailable class represents the different emails you would send like welcome emails, notifications, or newsletters. So, you can create separate mailable classes for each email. Each mailable class is a collection of three methods: envelope, content, and attachments.
Envelope method
The envelope method defines the email subject and the sender. It can be defined as:
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Envelope;
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
from: new Address('jeffrey@zylker.com', 'Jeffrey Way'),
subject: 'Warm greetings!',
);You can also add a global FROM address to this. But, this address will be used for all the emails sent from your account. This will also be used in case no FROM address is specified. You can add this in the config.php file as:
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'welcome@zylker..com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],Content method
The content method defines the actual content of the email in HTML or plain-text and attachments, if any. The email's contents can be added to the class under the View method, which contains the blade template.
You can create a directory in resources/views to hold all your templates. For example, to create a custom template, you can create a directory named, resources/views/mail/welcome-email.blade.php with the following content:
<p> Hi {{$name}}, </p>
<p>
Welcome to the service!
</pNotice how, we've added a dynamic value in the template? You can do this using the with parameter, which will pass the respective value. This can be added within the content class. Here's a sample code with the envelope and content in place:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Attachment;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Mail\Mailables\Headers;
use Illuminate\Queue\SerializesModels;
use Zeptomail\EmailHeader\CategoryHeader;
use Zeptomail\EmailHeader\CustomVariableHeader;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Header\UnstructuredHeader;
class ZeptoWelcomeMail extends Mailable
{
use Queueable, SerializesModels;
private string $name;
/**
* Create a new message instance.
*/
public function __construct(string $name)
{
$this->name = $name;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
from: new Address('jeffrey@zylker.com', 'Jeffrey Way'),//sender address should be verified
replyTo: [
new Address('taylor@zylkertech.com', 'Taylor'),
],
subject: 'Warm greetings!'
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'mail.zepto-welcome-email',
with: ['name' => $this->name],
);
}
}Next, create a route in the app/routes/console.php file with the recipient details and define the purpose of the code. In this example, it's sending a welcome email:
<?php
use App\Mail\ZeptoWelcomeMail;
use Illuminate\Support\Facades\Mail;
Artisan::command('send-zepto-welcome-mail', function () {
Mail::to('rebecca@zylker.com')->send(new ZeptoWelcomeMail("Jon"));
})->purpose('Send welcome mail');Using attachments
The example code above also lists an attachment component. You can add the relevant attachments by modifying the attachment method within the content method and add the relevant file in routes/web.php.
Here's a sample code within the content method:
public function content()
{
return new Content(
view: 'mail.welcomeemail',
with: ['name' => $this->name],
);
}
public function attachments()
{
return [
Attachment::fromPath($this->attachedFile),
];
}
}The corresponding router code is:
<?php
use Illuminate\Support\Facades\Route;
use App\Mail\MyTestEmail;
Route::get('/route', function () {
$filePath = public_path('Application.ico');
$name = "Application file";
Mail::to('receiver@zylker.com'')->send(new MyTestEmail($name, $filePath));
});Step 3: Send test email
Finally, you can check the configuration by sending a test email with the following command:
php artisan send-zepto-welcome-mailYou can check if you've received the email by logging in to the recipient email client.
That's the process for SMTP. If you want to use APIs, then you can follow the steps given below.
Email-sending using APIs
Laravel, which is powered by Symfony, supports multiple ESP driver APIs. To use ZeptoMail APIs, you should first add and register the driver, which can be done in a few simple steps.
Step 1: Add email driver
- Paste the following command in your application terminal:
composer require zohomail/laravel-zeptomail:1.0.1- Once the ZeptoMail package is installed, you can add the API token using the following command:
'zeptomail' => [
'key' => env('Send Mail Token'),
],Generating the Send Mail Token
- Select the Mail Agent you want to connect to your application.
- Navigate to the SMTP/API tab. This will open the Setup Details page.
- Here, you can copy your Mail Agent-specific send mail token under the API tab:
Mail Agents >> SMTP/API >> Send Mail Token >> Click to copy icon
Next, you should register ZeptoMail as a valid transport with Laravel. This requires you to add the details within the boot method of your AppServiceProvider:
use App\Mail\ZeptoMailTransport;
use Illuminate\Support\Facades\Mail;
use ZeptoMailTransactional\ApiClient;
public function boot(): void
{
Mail::extend('zeptomail', function (array $config = []) {
$client = new ApiClient;
$client->setApiKey($config['key']);
return new ZeptoMailTransport($client);
});
}- Once your transport is defined, you can add it to your config/mail.php file to use it as a driver:
'zeptomail' = [
'transport' = 'zeptomail',
],
Step 2: Set up ZeptoMail
Once you've registered ZeptoMail, you can add the API credentials to the .env file. Unlike the SMTP method, you can add just the send mail token:
ZEPTOMAIL_HOST=zoho.com
ZEPTOMAIL_TOKEN="SEND_MAIL_TOKEN"
MAIL_MAILER=zeptomail
MAIL_FROM_ADDRESS=welcome@zylker.com
MAIL_FROM_NAME="App Name"
Step 3: Create a mailable class
Next, create a mailable class to set up the desired email type:
php artisan make:mail WelcomemailWe've created a welcome email class in the example. This will be triggered when a new user signs up for a service. The following code will execute the function:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Attachment;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Mail\Mailables\Headers;
use Illuminate\Queue\SerializesModels;
use Zeptomail\EmailHeader\CategoryHeader;
use Zeptomail\EmailHeader\CustomVariableHeader;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Header\UnstructuredHeader;
class ZeptoWelcomeMail extends Mailable
{
use Queueable, SerializesModels;
private string $name;
/**
* Create a new message instance.
*/
public function __construct(string $name)
{
$this->name = $name;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
from: new Address('jeffrey@zylker.com', 'Jeffrey Way'),//sender address should be verified
replyTo: [
new Address('taylor@zylkertech.com', 'Taylor'),
],
subject: 'Welcome Mail'
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'mail.zepto-welcome-email',
with: ['name' => $this->name],
);
}
}Step 4: Create a template
You can add a new template under resources/views/mail/welcome-email.blade.php:
<p> Hi {{$name}}, </p>
<p>
Welcome to the service!
</p>Paste the router code for the template in the app/routes/console.php file:
<?php
use App\Mail\ZeptoWelcomeMail;
use Illuminate\Support\Facades\Mail;
Artisan::command('send-zepto-welcome-mail', function () {
Mail::to('rebecca@zylker.com')->send(new ZeptoWelcomeMail("Jon"));
})->purpose('Send welcome mail');
Step 5: Check the configuration
Finally, you can check the configuration by sending a test email using the following command:
php artisan send-zepto-welcome-mailNote: As a developer setting up their Laravel application for the first time, you can follow certain best practices to protect yourself against bad actors. Our guide on Laravel security gives you tips on how to get that done. These steps will ensure secure email sending from your Laravel application.
Additional functions
Send emails to multiple recipients
The above examples are for single recipients. If you wish to include multiple recipients, you can do it in two ways.
- Adding the recipients as CC, BCC within the envelope method. In this case, each recipient can see others in the list:
return new Envelope(
subject: 'My Test Email',
cc: ['receiver-cc@zylker.com'],
bcc: ['receiver-bcc@zylker.com']
);- The second method is done by creating an iterative loop of all the recipients. This way, the email will be sent out to individual recipients. However, an issue with this method is that every time the loop is executed, the email will be sent to the previous recipient in the list too.
To overcome this, we can recreate a mailable instance for every loop. This helps prevent the email from being sent to previous recipients every time the loop is executed. Here's how the code can be executed:
foreach (['First Coder' => 'recipientone@zylker.com', 'Second Coder' => 'recipienttwo@zylker.com'] as $name => $recipient) {
Mail::to($recipient)->send(new MyTestEmail($name));
}Queuing messages
Laravel supports asynchronous messaging which helps improve the application's performance time. You can do this by queuing the emails so they can be sent in the background.
To queue a message, add the queue method right before you specify the recipients:
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ZeptoWelcomeMail extends Mailable
{
use Queueable, SerializesModels;
/**
rest of the code
*/ Next, you should configure the queues in the .env file using QUEUE_CONNECTION.
Finally, when you use the following command in your emails, Laravel will automatically queue the email when ShouldQueue is executed:
Mail::to('testreceiver@example.com')->send(new MyTestEmail($name));Wrapping up
This guide has covered everything related to using ZeptoMail in your Laravel applications. Once you start using ZeptoMail for your transactional emails, you can review your outgoing emails in the Processed emails section of your account. This helps you review them and tweak your email sending based on the requirement.


