Laravel

How to send Email to Subscribers When You Publish a Post on Laravel

Often we write blog post and wish to send email to subscribers automatically right after the publishing the post. This is a really cool feature for laravel blog application. However it might be tricky. In today's blog post, I will show you can build a functionalities to send email to subscribers when you publish a post in laravel 10.

What you need?

#Table of Content

#Scenario

This is my plan as user story:

Scenario: Sending email when a new post is published

  • Given I have a list of subscribers
  • When I publish a new blog post
  • Then all subscribers should receive an email with the new post title and link

#Write Code

Let's write code for that functionalities.

#Set environmental values

To set environmental values, lets open our .env file and set the correct value based on your environment.

.env file

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel10
DB_USERNAME=root
DB_PASSWORD=

#Set up the controller

I will skip the route set-up. I will jump into the method in the controller which is more important for us.

Assume we have a controller called PostController where we work with store() method.

App\Controllers\PostController


use App\Events\PostPublished;

class PostController extends Controller {
    public function post(Request $request)
    {
        // Some form request validation code here

        $post = Post::create($request->all());

        // Dispatch an event for sending email to subscribers
        PostPublished::dispatch($post);

        // Other response code... 
    }
}

ℹī¸ Noticed here that, I dispatched an laravel event right after creating the post and passing the $post object on it.

The main idea is to tell event that something happened in the system, please send the email to all subscriber for that with the right information.

#Define an event

To define a new event, I will follow this command.

php artisan make:command PostPublished

Now let's update the event (just inject the post in the constructor).

class PostPublished
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct(public Post $post)
    {
    }
}

#Create the listener

The idea of event-listener is that, once an event is dispatched, a listener need to take care of it. So, let's create a listener now.

php artisan make:listener SendEmailToSubscribers
class SendEmailToSubscribers
{
    public function __construct(public Post $post)
    {
    }

    public function handle(object $event): void
    {
    }
}

#Registering event and listener

Now we need to register event with the respective listener in the boot() method EventServiceProvider class.

App\Providers\EventServiceProvider

    protected $listen = [
        // Some code
        PostPublished::class => [
            SendEmailToSubscribers::class
        ]
    ];

    // More code... 

#Sending email to Subscribers

Now in the handle() of listener SendEmailToSubscribers, I want to write code that send email to subscribers.

    public function handle(object $event): void
    {
        // Get Subscribers
        // You may need to filter the confirmed subscribers only by confirmed() custom scope.
        $subscribers = Subscriber::confirmed()->get();

        // Send email to all of them
        foreach ($subscribers as $subscriber) {
            Mail::to($subscriber->email)
                ->send(new PublishedNewPost($this->post));
        }
    }

#Create a mailable class

To send an email, let's create a mailable class, and I want it to markdown.

php artisan make:mail PublishedNewPost --markdown

App\Mail\PublishedNewPost

class PublishedNewPost extends Mailable
{
    use Queueable, SerializesModels;

    public function __construct(public Post $post)
    {
    }

    public function envelope(): Envelope
    {
        return new Envelope(
            subject: $this->post->title
        );
    }

    public function content(): Content
    {
        return new Content(
            markdown: 'mail.published-new-post',
        );
    }
}

#Update mail template (markdown)

resources/mail/published-new-post.blade.php

<x-mail::message>

Hello

The following new post has been published in {{ env('APP_NAME') }}.

{{ $post->title }}

<x-mail::button :url="{{ $post->link() }}">
Give a read now
</x-mail::button>

Thanks,<br>
{{ config('app.name') }}
</x-mail::message>

⚠ī¸ Be aware of that, if you are using any kind of 3rd party server for sending email, they might have email sending limitation per second. You need to find a way to handle that also.

That's it. It should work fine.

Get full Code