phplaravelemailamazon-ses

Email Send using AWS SES in Laravel


I tried to send email using AWS SES SMTP and this is how I did.

.env

MAIL_MAILER=smtp
MAIL_HOST=email-smtp.{AWS_REGION}.amazonaws.com
MAIL_PORT=587
MAIL_USERNAME="${AWS_SES_USER_NAME}"
MAIL_PASSWORD="${AWS_SES_USER_PASS}"
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"

Code to send email

Mail::raw('This is email test', function ($email_message) {
    $email_message->from('FROM_EMAIL', 'FROM_NAME');
    $email_message->to('TO_EMAIL');
    $email_message->subject('Email Test');
    $email_message->setBody('This is email test', 'text/html');
});

After run above code, I got this error

TypeError: Symfony\Component\Mime\Message::setBody(): Argument #1 ($body) must be of type ?Symfony\Component\Mime\Part\AbstractPart, string given, called in E:\PetCheck\laravel-api\vendor\laravel\framework\src\Illuminate\Support\Traits\ForwardsCalls.php on line 23 in file E:\PetCheck\laravel-api\vendor\symfony\mime\Message.php on line 45

I am using Laravel 10 and AWS SES Sandbox account.

Can anyone help me to fix this problem?


Solution

  • If you insist on using Mail::raw(...), remove the commented line:

    Mail::raw('This is email test', function ($email_message) {
        $email_message->from('${FROM_EMAIL}', '${FROM_NAME}');
        $email_message->to('${TO_EMAIL}');
        $email_message->subject('Email Test');
        //$email_message->setBody('This is email test', 'text/html');
    });
    

    HTML emails

    Alternatively, you can use another syntax for html emails:

    // Option 1
    Mail::html('This is email test', function ($email_message) {
        $email_message->from('${FROM_EMAIL}', '${FROM_NAME}');
        $email_message->to('${TO_EMAIL}');
        $email_message->subject('Email Test');
    });
    
    // Option 2
    Mail::send(['html' => new HtmlString('This is email test')], function ($email_message) {
        $email_message->from('${FROM_EMAIL}', '${FROM_NAME}');
        $email_message->to('${TO_EMAIL}');
        $email_message->subject('Email Test');
    });
    

    Recommended way

    The more expressive and flexible option in Laravel 10 is to create a custom class for your mail:

    php artisan make:mail TestEmail
    
    <?php
    
    namespace App\Mail;
    
    use Illuminate\Bus\Queueable;
    use Illuminate\Mail\Mailable;
    use Illuminate\Mail\Mailables\Content;
    use Illuminate\Mail\Mailables\Envelope;
    use Illuminate\Queue\SerializesModels;
    
    class TestEmail extends Mailable
    {
        use Queueable;
        use SerializesModels;
    
        public function envelope(): Envelope
        {
            return new Envelope(
                from: new Address('${FROM_EMAIL}', '${FROM_NAME}'),
                subject: 'Email Test',
            );
        }
    
        public function content(): Content
        {
            return new Content(
                view: 'mails.test', // This is relative to resources/views by default
            );
        }
    }
    

    Send the email:

    Mail::to('${TO_EMAIL}')->send(new TestEmail());