Skip to content

Commit 301f18b

Browse files
Merge pull request #29 from vormkracht10/feature/suppressions-list
Suppressions list
2 parents 4e8ef97 + e8dfdf7 commit 301f18b

File tree

10 files changed

+124
-2
lines changed

10 files changed

+124
-2
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('mail_events', function (Blueprint $table): void {
15+
$table->timestamp('unsuppressed_at')
16+
->nullable()
17+
->after('occurred_at');
18+
});
19+
20+
Schema::table('mails', function (Blueprint $table): void {
21+
$table->string('mailer')
22+
->after('uuid');
23+
24+
$table->string('stream_id')
25+
->nullable()
26+
->after('mailer');
27+
});
28+
}
29+
};

src/Actions/LogMail.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,27 @@ public function getDefaultLogAttributes(MessageSending|MessageSent $event): arra
7474
];
7575
}
7676

77+
protected function getStreamId(MessageSending|MessageSent $event): ?string
78+
{
79+
if ($event->data['mailer'] !== 'postmark') {
80+
return null;
81+
}
82+
83+
if (null !== $messageStream = $event->message->getHeaders()->get('x-pm-message-stream')) {
84+
return $messageStream;
85+
}
86+
87+
return config('mail.mailers.postmark.message_stream_id', 'outbound');
88+
}
89+
7790
public function getMandatoryAttributes(MessageSending|MessageSent $event): array
7891
{
7992
return [
8093
'uuid' => $this->getCustomUuid($event),
8194
// 'mail_class' => $this->getMailClassHeaderValue($event),
8295
'sent_at' => $event instanceof MessageSent ? now() : null,
96+
'mailer' => $event->data['mailer'],
97+
'stream_id' => $this->getStreamId($event),
8398
];
8499
}
85100

@@ -101,7 +116,7 @@ protected function getCustomUuid(MessageSending|MessageSent $event): ?string
101116
protected function getAddressesValue(array $address): ?Collection
102117
{
103118
$addresses = collect($address)
104-
->flatMap(fn(Address $address) => [$address->getAddress() => $address->getName() === '' ? null : $address->getName()]);
119+
->flatMap(fn (Address $address) => [$address->getAddress() => $address->getName() === '' ? null : $address->getName()]);
105120

106121
return $addresses->count() > 0 ? $addresses : null;
107122
}

src/Drivers/MailgunDriver.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Vormkracht10\Mails\Drivers;
44

5+
use Illuminate\Http\Client\Response;
56
use Illuminate\Support\Facades\Http;
67
use Illuminate\Support\Facades\URL;
78
use Vormkracht10\Mails\Contracts\MailDriverContract;
@@ -78,7 +79,7 @@ public function verifyWebhookSignature(array $payload): bool
7879
return false;
7980
}
8081

81-
$hmac = hash_hmac('sha256', $payload['signature']['timestamp'] . $payload['signature']['token'], config('services.mailgun.webhook_signing_key'));
82+
$hmac = hash_hmac('sha256', $payload['signature']['timestamp'].$payload['signature']['token'], config('services.mailgun.webhook_signing_key'));
8283

8384
if (function_exists('hash_equals')) {
8485
return hash_equals($hmac, $payload['signature']['signature']);
@@ -127,4 +128,13 @@ public function dataMapping(): array
127128
'tag' => 'tags',
128129
];
129130
}
131+
132+
public function unsuppressEmailAddress(string $address): Response
133+
{
134+
$client = Http::asJson()
135+
->withBasicAuth('api', config('services.mailgun.secret'))
136+
->baseUrl(config('services.mailgun.endpoint').'/v3/');
137+
138+
return $client->delete(config('services.mailgun.domain').'/unsubscribes/'.$address);
139+
}
130140
}

src/Drivers/PostmarkDriver.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Vormkracht10\Mails\Drivers;
44

5+
use Illuminate\Http\Client\Response;
56
use Illuminate\Support\Facades\Http;
67
use Illuminate\Support\Facades\URL;
78
use Vormkracht10\Mails\Contracts\MailDriverContract;
@@ -139,4 +140,22 @@ public function dataMapping(): array
139140
'user_agent' => 'UserAgent',
140141
];
141142
}
143+
144+
public function unsuppressEmailAddress(string $address, $stream_id): Response
145+
{
146+
$client = Http::asJson()
147+
->withHeaders([
148+
'X-Postmark-Server-Token' => config('services.postmark.token'),
149+
])
150+
->baseUrl('https://api.postmarkapp.com/');
151+
152+
return $client->post('message-streams/'.$stream_id.'/suppressions/delete', [
153+
'Suppressions' => [
154+
[
155+
'emailAddress' => $address,
156+
],
157+
],
158+
]);
159+
160+
}
142161
}

