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

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

Posted on:September 20, 2023 at 02:00 PM

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