Laravel Mail Notifications: How to Customize the Templates

 Laravel has a useful Notification system, where you can notify user about something via email, Slack etc. And there is a quite good default HTML template for emails. But what if you want to customize its design?

This is the template I’m talking about:

laravel notification

Let’s remind ourselves how to send this email.

php artisan make:notification HelloUser

It will generate class app/Notifications/HelloUser.php – here’s the main part of it:

class HelloUser extends Notification
{
    public function via($notifiable)
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->line('The introduction to the notification.')
                    ->action('Notification Action', url('/'))
                    ->line('Thank you for using our application!');
    }

}

By default, notification channel is mail, and there is some default email constructed.

You build the email text by using methods like ->line() or ->action(), and actually in the back-end it fills in a beautiful HTML template.

How to fire this notification?

$user = User::first(); // or any other way you get User instance
$user->notify(new HelloUser());

Now, we didn’t edit any Blade template or any HTML, where to find it? It’s not that easy, by default it’s not in resources/views anywhere. You need to publish the templates, like this:

php artisan vendor:publish --tag=laravel-notifications

Result:
Copied Directory [/vendor/laravel/framework/src/Illuminate/Notifications/resources/views] To [/resources/views/vendor/notifications]

So before you publish – the template is inside of Laravel core in /vendor folder (which you shouldn’t edit, ever). And now – we can modify our HTML.

In fact, there’s only one published template – file resources/views/vendor/notifications/email.blade.php:

@component('mail::message')
{{-- Greeting --}}
@if (! empty($greeting))
# {{ $greeting }}
@else
@if ($level == 'error')
# Whoops!
@else
# Hello!
@endif
@endif

{{-- Intro Lines --}}
@foreach ($introLines as $line)
{{ $line }}

@endforeach

{{-- Action Button --}}
@isset($actionText)

@component('mail::button', ['url' => $actionUrl, 'color' => $color])
{{ $actionText }}
@endcomponent
@endisset

{{-- Outro Lines --}}
@foreach ($outroLines as $line)
{{ $line }}

@endforeach

{{-- Salutation --}}
@if (! empty($salutation))
{{ $salutation }}
@else
Regards,
{{ config('app.name') }} @endif {{-- Subcopy --}} @isset($actionText) @component('mail::subcopy') If you’re having trouble clicking the "{{ $actionText }}" button, copy and paste the URL below into your web browser: [{{ $actionUrl }}]({{ $actionUrl }}) @endcomponent @endisset @endcomponent

But wait, you will say – where’s all the HTML?? It’s hiding under another layer – Laravel’s notification components based on Markdown language.

There are three components, mentioned in the official Laravel docs:

1. Button:

@component('mail::button', ['url' => $url, 'color' => 'green'])
View Invoice
@endcomponent

2. Panel:

@component('mail::panel')
This is the panel content.
@endcomponent

3. Table:

@component('mail::table')
| Laravel       | Table         | Example  |
| ------------- |:-------------:| --------:|
| Col 2 is      | Centered      | $10      |
| Col 3 is      | Right-Aligned | $20      |
@endcomponent

And yes, you can write Markdown instead of HTML, it may be a convenient thing for some people (developers, mostly).

But if you do want to get HTML and be able to edit it, run this:

php artisan vendor:publish --tag=laravel-mail

This will happen:
Copied Directory [/vendor/laravel/framework/src/Illuminate/Mail/resources/views] To [/resources/views/vendor/mail]

This is what we get then:

laravel mail components

Now it looks really familiar and we can, for example, go to button.blade.php and add some class or text:

<table class="wp-block-table action"><tbody><tr><td>
<table border="0" width="100%" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td align="center">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a class="button button-{{ $color or 'blue' }}" href="{{ $url }}" target="_blank" rel="noopener">{{ $slot }}</a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td><td>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a class="button button-{{ $color or 'blue' }}" href="{{ $url }}" target="_blank" rel="noopener">{{ $slot }}</a></td>
</tr>
</tbody>
</table>
</td><td><a class="button button-{{ $color or 'blue' }}" href="{{ $url }}" target="_blank" rel="noopener">{{ $slot }}</a></td></tr><tr><td>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a class="button button-{{ $color or 'blue' }}" href="{{ $url }}" target="_blank" rel="noopener">{{ $slot }}</a></td>
</tr>
</tbody>
</table>
</td><td><a class="button button-{{ $color or 'blue' }}" href="{{ $url }}" target="_blank" rel="noopener">{{ $slot }}</a></td></tr><tr><td><a class="button button-{{ $color or 'blue' }}" href="{{ $url }}" target="_blank" rel="noopener">{{ $slot }}</a></td></tr></tbody></table>

We change {{ $slot }} into Click here: {{ $slot }} and we get this email:

laravel notification

Finally, you can even have THEMES with different CSS styles for each of them – like, for example, different emails for different user groups.

For that, there’s a folder resources/views/mail/html/themes with a CSS file, and you can change the default them in config/mail.php:

    'markdown' => [
        'theme' => 'default',

        'paths' => [
            resource_path('views/vendor/mail'),
        ],
    ],

So this is how to customize Laravel email notifications. You can find more information in the official documentation.

Comments

Popular posts from this blog

How to Install and Use Wine on Ubuntu 20.04

Laravel: How to Paginate Collection

Laravel 8 Redis setup on Windows with xampp