wip process normal mailgun webhooks

This commit is contained in:
paulwer 2023-12-15 07:22:24 +01:00
parent 6df213956f
commit 58a7456087
3 changed files with 305 additions and 131 deletions

View File

@ -27,6 +27,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Mailgun\Mailgun;
use Postmark\PostmarkClient;
use Turbo124\Beacon\Facades\LightLogs;
@ -63,7 +64,7 @@ class ProcessMailgunWebhook implements ShouldQueue
return SystemLog::query()
->where('company_id', $this->invitation->company_id)
->where('type_id', SystemLog::TYPE_WEBHOOK_RESPONSE)
->whereJsonContains('log', ['MessageID' => $message_id])
->whereJsonContains('log', ['id' => $message_id])
->orderBy('id', 'desc')
->first();
@ -85,7 +86,7 @@ class ProcessMailgunWebhook implements ShouldQueue
{
MultiDB::findAndSetDbByCompanyKey($this->request['Tag']);
$this->invitation = $this->discoverInvitation($this->request['MessageID']);
$this->invitation = $this->discoverInvitation($this->request['message']['headers']['message-id']);
if (!$this->invitation) {
return;
@ -95,11 +96,12 @@ class ProcessMailgunWebhook implements ShouldQueue
$this->invitation->email_error = $this->request['Details'];
}
switch ($this->request['RecordType']) {
switch ($this->request['event'] ?? $this->request['severity']) {
case 'delivered':
return $this->processDelivery();
case 'permanent_fail':
case 'temporary_fail':
case 'failed':
case 'permanent':
case 'temporary':
return $this->processBounce();
case 'complained':
return $this->processSpamComplaint();
@ -112,40 +114,33 @@ class ProcessMailgunWebhook implements ShouldQueue
}
// {
// "Metadata": {
// "example": "value",
// "example_2": "value"
// "event": "opened",
// "id": "-laxIqj9QWubsjY_3pTq_g",
// "timestamp": 1377047343.042277,
// "log-level": "info",
// "recipient": "recipient@example.com",
// "geolocation": {
// "country": "US",
// "region": "Texas",
// "city": "Austin"
// },
// "RecordType": "Open",
// "FirstOpen": true,
// "Client": {
// "Name": "Chrome 35.0.1916.153",
// "Company": "Google",
// "Family": "Chrome"
// "tags": [],
// "campaigns": [],
// "user-variables": {},
// "ip": "111.111.111.111",
// "client-info": {
// "client-type": "mobile browser",
// "client-os": "iOS",
// "device-type": "mobile",
// "client-name": "Mobile Safari",
// "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B143",
// "bot": ""
// },
// "OS": {
// "Name": "OS X 10.7 Lion",
// "Company": "Apple Computer, Inc.",
// "Family": "OS X 10"
// "message": {
// "headers": {
// "message-id": "20130821005614.19826.35976@samples.mailgun.org"
// }
// },
// "Platform": "WebMail",
// "UserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
// "ReadSeconds": 5,
// "Geo": {
// "CountryISOCode": "RS",
// "Country": "Serbia",
// "RegionISOCode": "VO",
// "Region": "Autonomna Pokrajina Vojvodina",
// "City": "Novi Sad",
// "Zip": "21000",
// "Coords": "45.2517,19.8369",
// "IP": "188.2.95.4"
// },
// "MessageID": "00000000-0000-0000-0000-000000000000",
// "MessageStream": "outbound",
// "ReceivedAt": "2022-02-06T06:37:48Z",
// "Tag": "welcome-email",
// "Recipient": "john@example.com"
// }
private function processOpen()
@ -155,7 +150,7 @@ class ProcessMailgunWebhook implements ShouldQueue
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
$sl = $this->getSystemLog($this->request['MessageID']);
$sl = $this->getSystemLog($this->request['message']['headers']['message-id']);
if ($sl) {
$this->updateSystemLog($sl, $data);
@ -173,18 +168,54 @@ class ProcessMailgunWebhook implements ShouldQueue
}
// {
// "RecordType": "Delivery",
// "ServerID": 23,
// "MessageStream": "outbound",
// "MessageID": "00000000-0000-0000-0000-000000000000",
// "Recipient": "john@example.com",
// "Tag": "welcome-email",
// "DeliveredAt": "2021-02-21T16:34:52Z",
// "Details": "Test delivery webhook details",
// "Metadata": {
// "example": "value",
// "example_2": "value"
// }
// "event": "delivered",
// "id": "hK7mQVt1QtqRiOfQXta4sw",
// "timestamp": 1529692199.626182,
// "log-level": "info",
// "envelope": {
// "transport": "smtp",
// "sender": "sender@example.org",
// "sending-ip": "123.123.123.123",
// "targets": "john@example.com"
// },
// "flags": {
// "is-routed": false,
// "is-authenticated": false,
// "is-system-test": false,
// "is-test-mode": false
// },
// "delivery-status": {
// "tls": true,
// "mx-host": "aspmx.l.example.com",
// "code": 250,
// "description": "",
// "session-seconds": 0.4367079734802246,
// "utf8": true,
// "attempt-no": 1,
// "message": "OK",
// "certificate-verified": true
// },
// "message": {
// "headers": {
// "to": "team@example.org",
// "message-id": "20180622182958.1.48906CB188F1A454@exmple.org",
// "from": "sender@exmple.org",
// "subject": "Test Subject"
// },
// "attachments": [],
// "size": 586
// },
// "storage": {
// "url": "https://storage-us-west1.api.mailgun.net/v3/domains/...",
// "region": "us-west1",
// "key": "AwABB...",
// "env": "production"
// },
// "recipient": "john@example.com",
// "recipient-domain": "example.com",
// "campaigns": [],
// "tags": [],
// "user-variables": {}
// }
private function processDelivery()
{
@ -193,7 +224,7 @@ class ProcessMailgunWebhook implements ShouldQueue
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
$sl = $this->getSystemLog($this->request['MessageID']);
$sl = $this->getSystemLog($this->request['message']['headers']['message-id']);
if ($sl) {
$this->updateSystemLog($sl, $data);
@ -211,47 +242,66 @@ class ProcessMailgunWebhook implements ShouldQueue
}
// {
// "Metadata": {
// "example": "value",
// "example_2": "value"
// "event": "failed", || "temporary" || "permanent"
// "id": "pl271FzxTTmGRW8Uj3dUWw",
// "timestamp": 1529701969.818328,
// "log-level": "error",
// "severity": "permanent",
// "reason": "suppress-bounce",
// "envelope": {
// "sender": "john@example.org",
// "transport": "smtp",
// "targets": "joan@example.com"
// },
// "RecordType": "Bounce",
// "ID": 42,
// "Type": "HardBounce",
// "TypeCode": 1,
// "Name": "Hard bounce",
// "Tag": "Test",
// "MessageID": "00000000-0000-0000-0000-000000000000",
// "ServerID": 1234,
// "MessageStream": "outbound",
// "Description": "The server was unable to deliver your message (ex: unknown user, mailbox not found).",
// "Details": "Test bounce details",
// "Email": "john@example.com",
// "From": "sender@example.com",
// "BouncedAt": "2021-02-21T16:34:52Z",
// "DumpAvailable": true,
// "Inactive": true,
// "CanActivate": true,
// "Subject": "Test subject",
// "Content": "Test content"
// "flags": {
// "is-routed": false,
// "is-authenticated": true,
// "is-system-test": false,
// "is-test-mode": false
// },
// "delivery-status": {
// "attempt-no": 1,
// "message": "",
// "code": 605,
// "description": "Not delivering to previously bounced address",
// "session-seconds": 0.0
// },
// "message": {
// "headers": {
// "to": "joan@example.com",
// "message-id": "20180622211249.1.2A6098970A380E12@example.org",
// "from": "john@example.org",
// "subject": "Test Subject"
// },
// "attachments": [],
// "size": 867
// },
// "storage": {
// "url": "https://se.api.mailgun.net/v3/domains/example.org/messages/eyJwI...",
// "key": "eyJwI..."
// },
// "recipient": "slava@mailgun.com",
// "recipient-domain": "mailgun.com",
// "campaigns": [],
// "tags": [],
// "user-variables": {}
// }
private function processBounce()
{
$this->invitation->email_status = 'bounced';
$this->invitation->save();
$bounce = new EmailBounce(
$this->request['Tag'],
$this->request['From'],
$this->request['MessageID']
$this->request['tags']->implode(','),
$this->request['message']['headers']['from'],
$this->request['message']['headers']['message-id']
);
LightLogs::create($bounce)->send();
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
$sl = $this->getSystemLog($this->request['MessageID']);
$sl = $this->getSystemLog($this->request['message']['headers']['message-id']);
if ($sl) {
$this->updateSystemLog($sl, $data);
@ -265,29 +315,33 @@ class ProcessMailgunWebhook implements ShouldQueue
}
// {
// "Metadata": {
// "example": "value",
// "example_2": "value"
// "event": "opened",
// "id": "-laxIqj9QWubsjY_3pTq_g",
// "timestamp": 1377047343.042277,
// "log-level": "info",
// "recipient": "recipient@example.com",
// "geolocation": {
// "country": "US",
// "region": "Texas",
// "city": "Austin"
// },
// "tags": [],
// "campaigns": [],
// "user-variables": {},
// "ip": "111.111.111.111",
// "client-info": {
// "client-type": "mobile browser",
// "client-os": "iOS",
// "device-type": "mobile",
// "client-name": "Mobile Safari",
// "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B143",
// "bot": ""
// },
// "message": {
// "headers": {
// "message-id": "20130821005614.19826.35976@samples.mailgun.org"
// }
// },
// "RecordType": "SpamComplaint",
// "ID": 42,
// "Type": "SpamComplaint",
// "TypeCode": 100001,
// "Name": "Spam complaint",
// "Tag": "Test",
// "MessageID": "00000000-0000-0000-0000-000000000000",
// "ServerID": 1234,
// "MessageStream": "outbound",
// "Description": "The subscriber explicitly marked this message as spam.",
// "Details": "Test spam complaint details",
// "Email": "john@example.com",
// "From": "sender@example.com",
// "BouncedAt": "2021-02-21T16:34:52Z",
// "DumpAvailable": true,
// "Inactive": true,
// "CanActivate": false,
// "Subject": "Test subject",
// "Content": "Test content"
// }
private function processSpamComplaint()
{
@ -295,16 +349,16 @@ class ProcessMailgunWebhook implements ShouldQueue
$this->invitation->save();
$spam = new EmailSpam(
$this->request['Tag'],
$this->request['tags'],
$this->request['From'],
$this->request['MessageID']
$this->request['message']['headers']['message-id']
);
LightLogs::create($spam)->send();
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
$sl = $this->getSystemLog($this->request['MessageID']);
$sl = $this->getSystemLog($this->request['message']['headers']['message-id']);
if ($sl) {
$this->updateSystemLog($sl, $data);
@ -370,28 +424,30 @@ class ProcessMailgunWebhook implements ShouldQueue
private function fetchMessage(): array
{
if (strlen($this->request['MessageID']) < 1) {
if (strlen($this->request['message']['headers']['message-id']) < 1) {
return $this->default_response;
}
try {
$postmark = new PostmarkClient(config('services.postmark.token'));
$messageDetail = $postmark->getOutboundMessageDetails($this->request['MessageID']);
$mailgun = new Mailgun(config('services.mailgun.token'), config('services.mailgun.endpoint'));
$messageDetail = $mailgun->messages()->show($this->request['message']['headers']['message-id']);
$recipients = collect($messageDetail['recipients'])->flatten()->implode(',');
$subject = $messageDetail->subject ?? '';
$recipients = collect($messageDetail->getRecipients())->flatten()->implode(',');
$subject = $messageDetail->getSubject() ?? '';
$events = collect($messageDetail->messageevents)->map(function ($event) {
$events = collect($mailgun->events()->get(config('services.mailgun.domain'), [
"message-id" => $this->request['message']['headers']['message-id'],
])->getItems())->map(function ($event) {
return [
'bounce_id' => $event?->Details?->BounceID ?? '',
'recipient' => $event->Recipient ?? '',
'status' => $event->Type ?? '',
'delivery_message' => $event->Details->DeliveryMessage ?? $event->Details->Summary ?? '',
'server' => $event->Details->DestinationServer ?? '',
'server_ip' => $event->Details->DestinationIP ?? '',
'date' => \Carbon\Carbon::parse($event->ReceivedAt)->format('Y-m-d H:i:s') ?? '',
'bounce_id' => array_key_exists("id", $event) ? $event["id"] : '',
'recipient' => array_key_exists("recipient", $event) ? $event["recipient"] : '',
'status' => array_key_exists("delivery-status", $event) && array_key_exists("code", $event["delivery-status"]) ? $event["delivery-status"]["code"] : '',
'delivery_message' => array_key_exists("delivery-status", $event) && array_key_exists("message", $event["delivery-status"]) ? $event["delivery-status"]["message"] : (array_key_exists("delivery-status", $event) && array_key_exists("description", $event["delivery-status"]) ? $event["delivery-status"]["description"] : ''),
'server' => array_key_exists("delivery-status", $event) && array_key_exists("mx-host", $event["delivery-status"]) ? $event["delivery-status"]["mx-host"] : '',
'server_ip' => array_key_exists("ip", $event) ? $event["ip"] : '',
'date' => \Carbon\Carbon::parse($event["timestamp"])->format('Y-m-d H:i:s') ?? '',
];
})->toArray();

View File

@ -70,10 +70,12 @@
"league/fractal": "^0.20.0",
"league/omnipay": "^3.1",
"livewire/livewire": "^2.10",
"mailgun/mailgun-php": "^3.6",
"microsoft/microsoft-graph": "^1.69",
"mollie/mollie-api-php": "^2.36",
"nelexa/zip": "^4.0",
"nwidart/laravel-modules": "^10.0",
"nyholm/psr7": "^1.8",
"omnipay/paypal": "^3.0",
"payfast/payfast-php-sdk": "^1.1",
"phpoffice/phpspreadsheet": "^1.29",
@ -92,7 +94,7 @@
"sprain/swiss-qr-bill": "^4.3",
"square/square": "30.0.0.*",
"stripe/stripe-php": "^12",
"symfony/http-client": "^6.0",
"symfony/http-client": "^7.0",
"symfony/mailgun-mailer": "^6.1",
"symfony/postmark-mailer": "^6.1",
"turbo124/beacon": "^1.5",

146
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ef5c36f71295ade916c3b7084642f0b4",
"content-hash": "a1427d5a8467c0c3dffac544c6da5f65",
"packages": [
{
"name": "afosto/yaac",
@ -6071,6 +6071,67 @@
],
"time": "2023-06-21T14:59:35+00:00"
},
{
"name": "mailgun/mailgun-php",
"version": "v3.6.3",
"source": {
"type": "git",
"url": "https://github.com/mailgun/mailgun-php.git",
"reference": "3dbdc2f220fa64e78e903477efa22858c72509be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mailgun/mailgun-php/zipball/3dbdc2f220fa64e78e903477efa22858c72509be",
"reference": "3dbdc2f220fa64e78e903477efa22858c72509be",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"php-http/client-common": "^2.2.1",
"php-http/discovery": "^1.19",
"php-http/multipart-stream-builder": "^1.1.2",
"psr/http-client": "^1.0",
"webmozart/assert": "^1.9.1"
},
"require-dev": {
"nyholm/nsa": "^1.2.1",
"nyholm/psr7": "^1.3.1",
"phpunit/phpunit": "^9.3",
"squizlabs/php_codesniffer": "^3.7",
"symfony/http-client": "^5.4 || ^6.3"
},
"suggest": {
"nyholm/psr7": "PSR-7 message implementation",
"symfony/http-client": "HTTP client"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Mailgun\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Travis Swientek",
"email": "travis@mailgunhq.com"
}
],
"description": "The Mailgun SDK provides methods for all API functions.",
"support": {
"issues": "https://github.com/mailgun/mailgun-php/issues",
"source": "https://github.com/mailgun/mailgun-php/tree/v3.6.3"
},
"time": "2023-12-01T10:04:01+00:00"
},
{
"name": "markbaker/complex",
"version": "3.0.2",
@ -8012,6 +8073,62 @@
"abandoned": "psr/http-factory",
"time": "2023-04-14T14:16:17+00:00"
},
{
"name": "php-http/multipart-stream-builder",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/php-http/multipart-stream-builder.git",
"reference": "f5938fd135d9fa442cc297dc98481805acfe2b6a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/multipart-stream-builder/zipball/f5938fd135d9fa442cc297dc98481805acfe2b6a",
"reference": "f5938fd135d9fa442cc297dc98481805acfe2b6a",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0",
"php-http/discovery": "^1.15",
"psr/http-factory-implementation": "^1.0"
},
"require-dev": {
"nyholm/psr7": "^1.0",
"php-http/message": "^1.5",
"php-http/message-factory": "^1.0.2",
"phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3"
},
"type": "library",
"autoload": {
"psr-4": {
"Http\\Message\\MultipartStream\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com"
}
],
"description": "A builder class that help you create a multipart stream",
"homepage": "http://php-http.org",
"keywords": [
"factory",
"http",
"message",
"multipart stream",
"stream"
],
"support": {
"issues": "https://github.com/php-http/multipart-stream-builder/issues",
"source": "https://github.com/php-http/multipart-stream-builder/tree/1.3.0"
},
"time": "2023-04-28T14:10:22+00:00"
},
{
"name": "php-http/promise",
"version": "1.2.1",
@ -11378,28 +11495,27 @@
},
{
"name": "symfony/http-client",
"version": "v6.4.0",
"version": "v7.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client.git",
"reference": "5c584530b77aa10ae216989ffc48b4bedc9c0b29"
"reference": "c3e90d09b3c45a5d47170e81a712d51c352cbc68"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-client/zipball/5c584530b77aa10ae216989ffc48b4bedc9c0b29",
"reference": "5c584530b77aa10ae216989ffc48b4bedc9c0b29",
"url": "https://api.github.com/repos/symfony/http-client/zipball/c3e90d09b3c45a5d47170e81a712d51c352cbc68",
"reference": "c3e90d09b3c45a5d47170e81a712d51c352cbc68",
"shasum": ""
},
"require": {
"php": ">=8.1",
"php": ">=8.2",
"psr/log": "^1|^2|^3",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/http-client-contracts": "^3",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
"php-http/discovery": "<1.15",
"symfony/http-foundation": "<6.3"
"symfony/http-foundation": "<6.4"
},
"provide": {
"php-http/async-client-implementation": "*",
@ -11416,11 +11532,11 @@
"nyholm/psr7": "^1.0",
"php-http/httplug": "^1.0|^2.0",
"psr/http-client": "^1.0",
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/http-kernel": "^5.4|^6.0|^7.0",
"symfony/messenger": "^5.4|^6.0|^7.0",
"symfony/process": "^5.4|^6.0|^7.0",
"symfony/stopwatch": "^5.4|^6.0|^7.0"
"symfony/dependency-injection": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/messenger": "^6.4|^7.0",
"symfony/process": "^6.4|^7.0",
"symfony/stopwatch": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@ -11451,7 +11567,7 @@
"http"
],
"support": {
"source": "https://github.com/symfony/http-client/tree/v6.4.0"
"source": "https://github.com/symfony/http-client/tree/v7.0.0"
},
"funding": [
{
@ -11467,7 +11583,7 @@
"type": "tidelift"
}
],
"time": "2023-11-28T20:55:58+00:00"
"time": "2023-11-29T08:40:23+00:00"
},
{
"name": "symfony/http-client-contracts",