8000 feature #50502 [RemoteEvent][Webhook] Add Mailjet support (blaugueux) · symfony/symfony@0ce5112 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0ce5112

Browse files
committed
feature #50502 [RemoteEvent][Webhook] Add Mailjet support (blaugueux)
This PR was merged into the 6.4 branch. Discussion ---------- [RemoteEvent][Webhook] Add Mailjet support | Q | A | ------------- | --- | Branch | 6.4 | Bug fix | no | New feature | yes | Deprecations | no | Tickets | | License | MIT | Doc PR | Commits ------- 7b0ed35 [Webhook][RemoteEvent] Add Mailjet support.
2 parents bb7a7dd + 7b0ed35 commit 0ce5112

20 files changed

+336
-1
lines changed

src/Symfony/Component/Mailer/Bridge/Mailjet/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
6.4
5+
---
6+
7+
* Add `RemoteEvent` and `Webhook` support
8+
49
6.3
510
---
611

src/Symfony/Component/Mailer/Bridge/Mailjet/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ where:
1818
- `ACCESS_KEY` is your Mailjet access key
1919
- `SECRET_KEY` is your Mailjet secret key
2020

21+
Webhook
22+
-------
23+
24+
When you [setup your webhook URL](https://app.mailjet.com/account/triggers) on Mailjet you must not group events by unchecking the checkboxes.
25+
2126
Resources
2227
---------
2328

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Bridge\Mailjet\RemoteEvent;
13+
14+
use Symfony\Component\RemoteEvent\Event\Mailer\AbstractMailerEvent;
15+
use Symfony\Component\RemoteEvent\Event\Mailer\MailerDeliveryEvent;
16+
use Symfony\Component\RemoteEvent\Event\Mailer\MailerEngagementEvent;
17+
use Symfony\Component\RemoteEvent\Exception\ParseException;
18+
use Symfony\Component\RemoteEvent\PayloadConverterInterface;
19+
20+
final class MailjetPayloadConverter implements PayloadConverterInterface
21+
{
22+
public function convert(array $payload): AbstractMailerEvent
23+
{
24+
if (\in_array($payload['event'], ['bounce', 'sent', 'blocked'], true)) {
25+
$name = match ($payload['event']) {
26+
'bounce' => MailerDeliveryEvent::BOUNCE,
27+
'sent' => MailerDeliveryEvent::DELIVERED,
28+
'blocked' => MailerDeliveryEvent::DROPPED,
29+
};
30+
31+
$event = new MailerDeliveryEvent($name, $payload['MessageID'], $payload);
32+
$event->setReason($this->getReason($payload));
33+
} else {
34+
$name = match ($payload['event']) {
35+
'click' => MailerEngagementEvent::CLICK,
36+
'open' => MailerEngagementEvent::OPEN,
37+
'spam' => MailerEngagementEvent::SPAM,
38+
'unsub' => MailerEngagementEvent::UNSUBSCRIBE,
39+
default => throw new ParseException(sprintf('Unsupported event "%s".', $payload['event'])),
40+
};
41+
$event = new MailerEngagementEvent($name, $payload['MessageID'], $payload);
42+
}
43+
44+
if (!$date = \DateTimeImmutable::createFromFormat('U', $payload['time'])) {
45+
throw new ParseException(sprintf('Invalid date "%s".', $payload['time']));
46+
}
47+
48+
$event->setDate($date);
49+
$event->setRecipientEmail($payload['email']);
50+
51+
if (isset($payload['CustomID'])) {
52+
$event->setTags([$payload['CustomID']]);
53+
}
54+
55+
if (isset($payload['Payload'])) {
56+
$event->setMetadata(['Payload' => $payload['Payload']]);
57+
}
58+
59+
return $event;
60+
}
61+
62+
private function getReason(array $payload): string
63+
{
64+
return $payload['smtp_reply'] ?? $payload['error_related_to'] ?? '';
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"event": "blocked",
3+
"time": 1430812195,
4+
"MessageID": 13792286917004336,
5+
"Message_GUID": "1ab23cd4-e567-8901-2345-6789f0gh1i2j",
6+
"email": "bounce@mailjet.com",
7+
"mj_campaign_id": 0,
8+
"mj_contact_id": 1000,
9+
"customcampaign": "",
10+
"CustomID": "helloworld",
11+
"Payload": "",
12+
"error_related_to": "mailjet",
13+
"error": "preblocked"
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
use Symfony\Component\RemoteEvent\Event\Mailer\MailerDeliveryEvent;
4+
5+
$wh = new MailerDeliveryEvent(MailerDeliveryEvent::DROPPED, '13792286917004336', json_decode(file_get_contents(str_replace('.php', '.json', __FILE__)), true, flags: JSON_THROW_ON_ERROR));
6+
$wh->setRecipientEmail('bounce@mailjet.com');
7+
$wh->setDate(\DateTimeImmutable::createFromFormat('U', 1430812195));
8+
$wh->setReason('mailjet');
9+
$wh->setTags(['helloworld']);
10+
$wh->setMetadata(['Payload' => '']);
11+
12+
return $wh;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"event": "bounce",
3+
"time": 1685525050,
4+
"MessageID": 104427216766056450,
5+
"Message_GUID": "5577705c-024a-472d-8918-29ef81a64738",
6+
"email": "event-bounce@yahoo.fr",
7+
"mj_campaign_id": 0,
8+
"mj_contact_id": 1000,
9+
"customcampaign": "",
10+
"blocked": false,
11+
"hard_bounce": false,
12+
"error_related_to": "policy issue",
13+
"error": "",
14+
"comment": "421 4.7.0 [TSS04] Messages from 87.253.233.123 temporarily deferred due to unexpected volume or user complaints - 4.16.55.1; see https://postmaster.yahooinc.com/error-codes",
15+
"CustomID": "helloworld",
16+
"Payload": ""
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
use Symfony\Component\RemoteEvent\Event\Mailer\MailerDeliveryEvent;
4+
5+
$wh = new MailerDeliveryEvent(MailerDeliveryEvent::BOUNCE, '104427216766056450', json_decode(file_get_contents(str_replace('.php', '.json', __FILE__)), true, flags: JSON_THROW_ON_ERROR));
6+
$wh->setRecipientEmail('event-bounce@yahoo.fr');
7+
$wh->setDate(\DateTimeImmutable::createFromFormat('U', 1685525050));
8+
$wh->setReason('policy issue');
9+
$wh->setTags(['helloworld']);
10+
$wh->setMetadata(['Payload' => '']);
11+
12+
return $wh;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"event": "click",
3+
"time": 1685519224,
4+
"MessageID": 93449692684977140,
5+
"Message_GUID": "245e4120-9d53-41b7-91f5-9aac8fda3cb0",
6+
"email": "event-click@hotmail.com",
7+
"mj_campaign_id": 0,
8+
"mj_contact_id": 1000,
9+
"customcampaign": "",
10+
"url": "https://mailjet.com",
11+
"ip": "127.0.0.1",
12+
"geo": "FR",
13+
"agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 CCleaner/113.0.21244.129",
14+
"CustomID": "helloworld",
15+
"Payload": ""
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
use Symfony\Component\RemoteEvent\Event\Mailer\MailerEngagementEvent;
4+
5+
$wh = new MailerEngagementEvent(MailerEngagementEvent::CLICK, '93449692684977140', json_decode(file_get_contents(str_replace('.php', '.json', __FILE__)), true, flags: JSON_THROW_ON_ERROR));
6+
$wh->setRecipientEmail('event-click@hotmail.com');
7+
$wh->setDate(\DateTimeImmutable::createFromFormat('U', 1685519224));
8+
$wh->setTags(['helloworld']);
9+
$wh->setMetadata(['Payload' => '']);
10+
11+
return $wh;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"event": "open",
3+
"time": 1685519055,
4+
"MessageID": 102175416994919440,
5+
"Message_GUID": "982f91f1-4417-4ab1-9777-a2410e1bde36",
6+
"email": "event-open@gmail.com",
7+
"mj_campaign_id": 0,
8+
"mj_contact_id": 1000,
9+
"customcampaign": "",
10+
"ip": "127.0.0.1",
11+
"geo": "EU",
12+
"agent": "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0 (via ggpht.com GoogleImageProxy)",
13+
"CustomID": "helloworld",
14+
"Payload": ""
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
use Symfony\Component\RemoteEvent\Event\Mailer\MailerEngagementEvent;
4+
5+
$wh = new MailerEngagementEvent(MailerEngagementEvent::OPEN, '102175416994919440', json_decode(file_get_contents(str_replace('.php', '.json', __FILE__)), true, flags: JSON_THROW_ON_ERROR));
6+
$wh->setRecipientEmail('event-open@gmail.com');
7+
$wh->setDate(\DateTimeImmutable::createFromFormat('U', 1685519055));
8+
$wh->setTags(['helloworld']);
9+
$wh->setMetadata(['Payload' => '']);
10+
11+
return $wh;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"event": "sent",
3+
"time": 1685518742,
4+
"MessageID": 92042317804662640,
5+
"Message_GUID": "5b4de5f5-63d0-44f3-b4bd-a34f222cb8af",
6+
"email": "event-sent@gmail.com",
7+
"mj_campaign_id": 0,
8+
"mj_contact_id": 1000,
9+
"customcampaign": "",
10+
"CustomID": "helloworld",
11+
"Payload": "",
12+
"smtp_reply": "250 2.0.0 OK 1685518742 k22-20020a05600c0b5600b003f6020d9976si8376621wmr.181 - gsmtp"
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
use Symfony\Component\RemoteEvent\Event\Mailer\MailerDeliveryEvent;
4+
5+
$wh = new MailerDeliveryEvent(MailerDeliveryEvent::DELIVERED, '92042317804662640', json_decode(file_get_contents(str_replace('.php', '.json', __FILE__)), true, flags: JSON_THROW_ON_ERROR));
6+
$wh->setRecipientEmail('event-sent@gmail.com');
7+
$wh->setDate(\DateTimeImmutable::createFromFormat('U', 1685518742));
8+
$wh->setReason('250 2.0.0 OK 1685518742 k22-20020a05600c0b5600b003f6020d9976si8376621wmr.181 - gsmtp');
9+
$wh->setTags(['helloworld']);
10+
$wh->setMetadata(['Payload' => '']);
11+
12+
return $wh;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"event": "spam",
3+
"time": 1430812195,
4+
"MessageID": 13792286917004336,
5+
"Message_GUID": "1ab23cd4-e567-8901-2345-6789f0gh1i2j",
6+
"email": "bounce@mailjet.com",
7+
"mj_campaign_id": 0,
8+
"mj_contact_id": 1000,
9+
"customcampaign": "",
10+
"CustomID": "helloworld",
11+
"Payload": "",
12+
"source": "JMRPP"
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
use Symfony\Component\RemoteEvent\Event\Mailer\MailerEngagementEvent;
4+
5+
$wh = new MailerEngagementEvent(MailerEngagementEvent::SPAM, '13792286917004336', json_decode(file_get_contents(str_replace('.php', '.json', __FILE__)), true, flags: JSON_THROW_ON_ERROR));
6+
$wh->setRecipientEmail('bounce@mailjet.com');
7+
$wh->setDate(\DateTimeImmutable::createFromFormat('U', 1430812195));
8+
$wh->setTags(['helloworld']);
9+
$wh->setMetadata(['Payload' => '']);
10+
11+
return $wh;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"event": "unsub",
3+
"time": 1433334941,
4+
"MessageID": 20547674933128000,
5+
"Message_GUID": "1ab23cd4-e567-8901-2345-6789f0gh1i2j",
6+
"email": "api@mailjet.com",
7+
"mj_campaign_id": 0,
8+
"mj_contact_id": 1000,
9+
"customcampaign": "",
10+
"CustomID": "helloworld",
11+
"Payload": "",
12+
"mj_list_id": 1,
13+
"ip": "127.0.0.1",
14+
"geo": "FR",
15+
"agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36"
16+
}
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
use Symfony\Component\RemoteEvent\Event\Mailer\MailerEngagementEvent;
4+
5+
$wh = new MailerEngagementEvent(MailerEngagementEvent::UNSUBSCRIBE, '20547674933128000', json_decode(file_get_contents(str_replace('.php', '.json', __FILE__)), true, flags: JSON_THROW_ON_ERROR));
6+
$wh->setRecipientEmail('api@mailjet.com');
7+
$wh->setDate(\DateTimeImmutable::createFromFormat('U', 1433334941));
8+
$wh->setTags(['helloworld']);
9+
$wh->setMetadata(['Payload' => '']);
10+
11+
return $wh;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Bridge\Mailjet\Tests\Webhook;
13+
14+
use Symfony\Component\Mailer\Bridge\Mailjet\RemoteEvent\MailjetPayloadConverter;
15+
use Symfony\Component\Mailer\Bridge\Mailjet\Webhook\MailjetRequestParser;
16+
use Symfony\Component\Webhook\Client\RequestParserInterface;
17+
use Symfony\Component\Webhook\Test\AbstractRequestParserTestCase;
18+
19+
class MailjetRequestParserTest extends AbstractRequestParserTestCase
20+
{
21+
protected function createRequestParser(): RequestParserInterface
22+
{
23+
return new MailjetRequestParser(new MailjetPayloadConverter());
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Bridge\Mailjet\Webhook;
13+
14+
use Symfony\Component\HttpFoundation\ChainRequestMatcher;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpFoundation\RequestMatcher\IsJsonRequestMatcher;
17+
use Symfony\Component\HttpFoundation\RequestMatcher\MethodRequestMatcher;
18+
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
19+
use Symfony\Component\Mailer\Bridge\Mailjet\RemoteEvent\MailjetPayloadConverter;
20+
use Symfony\Component\RemoteEvent\Event\Mailer\AbstractMailerEvent;
21+
use Symfony\Component\RemoteEvent\Exception\ParseException;
22+
use Symfony\Component\Webhook\Client\AbstractRequestParser;
23+
use Symfony\Component\Webhook\Exception\RejectWebhookException;
24+
25+
final class MailjetRequestParser extends AbstractRequestParser
26+
{
27+
public function __construct(
28+
private readonly MailjetPayloadConverter $converter,
29+
) {
30+
}
31+
32+
protected function getRequestMatcher(): RequestMatcherInterface
33+
{
34+
return new ChainRequestMatcher([
35+
new MethodRequestMatcher('POST'),
36+
new IsJsonRequestMatcher(),
37+
]);
38+
}
39+
40+
protected function doParse(Request $request, string $secret): ?AbstractMailerEvent
41+
{
42+
try {
43+
return $this->converter->convert($request->toArray());
44+
} catch (ParseException $e) {
45+
throw new RejectWebhookException(406, $e->getMessage(), $e);
46+
}
47+
}
48+
}

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"symfony/mailer": "^5.4.21|^6.2.7|^7.0"
2121
},
2222
"require-dev": {
23-
"symfony/http-client": "^5.4|^6.0|^7.0"
23+
"symfony/http-client": "^5.4|^6.0|^7.0",
24+
"symfony/webhook": "^6.4"
2425
},
2526
"autoload": {
2627
"psr-4": { "Symfony\\Component\\Mailer\\Bridge\\Mailjet\\": "" },

0 commit comments

Comments
 (0)
0