laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.46k stars 11.01k forks source link

unable to add 'Reply-To' header in Mailables #50378

Closed Jamiul-Bari closed 8 months ago

Jamiul-Bari commented 8 months ago

Laravel Version

10.46.0

PHP Version

8.2.16

Database Driver & Version

MySQL 8.0.27

Description

I cannot add a 'Reply-To' header in Mailables since I want to send the email as a reply to a previous mail (I have the message-id of the last mail).

It gives the following error, which I believe should be handled by the framework or mentioned in the docs since I need to use Symfony-specific objects

local.ERROR: The "Reply-To" header must be an instance of "Symfony\Component\Mime\Header\MailboxListHeader" (got "Symfony\Component\Mime\Header\UnstructuredHeader"). {"exception":"[object] (Symfony\\Component\\Mime\\Exception\\LogicException(code: 0): The \"Reply-To\" header must be an instance of \"Symfony\\Component\\Mime\\Header\\MailboxListHeader\" (got \"Symfony\\Component\\Mime\\Header\\UnstructuredHeader\"). at /Users/jamiul_bari/Sites/name/vendor/symfony/mime/Header/Headers.php:244)

Steps To Reproduce

create a mailable

php artisan make:mail GreetingMail
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Mail\Mailables\Headers;
use Illuminate\Queue\SerializesModels;

class GreetingEmail extends Mailable {
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     */
    public function __construct( public string $emailMessageId, public string $clientName, public string $clientMail, public string $name, public string $mail ) {}

    /**
     * Get the message envelope.
     */
    public function envelope(): Envelope {
        return new Envelope(
            from: new Address( $this->mail, $this-name ),
            to: [new Address( $this->clientMail, $this->clientName )],
            cc: [new Address( $this->mail, $this->name )],
            subject: "Greeting Email",
        );
    }

    /**
     * Get the message headers.
     */
    public function headers(): Headers {
        $references = [];
        $text       = [];

        if ( strlen( $this->emailMessageId ) > 0 ) {
            $references[]     = $this->emailMessageId;
            $text['Reply-To'] = $this->emailMessageId;
        }

        return new Headers(
            references: $references,
            text: $text,
        );
    }

    /**
     * Get the message content definition.
     */
    public function content(): Content {
        return new Content(
            view: 'emails.view',
        );
    }

    /**
     * Get the attachments for the message.
     *
     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
     */
    public function attachments(): array {
        return [];
    }
}
Cbrad24 commented 8 months ago

Hi @Jamiul-Bari,

You make reference to the Reply-To email header, which is already supported by Laravel in the envelope() function as shown by this snippet in the docs:

return new Envelope(
    from: new Address('jeffrey@example.com', 'Jeffrey Way'),
    replyTo: [
        new Address('taylor@example.com', 'Taylor Otwell'),
    ],
    subject: 'Order Shipped',
);

Judging by what information you gave however, it seems you in fact want the In-Reply-To email header to reference the previous email, also known in some mail clients as email "Threads".

The following code should work for you:

public function headers(): Headers
{
    if (empty($this->emailMessageId)) {
        return new Headers();
    }

    return new Headers(
        references: [$this->emailMessageId],
        text: [
            'In-Reply-To' => $this->emailMessageId,
        ],
    );
}
driesvints commented 8 months ago

Thanks @Cbrad24