Repository: laravel/framework (php)

Issue:
SES v2 Transport - ReplyTo address incorrectly configured
### Laravel Version

9.52.9 - All versions will be impacted

### PHP Version

8.0

### Database Driver & Version

_No response_

### Description

SESv2 mail transport is incorrectly configuring the reply to address to be the email from address.
This seems to have come about as the SES v2 API method that's now being used is called `sendEmail` and I suspect when this new transport was created a number of items were copied over from the original transport class without updating them.


This is affecting all Versions of Laravel and anyone using the SES v2 transport.

### Steps To Reproduce

Create and send an email via the ses-v2 transport.
The received email will have the optional reply-to address set to the sender address.

If a reply-to the address has been specified it will be ignored.

Pull request:
[9.x] Fix SES V2 Transport "reply to" addresses
<!--
Please only send a pull request to branches that are currently supported: https://laravel.com/docs/releases#support-policy 

If you are unsure which branch your pull request should be sent to, please read: https://laravel.com/docs/contributions#which-branch

Pull requests without a descriptive title, thorough description, or tests will be closed.

In addition, please describe the benefit to end users; the reasons it does not break any existing features; how it makes building web applications easier, etc.
-->

When I added the `SesV2Transport` a few months back, I used the `ReplyToAddresses` attribute to define the sender of the message. This always set the sender as "reply to" address and prevented user-defined addresses to be applied.

Closes #47512.


Patch:
diff --git a/src/Illuminate/Mail/Transport/SesV2Transport.php b/src/Illuminate/Mail/Transport/SesV2Transport.php
index 4157570e5b..5cc3936d85 100644
--- a/src/Illuminate/Mail/Transport/SesV2Transport.php
+++ b/src/Illuminate/Mail/Transport/SesV2Transport.php
@@ -60,7 +60,7 @@ protected function doSend(SentMessage $message): void
             $result = $this->ses->sendEmail(
                 array_merge(
                     $options, [
-                        'ReplyToAddresses' => [$message->getEnvelope()->getSender()->toString()],
+                        'Source' => $message->getEnvelope()->getSender()->toString(),
                         'Destination' => [
                             'ToAddresses' => collect($message->getEnvelope()->getRecipients())
                                     ->map


Test patch:
diff --git a/tests/Mail/MailSesTransportTest.php b/tests/Mail/MailSesTransportTest.php
index 74598c6b61..f21b725647 100755
--- a/tests/Mail/MailSesTransportTest.php
+++ b/tests/Mail/MailSesTransportTest.php
@@ -11,6 +11,7 @@
 use Mockery as m;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\Mailer\Header\MetadataHeader;
+use Symfony\Component\Mime\Address;
 use Symfony\Component\Mime\Email;
 
 class MailSesTransportTest extends TestCase
@@ -56,6 +57,7 @@ public function testSend()
         $message->sender('myself@example.com');
         $message->to('me@example.com');
         $message->bcc('you@example.com');
+        $message->replyTo(new Address('taylor@example.com', 'Taylor Otwell'));
         $message->getHeaders()->add(new MetadataHeader('FooTag', 'TagValue'));
 
         $client = m::mock(SesClient::class);
@@ -68,7 +70,8 @@ public function testSend()
             ->with(m::on(function ($arg) {
                 return $arg['Source'] === 'myself@example.com' &&
                     $arg['Destinations'] === ['me@example.com', 'you@example.com'] &&
-                    $arg['Tags'] === [['Name' => 'FooTag', 'Value' => 'TagValue']];
+                    $arg['Tags'] === [['Name' => 'FooTag', 'Value' => 'TagValue']] &&
+                    strpos($arg['RawMessage']['Data'], 'Reply-To: Taylor Otwell <taylor@example.com>') !== false;
             }))
             ->andReturn($sesResult);
 
diff --git a/tests/Mail/MailSesV2TransportTest.php b/tests/Mail/MailSesV2TransportTest.php
index 692ab53791..c95a01440e 100755
--- a/tests/Mail/MailSesV2TransportTest.php
+++ b/tests/Mail/MailSesV2TransportTest.php
@@ -11,6 +11,7 @@
 use Mockery as m;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\Mailer\Header\MetadataHeader;
+use Symfony\Component\Mime\Address;
 use Symfony\Component\Mime\Email;
 
 class MailSesV2TransportTest extends TestCase
@@ -56,6 +57,7 @@ public function testSend()
         $message->sender('myself@example.com');
         $message->to('me@example.com');
         $message->bcc('you@example.com');
+        $message->replyTo(new Address('taylor@example.com', 'Taylor Otwell'));
         $message->getHeaders()->add(new MetadataHeader('FooTag', 'TagValue'));
 
         $client = m::mock(SesV2Client::class);
@@ -66,10 +68,10 @@ public function testSend()
             ->andReturn('ses-message-id');
         $client->shouldReceive('sendEmail')->once()
             ->with(m::on(function ($arg) {
-                return count($arg['ReplyToAddresses']) === 1 &&
-                    $arg['ReplyToAddresses'][0] === 'myself@example.com' &&
+                return $arg['Source'] === 'myself@example.com' &&
                     $arg['Destination']['ToAddresses'] === ['me@example.com', 'you@example.com'] &&
-                    $arg['Tags'] === [['Name' => 'FooTag', 'Value' => 'TagValue']];
+                    $arg['Tags'] === [['Name' => 'FooTag', 'Value' => 'TagValue']] &&
+                    strpos($arg['Content']['Raw']['Data'], 'Reply-To: Taylor Otwell <taylor@example.com>') !== false;
             }))
             ->andReturn($sesResult);