Skip to content

Commit d24f040

Browse files
committed
feature #37934 [Mailer] Mailjet Add ability to pass custom headers to API (tcheymol)
This PR was squashed before being merged into the 5.2-dev branch. Discussion ---------- [Mailer] Mailjet Add ability to pass custom headers to API | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | no | License | MIT | Doc PR | no Mailjet mailer now forwards headers from original email removes forbidden headers, and sends them to Maijlet Api Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - Never break backward compatibility (see https://symfony.com/bc). - Bug fixes must be submitted against the lowest maintained branch where they apply (lowest branches are regularly merged to upper ones so they get the fixes too.) - Features and deprecations must be submitted against branch master. --> Commits ------- 7b14ef3 [Mailer] Mailjet Add ability to pass custom headers to API
2 parents 6d521d4 + 7b14ef3 commit d24f040

File tree

4 files changed

+117
-1
lines changed

4 files changed

+117
-1
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
namespace Symfony\Component\Mailer\Bridge\Mailjet\Tests\Transport;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetApiTransport;
7+
use Symfony\Component\Mailer\Envelope;
8+
use Symfony\Component\Mime\Address;
9+
use Symfony\Component\Mime\Email;
10+
11+
class MailjetApiTransportTest extends TestCase
12+
{
13+
protected const USER = 'u$er';
14+
protected const PASSWORD = 'pa$s';
15+
16+
/**
17+
* @dataProvider getTransportData
18+
*/
19+
public function testToString(MailjetApiTransport $transport, string $expected)
20+
{
21+
$this->assertSame($expected, (string) $transport);
22+
}
23+
24+
public function getTransportData()
25+
{
26+
return [
27+
[
28+
new MailjetApiTransport(self::USER, self::PASSWORD),
29+
'mailjet+api://api.mailjet.com',
30+
],
31+
[
32+
(new MailjetApiTransport(self::USER, self::PASSWORD))->setHost('example.com'),
33+
'mailjet+api://example.com',
34+
],
35+
];
36+
}
37+
38+
public function testPayloadFormat()
39+
{
40+
$email = (new Email())
41+
->subject('Sending email to mailjet API');
42+
$email->getHeaders()
43+
->addTextHeader('X-authorized-header', 'authorized')
44+
->addTextHeader('X-MJ-TemplateLanguage', 'forbidden'); // This header is forbidden
45+
$envelope = new Envelope(new Address('foo@example.com', 'Foo'), [new Address('bar@example.com', 'Bar'), new Address('baz@example.com', 'Baz')]);
46+
47+
$transport = new MailjetApiTransport(self::USER, self::PASSWORD);
48+
$method = new \ReflectionMethod(MailjetApiTransport::class, 'getPayload');
49+
$method->setAccessible(true);
50+
$payload = $method->invoke($transport, $email, $envelope);
51+
52+
$this->assertArrayHasKey('Messages', $payload);
53+
$this->assertNotEmpty($payload['Messages']);
54+
55+
$message = $payload['Messages'][0];
56+
$this->assertArrayHasKey('Subject', $message);
57+
$this->assertEquals('Sending email to mailjet API', $message['Subject']);
58+
59+
$this->assertArrayHasKey('Headers', $message);
60+
$headers = $message['Headers'];
61+
$this->assertArrayHasKey('X-authorized-header', $headers);
62+
$this->assertEquals('authorized', $headers['X-authorized-header']);
63+
$this->assertArrayNotHasKey('x-mj-templatelanguage', $headers);
64+
$this->assertArrayNotHasKey('X-MJ-TemplateLanguage', $headers);
65+
66+
$this->assertArrayHasKey('From', $message);
67+
$sender = $message['From'];
68+
$this->assertArrayHasKey('Email', $sender);
69+
$this->assertArrayHasKey('Name', $sender);
70+
$this->assertEquals('foo@example.com', $sender['Email']);
71+
$this->assertEquals('Foo', $sender['Name']);
72+
73+
$this->assertArrayHasKey('To', $message);
74+
$recipients = $message['To'];
75+
$this->assertIsArray($recipients);
76+
$this->assertCount(2, $recipients);
77+
$this->assertEquals('bar@example.com', $recipients[0]['Email']);
78+
$this->assertEquals('', $recipients[0]['Name']); // For Recipients, even if the name is filled, it is empty
79+
$this->assertEquals('baz@example.com', $recipients[1]['Email']);
80+
$this->assertEquals('', $recipients[1]['Name']);
81+
}
82+
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Mailer\Bridge\Mailjet\Tests\Transport;
1313

14+
use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetApiTransport;
1415
use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetSmtpTransport;
1516
use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory;
1617
use Symfony\Component\Mailer\Test\TransportFactoryTestCase;
@@ -26,6 +27,11 @@ public function getFactory(): TransportFactoryInterface
2627

2728
public function supportsProvider(): iterable
2829
{
30+
yield [
31+
new Dsn('mailjet+api', 'default'),
32+
true,
33+
];
34+
2935
yield [
3036
new Dsn('mailjet', 'default'),
3137
true,
@@ -52,6 +58,16 @@ public function createProvider(): iterable
5258
$dispatcher = $this->getDispatcher();
5359
$logger = $this->getLogger();
5460

61+
yield [
62+
new Dsn('mailjet+api', 'default', self::USER, self::PASSWORD),
63+
new MailjetApiTransport(self::USER, self::PASSWORD, $this->getClient(), $dispatcher, $logger),
64+
];
65+
66+
yield [
67+
new Dsn('mailjet+api', 'example.com', self::USER, self::PASSWORD),
68+
(new MailjetApiTransport(self::USER, self::PASSWORD, $this->getClient(), $dispatcher, $logger))->setHost('example.com'),
69+
];
70+
5571
yield [
5672
new Dsn('mailjet', 'default', self::USER, self::PASSWORD),
5773
new MailjetSmtpTransport(self::USER, self::PASSWORD, $dispatcher, $logger),

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ class MailjetApiTransport extends AbstractApiTransport
2626
{
2727
private const HOST = 'api.mailjet.com';
2828
private const API_VERSION = '3.1';
29+
private const FORBIDDEN_HEADERS = [
30+
'Date', 'X-CSA-Complaints', 'Message-Id', 'X-Mailjet-Campaign', 'X-MJ-StatisticsContactsListID',
31+
'DomainKey-Status', 'Received-SPF', 'Authentication-Results', 'Received', 'X-Mailjet-Prio',
32+
'From', 'Sender', 'Subject', 'To', 'Cc', 'Bcc', 'Return-Path', 'Delivered-To', 'DKIM-Signature',
33+
'X-Feedback-Id', 'X-Mailjet-Segmentation', 'List-Id', 'X-MJ-MID', 'X-MJ-ErrorMessage',
34+
'X-MJ-TemplateErrorDeliver', 'X-MJ-TemplateErrorReporting', 'X-MJ-TemplateLanguage',
35+
'X-Mailjet-Debug', 'User-Agent', 'X-Mailer', 'X-MJ-CustomID', 'X-MJ-EventPayload', 'X-MJ-Vars',
36+
'X-Mailjet-TrackOpen', 'X-Mailjet-TrackClick', 'X-MJ-TemplateID', 'X-MJ-WorkflowID',
37+
];
2938

3039
private $privateKey;
3140
private $publicKey;
@@ -104,6 +113,14 @@ private function getPayload(Email $email, Envelope $envelope): array
104113
$message['HTMLPart'] = $html;
105114
}
106115

116+
foreach ($email->getHeaders()->all() as $header) {
117+
if (\in_array($header->getName(), self::FORBIDDEN_HEADERS, true)) {
118+
continue;
119+
}
120+
121+
$message['Headers'][$header->getName()] = $header->getBodyAsString();
122+
}
123+
107124
return [
108125
'Messages' => [$message],
109126
];

src/Symfony/Component/Mailer/Bridge/Mailjet/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
],
1818
"require": {
1919
"php": "^7.2.5",
20-
"symfony/mailer": "^4.4|^5.0"
20+
"symfony/mailer": "^4.4|^5.0",
21+
"symfony/mime": "^5.2"
2122
},
2223
"require-dev": {
2324
"symfony/http-client": "^4.4|^5.0"

0 commit comments

Comments
 (0)