src/Events/MailUnsuppressed.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Vormkracht10\Mails\Events;
4+
5+
use Illuminate\Broadcasting\InteractsWithSockets;
6+
use Illuminate\Foundation\Events\Dispatchable;
7+
use Illuminate\Queue\SerializesModels;
8+
9+
class MailUnsuppressed
10+
{
11+
use Dispatchable, InteractsWithSockets, SerializesModels;
12+
13+
/**
14+
* Create a new event instance.
15+
*/
16+
public function __construct(public string $emailAddress, public string $mailer, public ?string $stream_id = null) {}
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Vormkracht10\Mails\Listeners;
4+
5+
use Vormkracht10\Mails\Events\MailUnsuppressed;
6+
use Vormkracht10\Mails\Facades\MailProvider;
7+
8+
class UnsuppressEmailAddress
9+
{
10+
public function handle(MailUnsuppressed $event): void
11+
{
12+
MailProvider::with(driver: $event->mailer)
13+
->unsuppressEmailAddress(
14+
address: $event->emailAddress,
15+
stream_id: $event->stream_id ?? null
16+
);
17+
}
18+
}

src/MailsServiceProvider.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
use Vormkracht10\Mails\Contracts\MailProviderContract;
1515
use Vormkracht10\Mails\Events\MailEvent;
1616
use Vormkracht10\Mails\Events\MailHardBounced;
17+
use Vormkracht10\Mails\Events\MailUnsuppressed;
1718
use Vormkracht10\Mails\Listeners\AttachMailLogUuid;
1819
use Vormkracht10\Mails\Listeners\LogMailEvent;
1920
use Vormkracht10\Mails\Listeners\LogSendingMail;
2021
use Vormkracht10\Mails\Listeners\LogSentMail;
2122
use Vormkracht10\Mails\Listeners\NotifyOnBounce;
2223
use Vormkracht10\Mails\Listeners\StoreMailRelations;
24+
use Vormkracht10\Mails\Listeners\UnsuppressEmailAddress;
2325
use Vormkracht10\Mails\Managers\MailProviderManager;
2426

2527
class MailsServiceProvider extends PackageServiceProvider
@@ -35,6 +37,8 @@ public function registeringPackage(): void
3537
$this->app['events']->listen(MailHardBounced::class, NotifyOnBounce::class);
3638

3739
$this->app['events']->listen(MessageSending::class, StoreMailRelations::class);
40+
41+
$this->app['events']->listen(MailUnsuppressed::class, UnsuppressEmailAddress::class);
3842
}
3943

4044
public function bootingPackage(): void
@@ -53,6 +57,7 @@ public function configurePackage(Package $package): void
5357
'2_create_mail_attachments_table',
5458
'2_create_mail_events_table',
5559
'2_create_mailables_table',
60+
'3_add_unsuppressed_at_to_mail_events',
5661
)
5762
->hasRoutes('webhooks')
5863
->hasCommands(

src/Models/Mail.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class Mail extends Model
5151

5252
protected $fillable = [
5353
'uuid',
54+
'mailer',
55+
'stream_id',
5456
'mail_class',
5557
'subject',
5658
'html',
@@ -75,6 +77,8 @@ class Mail extends Model
7577
protected $casts = [
7678
'id' => 'integer',
7779
'uuid' => 'string',
80+
'mailer' => 'string',
81+
'stream_id' => 'string',
7882
'subject' => 'string',
7983
'from' => 'json',
8084
'reply_to' => 'json',

src/Models/MailEvent.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class MailEvent extends Model
4949
'tag',
5050
'payload',
5151
'occurred_at',
52+
'unsuppressed_at',
5253
];
5354

5455
protected $casts = [
@@ -57,6 +58,7 @@ class MailEvent extends Model
5758
'created_at' => 'datetime',
5859
'updated_at' => 'datetime',
5960
'occurred_at' => 'datetime',
61+
'unsuppressed_at' => 'datetime',
6062
];
6163

6264
public function getTable()

tests/TestCase.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,8 @@ public function getEnvironmentSetUp($app)
4444

4545
$migration = require __DIR__.'/../database/migrations/2_create_mailables_table.php.stub';
4646
$migration->up();
47+
48+
$migration = require __DIR__.'/../database/migrations/3_add_unsuppressed_at_to_mail_events.php.stub';
49+
$migration->up();
4750
}
4851
}

0 commit comments

Comments
 (0)