Magmatic
Magmatic

Reputation: 1951

How to send a plain text email in Laravel 8 without using a blade?

How can I send a plain text email in Laravel 8 without using a blade?

All our email messages and templates are stored in a database, so using a blade is not applicable to us. I just want to pass in text to send.

Thanks.

Upvotes: 4

Views: 6333

Answers (3)

Magmatic
Magmatic

Reputation: 1951

This is what I ended up doing, and I think it's a good solution.

I created a generic Mailable class called app\Mail\Message.php.

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class Message extends Mailable {
    use Queueable, SerializesModels;

    private $theSubject;
    private $htmlBody;
    private $fromAddress;
    private $theAttachments;
    private $replyToEmail;

    public function __construct($subject, $htmlBody, $fromAddress, $replyTo=null, $attachments=null) {
        $this->theSubject = $subject;
        $this->htmlBody = $htmlBody;
        $this->fromAddress = $fromAddress;
        $this->theAttachments = $attachments;
        $this->replyToEmail = $replyTo;
    }

    public function getBody() {
        return $this->htmlBody;
    }


    public function build() {
        $this->subject($this->theSubject);
        $this->from($this->fromAddress);
        $this->html($this->htmlBody);

        if ($this->replyToEmail != null) {
            $this->replyTo($this->replyToEmail);
        }

        // more info here: https://laravel.com/docs/8.x/mail#attachments
        if ($this->theAttachments != null) {
            foreach($this->theAttachments as $attachment) {
                if (is_array($attachment)) {
                    $this->attach($attachment[0], [                     // $attachment[0] = temp file path
                        'as'    =>  (isset($attachment[1]) ? $attachment[1]:null),  // $attachment[1] = filename
                        'mime'  =>  (isset($attachment[2]) ? $attachment[2]:null),  // $attachment[2] = mime type
                    ]);
                } else {
                    $this->attach($attachment);     // $attachment = temp file path
                }
            }
        }
        
        return $this;
    }
}

To send an email, I do this:

$message = new Message($subject, $fullBody, $fromAddress, $replyTo, $attachments);
Mail::to($address)->send($message);

To test sending email, I do this:

Mail::fake();
Mail::assertNothingSent();

// do something that sends an email...

Mail::assertSent(Message::class, function($email) {
    $token = // get something that should be found in the body

    $email->build();
    $allGood = true;
    $allGood &= $email->subject === 'Password Recovery';
    $allGood &= str_contains($email->getBody(), $token);
    return $allGood;
});

Upvotes: 2

Tanner
Tanner

Reputation: 868

I think you might be better of creating a Notification class that sends via mail. You can generate a notification with php artisan make:notification OrderShipped And by default its via method will send by mail, and will use Laravels default mail templates. In the toMail you can send whatever is needed. Then for your tests you can do:

public function testUserGetNotifiedIfOrderShipped())
{
    Notification::fake();

    // Hit some endpoints thats will send notification

    // Assert Admin gets notification
    Notification::assertSentTo(User::first(), OrderShipped::class);
}

Upvotes: 0

Aniket Das
Aniket Das

Reputation: 398

Mail::raw('This is a simple text', function ($m) {
  $m->to('[email protected]')->subject('Email Subject');
});

Don't forget to include

use Mail;

Upvotes: 5

Related Questions