Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

cconover's avatar

Plain text emails for notifications?

Is it possible to explicitly specify a plain text email template, and send both a formatted email and a plain text email, through the Notifications system? I have attempted to use the text() method on the MailMessage class, but apparently that method does not exist.

0 likes
7 replies
cconover's avatar
cconover
OP
Best Answer
Level 1

I solved my issue using the markdown method, since Markdown email templates create both a plain text and full HTML version.

yusukeokui's avatar

You can use view() instead of markdown().

    public function toMail($notifiable)
    {
        return (new MailMessage)
            ->subject('subject')
            ->view('emails.viewname', ['param' => $this->param]);
    }
igorsantos07's avatar

@yusukeokui that doesn't create a text-only part :P

@cconover, markdown() doesn't solve the matter if you have more complicated email templates (lucky you!)

I requested that text() should be included on MailMessage as well, but in the meantime, you can return a Mailable instead.

To make matters "simpler", I created a BareMail class to help on that, so you don't have to create separate classes just to configure a couple of commands (all Mailable methods are public anyway...):

class Welcome extends Notification {
    //[...]
    public function toMail(User $user) {
        return (new BareMail)
            ->to($user->email) //don't forget this!
            ->subject('Welcome to the app')
            ->view('emails.welcome', ['user' => $user])
            ->text('emails.welcome.text');
    }
}

class BareMail extends Mailable {
    use Queueable, SerializesModels;
    public function build() {}
}
lukas.pierce's avatar

You can create Mailable class and use it in notifications. And mailables supports plain text. Read more in official Laravel docs.

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);
}
onlime's avatar

Thanks @lukas.pierce for the hint. Using a Mailable is a decent workaround, but remember to use text() instead of view() to build a plain-text only email notification (if you don't want to provide a Content definition by overriding the Mailable):

class Welcome extends Notification {
    //[...]
    public function toMail(User $notifiable)
    {
        return (new Mailable)
            ->to($notifiable->email) // this is needed!
            ->subject('Welcome to the app')
            ->text('emails.welcome', ['user' => $user]);
    }
}

Like this, there is no need to extend/override Mailable.

But after all, I prefer using MailMessage instead of a Mailable in all notifications, so that the to is automatically applied as recipient, from the Notifiable's standard routeNotificationForMail() method (or from the default email field if you use a model as Notifiable and don't override this method) on MailChannel::getRecipients().

There is no MailMessage::text() method as mentioned by @igorsantos07 [Proposal] Add text/plain part to MailMessage.

Here's the crucial part which does not seem to be documented anywhere in Laravel docs:

So, if you want to use MailMessage for plain-text only notifications, just use an array as $view param in view() method, where you only fill text (your view template key) or raw (your pre-rendered plaintext body) like so:

class Welcome extends Notification {
    //[...]
    public function toMail(User $notifiable)
    {
        return (new MailMessage)
            ->subject('Welcome to the app')
            ->view(['text' => 'emails.welcome'], ['user' => $user])
            // ->view(['raw' => 'Some email body...']) // alternatively, if you want to provide pre-rendered text
            ->text('emails.welcome', ['user' => $user]);
    }
}

This definitely seems to be the simplest we can go to send out plain-text only email notifications, without reinventing the wheel. Hope this helps some others save some time, as I wasted way too much on it and that was actually a big pain point already 3yrs ago when I started with Laravel. Should really make it into the docs, this hidden feature! I might PR text() and raw() helper methods on MailMessage.

Cheers, Philip

arxeiss's avatar

I was facing something similar, here is my solution. Might be useful for some devs too.

I wanted to do similar thing. Every time notification is sent to "normal" email, I want to use all benefits of Markdown templates. But when it goes to Basecamp (adding as ticket) it must be plain text format. However, I don't want to define same email template twice, so I used this little hack with callback.

If email goes to Basecamp, I just remove HTML part, just before it is sent out.

class TripCreatedNotification extends Notification
{
    public function toMail(): MailMessage
    {
        return (new MailMessage())
            ->subject('subject')
            ->markdown('mail.trip.created', ['trip' => $this->trip])
            ->withSymfonyMessage(static function (Email $message): void {
                $goesToBasecamp = \collect($message->getTo())->first(
                    static fn ($to) => Str::match('#\@([0-9]+\.)basecamp\.com$#i', $to->getAddress()),
                );
                if ($goesToBasecamp) {
                    $message->html(null);
                }
            });
    }
}

Please or to participate in this conversation.