Updated on July 10, 2020
Notifications are informational messages delivered to app users. They are mostly meant to notify of certain transactions or events like password change, order status, and so on. Laravel provides a built-in feature called Notification. It allows you to send a message to any user via different communication channels. Today, we’ll focus on sending email notifications and explain how to implement this in your app.
What notification channels are supported by Laravel?
Although we’ll be talking about notifications to be sent via the email channel, you might be interested in other options. Besides mail, those include:
- SMS – users will get text notifications on their phone. SMS notifications in Laravel are implemented through the Vonage, formerly known as Nexmo Nexmo API. But you are free to use another SMS provider, of course:)
- Slack – users will get notifications in Slack. For this, you need to configure the
Incoming Webhooks
integration to send data into Slack in real-time. - Database – users will get notifications in the app’s user interface. The information about notifications is stored in a database table. Your JavaScript client accesses it to return notifications for a notifiable user.
- Broadcast – notifications are broadcast to a notifiable user in real time. When some data is updated on the server, a message is sent over a WebSocket connection to the JavaScript client.
If you need a custom notification channel, you can always write your own drivers to deliver notifications. But first, let’s find out how it goes with email notifications.
How to create a mail notification?
Notifications in Laravel are created with the make:notification
Artisan command. Let’s make one on the order status update as follows:
php artisan make:notification StatusUpdate
All notifications are stored in the app/Notifications directory. Once created, you’ll see the following content in your StatusUpdate.php file:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class StatusUpdate extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
Let’s format it as a message to be sent via the email channel.
Notification formatting
To preview all variations of the email, you need to return it directly from a route. So, you don’t have to actually send it to a real or fake user. For this, we need to create a route by adding the following line to web.php in the routes/ directory:
Route::get('send', 'NotifyController@index);
And here is how to preview your notification:
Route::get('mail', function () {
$order = App\Order::find(1);
return (new App\Notifications\StatusUpdate($order))
->toMail($order->user);
});
Each notification in Laravel is represented by a single class. If you want your app to send email notifications, focus your attention on two methods, via
and toMail
.
The via
method will receive a $notifiable
entity and defines the notification delivery channel. In the code above, we already have the required parameter, return ['mail']
, by default.
public function via($notifiable)
{
return ['mail'];
}
toMail
is a message building method triggered by the via
method. It will receive a $notifiable
entity and should return an Illuminate\Notifications\Messages\MailMessage
instance. toMail
allows you to configure email parameters. So, your mail message may contain a text line (line
), a call-to-action button (action
), a greeting line (greeting
), and so on. Check out the following example:
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->line('Your order status has been updated')
->action('Check it out', url('/'))
->line('Best regards!');
}
Here, we defined several methods provided by the MailMessage
object. The notification will be converted into a responsive email template consisting of HTML and plain-text.
If you want to inform users of some failed activity or error, there is the error
method for that. It will mark your email’s CTA button in red. Here is how it looks under the hood:
public function toMail($notifiable)
{
return (new MailMessage)
->error()
->subject('Payment Failed')
->line('Your payment details are wrong')
->action('Pay', url('/'));
}
If you prefer to use a custom template to render the notification message, you can make use of the view method. It will specify a template to be used instead of defining the “lines” of text. For example:
public function toMail($notifiable)
{
return (new MailMessage)->view(
'emails.order', ['order' => $this->order]
);
}
Don’t forget to put your template under resources/views/emails/order.blade.php
Another alternative is to generate a mailable class and return it from toMail
as follows:
use App\Mail\StatusUpdate as Mailable;
public function toMail($notifiable)
{
return (new Mailable($this->order))->to($this->user->email);
}
Customizing the email notification attributes
Sender
The address the email notification is sent from is defined by default in the configuration file – config/mail.php. If you want to use a specific address, it’s not necessary to tweak this file. You can specify it using the from
method as follows:
public function toMail($notifiable)
{
return (new MailMessage)
->from('sender@example.com', 'Sender')
}
Recipient
The Laravel Notification system sends an email message to the recipient identified as a user of your app. But you can customize the recipient’s email address. For this, you need to define a routeNotificationForMail
method on the notifiable entity. For example:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
public function routeNotificationForMail($notification)
{
} // Return email address only
return $this->email_address;
}
} // Return both name and email address
return [$this->email_address => $this->name];
}
}
Starting from version 5.6.19, Laravel supports for multiple Cc, Bcc, and Reply-to recipients on mail notifications. This can be done on mailable classes as follows:
public function build()
{
return $this->from('example@example.com')
$this->cc('cc@example.com')
$this->bcc('bcc@example.com')
$this->replyTo('replyTo@example.com')
->view('emails.orders.shipped');
}
Subject
By default, the class name of the notification forms the email subject. But it’s automatically formatted to “title case”. In our example, we named the class StatusUpdate
. So, the email subject will be Status Update. For a specific subject for your notification, you can use the subject
method as follows:
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Order Status')
}
Here is the email notification we’ve got in the end:
<<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class StatusUpdate extends Notification
{
use Queueable;
public function __construct()
{
//
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Order Status')
->from('sender@example.com', 'Sender')
->greeting('Hello!')
->line('Your order status has been updated')
->action('Check it out', url('/'))
->line('Best regards!');
}
public function toArray($notifiable)
{
return [
//
];
}
}
Once the notification is ready, let’s get it delivered!
How to send mail notifications?
Configuring the email sender
First, we need to set up a configuration to be used for sending emails. Laravel uses the popular SwiftMailer library. It has drivers for a bunch of popular email services like Mailgun, Amazon SES (check out our tutorial on how to use Amazon SES), and others. The configuration for the API-based drivers, you will find in the Laravel Documentation.
If you prefer using a particular SMTP relay service for sending emails, you need to tweak configuration in the .env file in the root directory. For example, here are the settings for the SendGrid SMTP server:
APP_NAME="YOUR_APP_NAME"
MAIL_MAILER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=25
MAIL_USERNAME=<username>
MAIL_PASSWORD=<password>
MAIL_ENCRYPTION=ssl
MAIL_FROM_NAME=<Sender’s name>
MAIL_FROM_ADDRESS=<Sender’s email address>
For more on this, read the tutorial on How to send emails in Laravel.
Sending notifications
There are two ways for sending mail notifications in Laravel: Notifiable
trait and Notification
facade.
Sending with Notifiable
trait
Notifiable
trait contains the notify
method to send notifications. The App\User
class implements the trait, and it becomes the notifiable entity.
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
}
notify
expects to receive a notification instance:
use App\Notifications\StatusUpdate;
$user->notify(new StatusUpdate($order));
That’s how NotifyController.php will look if you use the Notifiable
trait for notification sending:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Notification;
use App\Notifications\StatusUpdate;
use Illuminate\Notifications\Notifiable;
class NotifyController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$user->notify(new StatusUpdate($order));
}
}
You can use Notifiable
trait not only on the App\User
class but on any of your classes.
Sending with Notification
facade
Facades in Laravel are sort of static methods to classes but with an expressive syntax, as well as better testability and flexibility. They allow you to use Laravel’s features, and you don’t have to remember long class names to be configured manually. The Notification
facade is suitable for sending a notification to multiple notifiable entities. To use it, pass the notifiable entities and the notification instance to the send
method as follows:
Notification::send($users, new StatusUpdate($order));
On-demand and queued notifications
In the above examples, notifications will be sent to users of your app. And what if you need to notify someone else? In this case, you can use the Notification::route
method that will send the notification to the recipient specified by you. Here is how it looks:
Notification::route('mail', 'not-a-user@example.com')
->notify(new StatusUpdate($order));
Something else you might be interested in is queued emails. It’s not about SMTP queues, but queued notifications that will let you speed up your app’s response time. For this, you need to add the ShouldQueue
interface and the Queueable
trait to your class. You don’t have to import them since they already are for all notifications generated through make:notification
. All you need to do is add them to your class:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
class StatusUpdate extends Notification implements ShouldQueue
{
use Queueable;
// ...
}
After that, send the notification as usual, and its delivery will be queued automatically by the ShouldQueue
interface. If you need to delay the delivery, there is the delay method for this. Chain it onto the instantiation of your notification like this:
$when = now()->addMinutes(10);
$user->notify((new StatusUpdate($order))->delay($when));
How to test email notifications
Mailtrap Email Sandbox
Once you have your email notifications set up, you should test this functionality. Thanks to our Email Sandbox, you don’t have to send actual notifications using Laravel.
Using the Sandbox, developers can capture SMTP traffic from staging and prevent all those test email notifications from going to actual recipients. Besides performing tests in a safe environment, the Sandbox allows you to inspect and debug emails.
Email Sandbox has a quick installation process that requires you to only type in your Mailtrap credentials to the .env file, so it will look as follows:
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=528
MAIL_USERNAME=<username> //your Mailtrap username
MAIL_PASSWORD=<password> // your Mailtrap password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=from@example.com
MAIL_FROM_NAME=Example
Alternatively, you can adjust your config/mail.php using the same settings. After that, all the email notifications sent from your app will end up in the Mailtrap Demo Inbox.
Also, you’ll be able to do quick spam score checks for your email notifications and preview them to know how they are rendered in different email clients.
For more on the available features and functionalities, read the Mailtrap Getting Started Guide.
Notification Fake
Besides Mailrap, you can make use of the fake
method of the Notification
facade. It mimics the mail delivery process and lets you verify whether a particular email would have hit the recipient’s inbox. Check out how it works:
<?php
namespace App\Notifications;
use App\User;
use App\Notifications\StatusUpdate;
use Illuminate\Support\Facades\Notification;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
class StatusUpdate extends User
{
public function testStatusOrder()
{
Notification::fake();
// Perform status order...
Notification::assertSentTo(
$user,
StatusOrder::class,
function ($notification, $channels) use ($order) {
// retrieve the mail content
$mailData = $notification->toMail($user)->toArray();
$this->assertEquals("Order #{$order->orderNumber} shipped", $mailData['subject']);
$this->assertEquals("Hello {$user->name}!", $mailData['greeting']);
$this->assertContains("Your order #{$order->orderNumber} has been shipped", $mailData['introLines']);
$this->assertEquals("View Order", $mailData['actionText']);
$this->assertEquals(route('orders.show', $order), $mailData['actionUrl']);
$this->assertContains("Thank You!", $mailData['outroLines']);
return $notification->order->id === $order->id;
}
);
}
}
Here, you can see various assertions to test the mail content. They are made after the code under test is executed.
Wrap up: How to get the most of the email notifications?
You should not go without email notifications in your app. They increase the LTV of your customers, as well as the retention rate. That’s why you must not only have them function well, but also make sure of their quality and validity. The following tips will help you get the most of email notifications:
- Control spamminess of your notifications
We know you’re not a spammer (at least we hope so), but are spam filters aware of this as well? You should care about why emails going to spam and how to prevent it. This will prevent your users from missing some important notifications and will strengthen their loyalty to your app.
- Polish your body text
The content of an email notification must be grammatically correct. This is one of the essential aspects of spam-proof emails, as well as a sign of respect to your users.
- Put emphasis on the subject line
We’re sure you know the importance and significance of the email subject line. So, make it informative and eye-catching, and avoid such spam-triggers as exclamation marks or capital letters. Check out the Email Testing Checklist to discover some useful tools for handling email subject lines.
- Apply a personal approach
Most likely, this tip is better suited to email marketing campaigns. However, setting a personal connection via email notifications won’t do any harm. Instead, it’s a good way to show the importance of each user individually.
- Use appealing layouts
People draw attention to visually appealing content. But you should be careful in visualizing your email notifications. Do not abuse colors and fonts. You need to attract the recipient with your message rather than make him want to close it right away.