Skip to content

Commit 2973d30

Browse files
committed
bug #38179 [Mailer] Mailjet - Allow using Reply-To with Mailjet API (t-richard)
This PR was squashed before being merged into the 5.2-dev branch. Discussion ---------- [Mailer] Mailjet - Allow using Reply-To with Mailjet API | Q | A | ------------- | --- | Branch? | master | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | none | License | MIT | Doc PR | none Using this bridge I got an error from Mailjet API given below and this PR fixes this issue. <details> <summary>Error from Mailjet</summary> ```json { "Messages": [ { "Status": "error", "Errors": [ { "ErrorIdentifier": "xxxx", "ErrorCode": "send-0011", "StatusCode": 400, "ErrorMessage": "Header cannot be customized using the \"Headers\" collection. Please use the dedicated property to set this header.", "ErrorRelatedTo": [ "Headers[\"Reply-To\"]" ] } ] } ] } ``` </details> As detailed in [the Mailjet API doc](https://dev.mailjet.com/email/reference/send-emails/index.html#v3_1_post_send), `ReplyTo` is a single email address whereas the `Symfony\Mime\Email` class allows for several emails in `ReplyTo`. I implemented the [same logic as the Sendgrid bridge](https://github.com/symfony/symfony/blob/0f5ac5dc8f944a719e7d71729c0a63e1cfc9c6b5/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php#L96) but added logging (I first thought about throwing an exception but this would reduce transport interchangeability). Note : `Reply-To` is not listed in the ["Forbidden headers" section of Mailjet's documentation](https://dev.mailjet.com/email/guides/send-api-v31/#add-email-headers) but the API response is clear about the expected input. Commits ------- 1ff3e29 [Mailer] Mailjet - Allow using Reply-To with Mailjet API
2 parents 28edd70 + 1ff3e29 commit 2973d30

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

src/Symfony/Component/Mailer/Bridge/Mailjet/Tests/Transport/MailjetApiTransportTest.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ public function getTransportData()
3838
public function testPayloadFormat()
3939
{
4040
$email = (new Email())
41-
->subject('Sending email to mailjet API');
41+
->subject('Sending email to mailjet API')
42+
->replyTo(new Address('qux@example.com', 'Qux'));
4243
$email->getHeaders()
4344
->addTextHeader('X-authorized-header', 'authorized')
4445
->addTextHeader('X-MJ-TemplateLanguage', 'forbidden'); // This header is forbidden
@@ -76,5 +77,31 @@ public function testPayloadFormat()
7677
$this->assertEquals('', $recipients[0]['Name']); // For Recipients, even if the name is filled, it is empty
7778
$this->assertEquals('baz@example.com', $recipients[1]['Email']);
7879
$this->assertEquals('', $recipients[1]['Name']);
80+
81+
$this->assertArrayHasKey('ReplyTo', $message);
82+
$replyTo = $message['ReplyTo'];
83+
$this->assertIsArray($replyTo);
84+
$this->assertEquals('qux@example.com', $replyTo['Email']);
85+
$this->assertEquals('Qux', $replyTo['Name']);
86+
}
87+
88+
public function testReplyTo()
89+
{
90+
$from = 'foo@example.com';
91+
$to = 'bar@example.com';
92+
$email = new Email();
93+
$email
94+
->from($from)
95+
->to($to)
96+
->replyTo(new Address('qux@example.com', 'Qux'), new Address('quux@example.com', 'Quux'));
97+
$envelope = new Envelope(new Address($from), [new Address($to)]);
98+
99+
$transport = new MailjetApiTransport(self::USER, self::PASSWORD);
100+
$method = new \ReflectionMethod(MailjetApiTransport::class, 'getPayload');
101+
$method->setAccessible(true);
102+
103+
$this->expectExceptionMessage('Mailjet\'s API only supports one Reply-To email, 2 given.');
104+
105+
$method->invoke($transport, $email, $envelope);
79106
}
80107
}

src/Symfony/Component/Mailer/Bridge/Mailjet/Transport/MailjetApiTransport.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Psr\Log\LoggerInterface;
1515
use Symfony\Component\Mailer\Envelope;
1616
use Symfony\Component\Mailer\Exception\HttpTransportException;
17+
use Symfony\Component\Mailer\Exception\TransportException;
1718
use Symfony\Component\Mailer\SentMessage;
1819
use Symfony\Component\Mailer\Transport\AbstractApiTransport;
1920
use Symfony\Component\Mime\Address;
@@ -29,7 +30,7 @@ class MailjetApiTransport extends AbstractApiTransport
2930
private const FORBIDDEN_HEADERS = [
3031
'Date', 'X-CSA-Complaints', 'Message-Id', 'X-Mailjet-Campaign', 'X-MJ-StatisticsContactsListID',
3132
'DomainKey-Status', 'Received-SPF', 'Authentication-Results', 'Received', 'X-Mailjet-Prio',
32-
'From', 'Sender', 'Subject', 'To', 'Cc', 'Bcc', 'Return-Path', 'Delivered-To', 'DKIM-Signature',
33+
'From', 'Sender', 'Subject', 'To', 'Cc', 'Bcc', 'Reply-To', 'Return-Path', 'Delivered-To', 'DKIM-Signature',
3334
'X-Feedback-Id', 'X-Mailjet-Segmentation', 'List-Id', 'X-MJ-MID', 'X-MJ-ErrorMessage',
3435
'X-MJ-TemplateErrorDeliver', 'X-MJ-TemplateErrorReporting', 'X-MJ-TemplateLanguage',
3536
'X-Mailjet-Debug', 'User-Agent', 'X-Mailer', 'X-MJ-CustomID', 'X-MJ-EventPayload', 'X-MJ-Vars',
@@ -106,6 +107,12 @@ private function getPayload(Email $email, Envelope $envelope): array
106107
if ($emails = $email->getBcc()) {
107108
$message['Bcc'] = $this->formatAddresses($emails);
108109
}
110+
if ($emails = $email->getReplyTo()) {
111+
if (1 < $length = \count($emails)) {
112+
throw new TransportException(sprintf('Mailjet\'s API only supports one Reply-To email, %d given.', $length));
113+
}
114+
$message['ReplyTo'] = $this->formatAddress($emails[0]);
115+
}
109116
if ($email->getTextBody()) {
110117
$message['TextPart'] = $email->getTextBody();
111118
}

0 commit comments

Comments
 (0)