framework: Mailable not working with On-Demand Notifications

  • Laravel Version: 8.24.0
  • PHP Version: 7.4.14
  • Database Driver & Version: 10.5.8-MariaDB

Description:

When using a Mailable within toMail function of notification, email is not sent when sending an On-Demand notification

Steps To Reproduce:

  1. Create a notification using code in documentation
use App\Mail\InvoicePaid as InvoicePaidMailable;

/**
 * Get the mail representation of the notification.
 *
 * @param  mixed  $notifiable
 * @return Mailable
 */
public function toMail($notifiable)
{
    return (new InvoicePaidMailable($this->invoice))
                ->to($notifiable->email);
}
  1. Try to send On-Demand notification using code from documentation
Notification::route('mail', 'taylor@example.com')
            ->notify(new InvoicePaid($invoice));

Following error is raised:

Undefined property: Illuminate\Notifications\AnonymousNotifiable::$email 

Same when changing $notifiable->email to $notifiable->mail

Undefined property: Illuminate\Notifications\AnonymousNotifiable::$mail 

And when removing ->to($notifiable->email) (because On-Demand notification should handle mail from route property) there is no error but email is not sent.

public function toMail($notifiable)
{
    return (new InvoicePaidMailable($this->invoice));
}

Email is not send.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 21 (9 by maintainers)

Most upvoted comments

@gaetan-hexadog aaah I now indeed see what you mean.

I took a very very deep dive into all of this and came to the conclusion that this isn’t possible at all. When using a Mailable instead of MailMessage you should always explicitly define the recipients using the ->to method on the mailable even if you’re using on demand notifications.

I’ve sent a PR to the docs with an example for your specific use case that also explains the limitations of using Mailables vs MailMessages. I hope that helps: https://github.com/laravel/docs/pull/6816

In any case, the solution to your problem is the following one:


     use App\Mail\InvoicePaid as InvoicePaidMailable;
     use Illuminate\Notifications\AnonymousNotifiable;

     /**
      * Get the mail representation of the notification.
      *
      * @param  mixed  $notifiable
      * @return Mailable
      */
     public function toMail($notifiable)
     {
         $recipient = $notifiable instanceof AnonymousNotifiable
             ? $notifiable->routeNotificationFor('mail')
             : $notifiable->email;

         return (new InvoicePaidMailable($this->invoice))
                     ->to($recipient);
     }

Thanks a lot @driesvints for your time, the investigation you performed and the given solution (working like a charm).