Content Index
- Mailable class
- Send emails individually
- Parameters
- CC and BCC/CCO
- Send mass emails
- Send user email verification messages in Laravel
- Send confirmation messages programmatically
- Extra: Rest Api for users to verify
- AWESOME TRICK to send Automated and MASSIVE emails in Laravel Livewire
- Implementation
- 1. Counter Management (subpage)
- 2. The sending function (sendEmailSubscribers)
- 3. The Secret: wire:poll and always
- Optimization and Concurrency
- JavaScript Alternative
Knowing how to limit the number of user requests makes it a good idea to learn how to send email notifications to these users. Email sending is very easy to configure in Laravel. If you already have a hosting service, all you need to do is create an email address and password.
From there, you'll need to configure some parameters. If you don't know these because your email server is provided by a different service, you should ask your service provider. In the case of Hostinger, the parameters would be as follows:
config/mail.php
'smtp' => [
'transport' => 'smtp',
'host' => env('MAIL_HOST', 'smtp.hostinger.com'),
'port' => env('MAIL_PORT', 465),
'encryption' => env('MAIL_ENCRYPTION', 'ssl'),
'username' => env('MAIL_USERNAME','<EMAIL>'),
'password' => env('MAIL_PASSWORD',"<PASSWORD>"),
'timeout' => null,
'auth_mode' => null,
],Or you can use a testing service in case you don't have access to a real email server like mailtrap:
In which, you must go to the previous page, create an account that is completely free, create an inbox and configure your project.
.env
MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=ec5cbede982042
MAIL_PASSWORD=********0be7Mailable class
To send any email, we must use a class, just as when we define a model, controller or request, we must create a class with a specific structure:
app\Mail\OrderShipped.php
<?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 OrderShipped extends Mailable
{
public $email;
public $title;
public $content;
use Queueable, SerializesModels;
public function __construct($email, $title, $content)
{
$this->email = $email;
$this->title = $title;
$this->content = $content;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Order Shipped',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'emails.subscribe',
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}To do this, we use the command:
$ php artisan make:mail OrderShippedWe use the envelope() method to define the subject, the content() method for the body of the message, there we specify the view and the attachments() method for attached files, the constructor is basic in PHP classes and is used to initialize properties or other tasks when creating the object or instance of the class.
We also defined some example properties such as the title, content and email, you can create others or modify the defined ones according to your needs.
We can also use a single method to define the subject and content:
app\Mail\SubscribeEmail.php
<?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 SubscribeEmail extends Mailable
{
use Queueable, SerializesModels;
public $email;
public $title;
public $content;
public function __construct($email, $title, $content)
{
$this->email = $email;
$this->title = $title;
$this->content = $content;
}
public function build()
{
return $this->subject($this->title)->view('subscribe');
}
}From it, we can customize the arguments to receive, such as email subject or email content, and return a blade view that corresponds to the body of the email; for example:
We create the view that can have any format:
resources\views\emails\subscribe.blade.php
<p>Hi<br>
{!! $content !!}Send emails individually
To send the emails, we create an instance as follows:
Mail::to('no-reply@example.net.com')->send(new SubscribeEmail('contact@gmail.com', $title, $content));Parameters
You are not limited to simply specifying "to" recipients when sending a message. You are free to configure "to", "cc" and "bcc" recipients using their respective methods:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->send(new SubscribeEmail(contact@gmail.com', $title, $content));CC and BCC/CCO
A CC is a way of sending additional copies of an email to other people "carbon copy", while BCC is the same as the CC but this list of recipients or people remain hidden, that is, they do not appear in the signature of the email.
Send mass emails
One of the ways in which we can send multiple emails in bulk or batch is to send multiple emails in the same contact. This is usually a delicate case since, if we do something like the following:
Mail::to('no-reply@example.net.com')
->cc(['hideemail1@gmail.com','hideemail2@gmail.com','hideemail3@gmail.com'])->send(new SubscribeEmail(contact@gmail.com', $title, $content));The email will expose all the users' emails, a situation that is usually a problem due to the exposure of all emails to all recipients; instead of using the cc option we can use the bcc option which allows us to hide the recipients:
Mail::to('no-reply@example.net.com')
->bcc(['hideemail1@gmail.com','hideemail2@gmail.com','hideemail3@gmail.com'])->send(new SubscribeEmail(contact@gmail.com', $title, $content));Now we will see that the emails defined in BBC appear hidden:
And not present as in the previous image.
Send user email verification messages in Laravel
Confirmation messages are emails that are sent to a client when completing an action to confirm the operation carried out, for example, changing a password, recovering a username, purchasing a product, etc., this in any web system that includes some interaction with the user is a fundamental task, therefore, we will learn to send emails from Laravel.
In Laravel, we have access to a function that we can use to confirm a user's registration.
Send confirmation messages programmatically
From a user instance, we have access to a function that sends the confirmation email to verify a user by email:
$user->sendEmailVerificationNotification();Of course, for this you must have configured your SMTP server to send emails.
And remember to implement in your user model the classe MustVerifyEmail:
use Illuminate\Contracts\Auth\MustVerifyEmail;
***
class User extends Authenticatable implements MustVerifyEmailNow with this, you can make use of the previous function; when using it, you will receive an email like the following:

Extra: Rest Api for users to verify
Here I leave you a common use of this function on a Rest Api to register users and verify them; we have an exclusive function to send user verification emails:
class UserController extends Controller
{
/**
* Register
*/
public function register(Request $request)
{
$validator = Validator::make($request->all(), StoreUser::myRules());
if ($validator->fails())
return $this->errorResponse($validator->errors(), 422);
try {
$user = new User();
$user->name = $request->name;
$user->email = $request->email;
$user->password = Hash::make($request->password);
$user->save();
if ($request->subscribed) {
Subscribe::create(['email' => $request->email]);
}
$success = true;
$message = 'User register successfully';
} catch (\Illuminate\Database\QueryException $ex) {
$success = false;
$message = $ex->getMessage();
}
// response
$response = [
'success' => $success,
'message' => $message,
];
$credentials = [
'email' => $request->email,
'password' => $request->password,
];
Auth::attempt($credentials);
$user->sendEmailVerificationNotification();
return $this->successResponse($response);
}
public function verifie()
{
$user = Auth::user() ?? auth('sanctum')->user();
$userModel = User::find($user->id);
$userModel->sendEmailVerificationNotification();
return $this->successResponse("ok");
}As you can see, we have a registration function, in which we obtain the user's data and once registered, we start the session with sendEmailVerificationNotification and send the email with the function explained in this post.
And a check function for you to run programmatically; In this example, we are using a Rest Api in Laravel with Laravel Sanctum with tokens, but you can use any type to verify user accounts.
AWESOME TRICK to send Automated and MASSIVE emails in Laravel Livewire
I'm going to show you how to send automated emails every 7, 5, or 4 seconds (or whatever interval you determine) using Laravel Livewire. As you can see, every time the counter changes, an email is sent to my subscribers.
This scheme is extremely efficient: I have used it to send about 1,000 emails in less than two hours. If you have a database of, for example, 9,000 users, you can do the math or even run the process in parallel by opening several browser tabs. If you don't use Livewire, don't worry; you can implement this same scheme with a bit of JavaScript.
The panel I use to manage the mailings. The email content is written in HTML using the CKEditor plugin. I have published several videos and articles here on my blog about how to integrate this editor with Laravel in case you are interested in diving deeper into it.
Implementation
The core of this is a Livewire component, taking advantage of its reactive nature. Here are the key points:
1. Counter Management (subpage)
I use a property called subpage that starts at zero. This is fundamental in case an error occurs (internet or server failure). If the process stops, I can see which was the last block sent and resume from there (for example, from page 50). This allows me to send blocks of 300 emails, let the server rest, and continue later.
<?php
namespace App\Livewire\Dashboard\Blog;
use App\Mail\SubscribeEmail;
use App\Models\Subscribe;
use App\Models\SubscriptionContent;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Livewire\Component;
use Livewire\WithFileUploads;
use Illuminate\Support\Facades\Config;
class SubscribeSendEmail extends Component
{
***
public $subPage = 0; // current sub
***
// sends the email to each sub
function sendEmailSubscriptions()
{
// SEND TO ALL
$subscribe = Subscribe::select('name', 'email', 'id')
->where('active', $this->typeSubscriptors) // Selected Subs Group
->offset($this->subPage) // page that varies in the poll
->limit(1) // only one
->orderBy('id')->first();
}
}2. The sending function (sendEmailSubscribers)
I look for the user in my subscribers table using a limit of one (limit(1)->first()). As long as records exist, the process continues; otherwise, it stops.
class SubscribeSendEmail extends Component
{
***
// sends the email to each sub
function sendEmailSubscriptions()
{
// SEND TO ALL
$subscribe = Subscribe::select('name', 'email', 'id')
->where('active', $this->typeSubscriptors) // Selected Subs Group
->offset($this->subPage) // page that varies in the poll
->limit(1) // only one
->orderBy('id')->first();
***
}3. The Secret: wire:poll and always
The real "magic" of Livewire in this scheme is the wire:poll directive. This instruction tells the component how often it should refresh (call itself).
- Interval: I use 7 seconds. I've tried 3 or 4 seconds and it works fine, but 7 is a safe margin to avoid crashing third-party services (like Hostinger or Gmail).
- Keep-alive mode: I use the .always modifier so that if you switch tabs in the browser, the process doesn't stop. This allows the sending to continue in the background.
And the blade:
resources/views/livewire/dashboard/subscribe-send-email.blade.php
@if ($active)
<div wire:poll.7000ms.keep-alive="startSendEmailOne">
<h3>Current Value: {{ $subPage }}</h3>
<p class="m-0">This value updates automatically every 7 seconds.</p>
</div>
<label for="">SubPage</label>
@endifThe complete code for the automated sending of my component in Laravel Livewire:
app/Livewire/Dashboard/Blog/SubscribeSendEmail.php
<?php
namespace App\Livewire\Dashboard\Blog;
use App\Mail\SubscribeEmail;
use App\Models\Subscribe;
use App\Models\SubscriptionContent;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Livewire\Component;
use Livewire\WithFileUploads;
use Illuminate\Support\Facades\Config;
class SubscribeSendEmail extends Component
{
// object
public SubscriptionContent $subscriptionContent;
// info
public $subscribes = [];
public $countSubscribes = 0;
// to send the email, poll is activated and if it is active
public $subPage = 0; // current sub
public $active = false; // sending emails
*** // to move to the next sub to send the email
public function startSendEmailOne()
{
$this->submit();
$this->subPage++;
}
// this function starts the process of sending the individual email
public function submit()
{
// activates the poll
$this->active = true;
// sends the first email
$this->sendEmailSubscriptions();
}
// sends the email to each sub
function sendEmailSubscriptions()
{
// SEND TO ALL
$subscribe = Subscribe::select('name', 'email', 'id')
->where('active', $this->typeSubscriptors) // Selected Subs Group
->offset($this->subPage) // page that varies in the poll
->limit(1) // only one
->orderBy('id')->first();
// if there is no sub it ends
if (!$subscribe) {
$this->active = false;
return;
}
// *** Testing
Log::info("$this->subPage - $subscribe->id $subscribe->email");
// app email
$smtpUser = config('mail')['mailers']['smtp']['username'];
// prepares the mail to send the email
$mailer = Mail::build([
'transport' => 'smtp',
'host' => 'smtp.domain.com',
'port' => 465,
'encryption' => 'ssl',
'username' => $smtpUser,
'password' => config('mail')['mailers']['smtp']['password'],
]);
// Send the email
$mailer
->to($subscribe->email)
->send(
(new SubscribeEmail($subscribe->email, $subscribe->name ?? $subscribe->email, $this->subscriptionContent->title, $this->subscriptionContent->content))
->from($smtpUser, 'Andrés Cruz')
);
}
}And the blade:
resources/views/livewire/dashboard/subscribe-send-email.blade.php
@if ($active)
<div wire:poll.7000ms.keep-alive="startSendEmailOne">
<h3>Current Value: {{ $subPage }}</h3>
<p class="m-0">This value updates automatically every 7 seconds.</p>
</div>
<label for="">SubPage</label>
@endif
<x-button class="mt-2 mb-3" wire:click="startSendEmailOne">
{{ __('Start Send Email') }}
</x-button>Optimization and Concurrency
If you need to go faster, you can open multiple instances of the panel. For example:
- Tab 1: Sends from subscriber 0 to 4,500.
- Tab 2: Sends from subscriber 4,501 to 9,000.
This allows concurrent sending and cuts the time in half. Remember that the 7-second interval is to avoid error 500; if you send emails every half second and the mail service takes 2 seconds to respond, you will saturate the queue and the process will fail.
JavaScript Alternative
If you prefer not to use Livewire, you can achieve the same with setInterval or setTimeout in JavaScript, making requests via AJAX or Fetch to the server every 7 seconds cyclically.
The next step is for you to learn how you can extend Laravel with key functionalities such as detecting whether the browsing is mobile or PC.