diff --git a/app/Jobs/PostMark/ProcessPostmarkWebhook.php b/app/Jobs/PostMark/ProcessPostmarkWebhook.php index d99455ab322e..1a04673afc40 100644 --- a/app/Jobs/PostMark/ProcessPostmarkWebhook.php +++ b/app/Jobs/PostMark/ProcessPostmarkWebhook.php @@ -11,27 +11,24 @@ namespace App\Jobs\PostMark; -use App\DataMapper\Analytics\Mail\EmailBounce; -use App\DataMapper\Analytics\Mail\EmailSpam; -use App\Jobs\Util\SystemLogger; +use App\Models\SystemLog; use App\Libraries\MultiDB; -use App\Models\Company; +use Postmark\PostmarkClient; +use Illuminate\Bus\Queueable; +use App\Jobs\Util\SystemLogger; +use App\Models\QuoteInvitation; use App\Models\CreditInvitation; use App\Models\InvoiceInvitation; -use App\Models\Payment; -use App\Models\PurchaseOrderInvitation; -use App\Models\QuoteInvitation; -use App\Models\RecurringInvoiceInvitation; -use App\Models\SystemLog; -use App\Notifications\Ninja\EmailBounceNotification; -use App\Notifications\Ninja\EmailSpamNotification; -use App\Utils\Ninja; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; -use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Turbo124\Beacon\Facades\LightLogs; +use App\Models\PurchaseOrderInvitation; +use Illuminate\Queue\InteractsWithQueue; +use App\Models\RecurringInvoiceInvitation; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; +use App\DataMapper\Analytics\Mail\EmailSpam; +use App\DataMapper\Analytics\Mail\EmailBounce; +use App\Notifications\Ninja\EmailSpamNotification; class ProcessPostmarkWebhook implements ShouldQueue { @@ -41,6 +38,16 @@ class ProcessPostmarkWebhook implements ShouldQueue public $invitation; + private array $default_response = [ + 'subject' => 'Message not found.', + 'status' => '', + 'recipient' => '', + 'type' => '', + 'delivery_message' => '', + 'server' => '', + 'server_ip' => '', + ]; + /** * Create a new job instance. * @@ -126,8 +133,10 @@ class ProcessPostmarkWebhook implements ShouldQueue $this->invitation->opened_date = now(); $this->invitation->save(); + $data = array_merge($this->request, ['history' => $this->fetchMessage()]); + (new SystemLogger( - $this->request, + $data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_OPENED, SystemLog::TYPE_WEBHOOK_RESPONSE, @@ -155,8 +164,10 @@ class ProcessPostmarkWebhook implements ShouldQueue $this->invitation->email_status = 'delivered'; $this->invitation->save(); + $data = array_merge($this->request, ['history' => $this->fetchMessage()]); + (new SystemLogger( - $this->request, + $data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_DELIVERY, SystemLog::TYPE_WEBHOOK_RESPONSE, @@ -204,7 +215,9 @@ class ProcessPostmarkWebhook implements ShouldQueue LightLogs::create($bounce)->send(); - (new SystemLogger($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); + $data = array_merge($this->request, ['history' => $this->fetchMessage()]); + + (new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); // if(config('ninja.notification.slack')) // $this->invitation->company->notification(new EmailBounceNotification($this->invitation->company->account))->ninja(); @@ -248,7 +261,9 @@ class ProcessPostmarkWebhook implements ShouldQueue LightLogs::create($spam)->send(); - (new SystemLogger($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); + $data = array_merge($this->request, ['history' => $this->fetchMessage()]); + + (new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); if (config('ninja.notification.slack')) { $this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja(); @@ -273,4 +288,33 @@ class ProcessPostmarkWebhook implements ShouldQueue return $invitation; } } + + private function fetchMessage(): array + { + if(strlen($this->request['MessageID']) < 1){ + return $this->default_response; + } + + try { + + $postmark = new PostmarkClient(config('services.postmark.secret')); + $messageDetail = $postmark->getOutboundMessageDetails($this->request['MessageID']); + + return [ + 'subject' => $messageDetail->subject ?? '', + 'status' => $messageDetail->status ?? '', + 'recipient' => $messageDetail->messageevents[0]['Recipient'] ?? '', + 'type' => $messageDetail->messageevents[0]->Type ?? '', + 'subject' => $messageDetail->messageevents[0]->Details->DeliveryMessage ?? '', + 'server' => $messageDetail->messageevents[0]->Details->DestinationServer ?? '', + 'server_ip' => $messageDetail->messageevents[0]->Details->DestinationIP ?? '', + ]; + + } + catch (\Exception $e) { + + return $this->default_response; + + } + } } diff --git a/app/Services/Client/EmailHistory.php b/app/Services/Client/EmailHistory.php new file mode 100644 index 000000000000..b279c6c5f2c6 --- /dev/null +++ b/app/Services/Client/EmailHistory.php @@ -0,0 +1,95 @@ + 'Message not found.', + 'status' => '', + 'recipient' => '', + 'type' => '', + 'subject' => '', + 'server' => '', + 'server_ip' => '', + ]; + + public function __construct(public Client $client) + { + } + + public function run(): array + { + // $settings = $this->client->getMergedSettings(); + + // if($settings->email_sending_method == 'default'){ + // $this->postmark_token = config('services.postmark.token'); + // } + // elseif($settings->email_sending_method == 'client_postmark'){ + // $this->postmark_token = $settings->postmark_secret; + // } + // else{ + // return []; + // } + + // $this->postmark = new PostmarkClient($this->postmark_token); + + return SystemLog::query() + ->where('client_id', $this->client->id) + ->where('category_id', SystemLog::CATEGORY_MAIL) + ->orderBy('id','DESC') + ->cursor() + ->map(function ($system_log) { + + if($system_log->log['history'] ?? false){ + return json_decode($system_log->log['history'],true); + } + })->toArray(); + } + + private function fetchMessage(string $message_id): array + { + if(strlen($message_id) < 1){ + return $this->default_response; + } + + try { + + $messageDetail = $this->postmark->getOutboundMessageDetails($message_id); + + return [ + 'subject' => $messageDetail->subject ?? '', + 'status' => $messageDetail->status ?? '', + 'recipient' => $messageDetail->messageevents[0]['Recipient'] ?? '', + 'type' => $messageDetail->messageevents[0]->Type ?? '', + 'delivery_message' => $messageDetail->messageevents[0]->Details->DeliveryMessage ?? '', + 'server' => $messageDetail->messageevents[0]->Details->DestinationServer ?? '', + 'server_ip' => $messageDetail->messageevents[0]->Details->DestinationIP ?? '', + ]; + + } + catch (\Exception $e) { + + return $this->default_response; + + } + } +} \ No newline at end of file diff --git a/app/Services/Email/Email.php b/app/Services/Email/Email.php index 4c114d586d31..cebb8b7b6f79 100644 --- a/app/Services/Email/Email.php +++ b/app/Services/Email/Email.php @@ -240,7 +240,6 @@ class Email implements ShouldQueue } if ($this->client_mailgun_secret) { - $mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain, $this->client_mailgun_endpoint); } @@ -254,6 +253,7 @@ class Email implements ShouldQueue LightLogs::create(new EmailSuccess($this->company->company_key)) ->send(); + } catch(\Symfony\Component\Mime\Exception\RfcComplianceException $e) { nlog("Mailer failed with a Logic Exception {$e->getMessage()}"); $this->fail(); diff --git a/composer.json b/composer.json index d9bb6348f79c..3204247f8398 100644 --- a/composer.json +++ b/composer.json @@ -76,6 +76,7 @@ "omnipay/paypal": "^3.0", "payfast/payfast-php-sdk": "^1.1", "pragmarx/google2fa": "^8.0", + "psr/http-message": "^1.0", "pusher/pusher-php-server": "^7.2", "razorpay/razorpay": "2.*", "sentry/sentry-laravel": "^3", @@ -96,7 +97,7 @@ "twilio/sdk": "^6.40", "webpatser/laravel-countries": "dev-master#75992ad", "wepay/php-sdk": "^0.3", - "psr/http-message": "^1.0" + "wildbit/postmark-php": "^4.0" }, "require-dev": { "php": "^8.1", diff --git a/composer.lock b/composer.lock index 31584f8b7590..accbb507064e 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "673ca66ddfdb05c3ea29012594a196d3", + "content-hash": "70ade0ea4925946765213166010b0f32", "packages": [ { "name": "adrienrn/php-mimetyper", @@ -14230,6 +14230,44 @@ "source": "https://github.com/wepay/PHP-SDK/tree/master" }, "time": "2017-01-21T07:03:26+00:00" + }, + { + "name": "wildbit/postmark-php", + "version": "v4.0.5", + "source": { + "type": "git", + "url": "https://github.com/ActiveCampaign/postmark-php.git", + "reference": "b71efba061de7cf7e1f853d211b1c5edce4e3c5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ActiveCampaign/postmark-php/zipball/b71efba061de7cf7e1f853d211b1c5edce4e3c5b", + "reference": "b71efba061de7cf7e1f853d211b1c5edce4e3c5b", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0|^7.0", + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Postmark\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The officially supported client for Postmark (http://postmarkapp.com)", + "support": { + "issues": "https://github.com/ActiveCampaign/postmark-php/issues", + "source": "https://github.com/ActiveCampaign/postmark-php/tree/v4.0.5" + }, + "time": "2023-02-03T15:00:17+00:00" } ], "packages-dev": [ diff --git a/lang/en/texts.php b/lang/en/texts.php index a00b5f151fc1..183cbf5c8c04 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -5158,8 +5158,7 @@ $LANG = array( 'unlinked_transaction' => 'Successfully unlinked transaction', 'view_dashboard_permission' => 'Allow user to access the dashboard, data is limited to available permissions', 'marked_sent_credits' => 'Successfully marked credits sent', - -); +); return $LANG;