Skip to content

SendEmailVerificationNotification listener is registered by default and there is no (easy) way to disable it #52601

@JaZo

Description

@JaZo

Laravel Version

11.21.0

PHP Version

8.2.22

Database Driver & Version

No response

Description

Issue

Laravel registers the \Illuminate\Auth\Listeners\SendEmailVerificationNotification listener for the \Illuminate\Auth\Events\Registered event by default, and there is no (easy) way to disable this.

What I've tried:

1. Replace EventServiceProvider

As suggested in #51187. I've created a custom EventServiceProvider where I've overwritten the configureEmailVerification function with an empty function. After that I tried to replace this service provider in config/app.php:

'providers' => ServiceProvider::defaultProviders()->replace([
    \Illuminate\Foundation\Support\Providers\EventServiceProvider::class => \App\Providers\EventServiceProvider::class,
])->toArray(),

But this won't work as this provider is registered dynamically in \Illuminate\Foundation\Configuration\ApplicationBuilder::withEvents. Replacing it with a custom binding also isn't possible as service providers aren't resolved from the container.

Conclusion: not viable

2. Stop event propagation

I can stop propagation in my own listener to prevent execution of the default one. But that is highly unstable as the order might not always be guaranteed and what if I need an extra listener that is triggered afterwards?

Conclusion: not viable

3. Use a custom Registered event

I can create a custom registered event and dispatch that instead of the default one. But several (1st party) packages, such as fortify, rely on this event by either dispatching it or listening to it. That would mean I have to find a way to swap the event in these packages.

Conclusion: viable, but highly inconvenient

4. Overwrite the listener

I can "disable" the listener by creating a no-op listener and swapping it out in the container.

$this->app->bind(\Illuminate\Auth\Listeners\SendEmailVerificationNotification::class, \App\Listeners\Noop::class);

Conclusion: viable, but not so elegant

5. Patch Laravel

Use something like cweagans/composer-patches to patch the issue away.

Conclusion: viable, but 🤢

Context

We have a custom listener for the \Illuminate\Auth\Events\Registered event where we dispatch a job that, eventually, sends the email verification notification ($user->sendEmailVerificationNotification()), but first checks some prerequisites. We do this in a (delayed) job because the user has to be present in an external system before we can send the notification. This worked all fine, but after we upgraded to Laravel 11, users get two of these notifications. I tracked it down and found that this specific event and its listener are hard coded in the Laravel source in \Illuminate\Foundation\Support\Providers\EventServiceProvider::configureEmailVerification.

Related

Steps To Reproduce

  1. Create a listener for the \Illuminate\Auth\Events\Registered event;
  2. Send the email verification notification in that listener ($user->sendEmailVerificationNotification());
  3. Register a user;
  4. See you get two email verification notifications.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions