feat: ✨ handle Mailjet spam complaints via webhook
This commit is contained in:
parent
27d0c1fc21
commit
b04ca114ae
4 changed files with 93 additions and 25 deletions
32
app/Http/Controllers/Api/WebhookController.php
Normal file
32
app/Http/Controllers/Api/WebhookController.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Lib\Helpers\MailjetHelper;
|
||||
use App\Models\Brand;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class WebhookController extends Controller
|
||||
{
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handleMailjetWebhook(Request $request): \Illuminate\Http\Response
|
||||
{
|
||||
$data = $request->all();
|
||||
|
||||
if ($data["event"] === "spam") {
|
||||
$campaign = MailjetHelper::getCampaign($data["mj_campaign_id"]);
|
||||
if (!$campaign) { return; }
|
||||
|
||||
$brand = Brand::query()->where('newsletter_email', $campaign['FromEmail'])->first();
|
||||
if (!$brand) { return; }
|
||||
|
||||
MailjetHelper::unsubscribeContact($brand, $data["email"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,6 @@ namespace App\Jobs;
|
|||
|
||||
use App\Lib\Helpers\MailjetHelper;
|
||||
use App\Models\BrandContactList;
|
||||
use App\Models\CustomerInfo;
|
||||
use App\Models\SingleOptin;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Queue\Queueable;
|
||||
|
|
@ -22,8 +20,8 @@ class SyncEmailOptOuts implements ShouldQueue
|
|||
$contacts = MailjetHelper::getContactLists();
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
$listId = $contact['ID'];
|
||||
$brandModel = BrandContactList::query()->where('mailjet_list_id', $listId)->with('brand')->first();
|
||||
$listId = $contact['ID'];
|
||||
$brandModel = BrandContactList::query()->where('mailjet_list_id', $listId)->with('brand')->first();
|
||||
|
||||
if ($brandModel) {
|
||||
$unsubscribedContacts = MailjetHelper::getUnsubscribedContacts($listId, Carbon::now()->subDay());
|
||||
|
|
@ -33,27 +31,9 @@ class SyncEmailOptOuts implements ShouldQueue
|
|||
}
|
||||
|
||||
foreach ($unsubscribedContacts as $unsubscribedContact) {
|
||||
$contact = MailjetHelper::getContact($unsubscribedContact['ContactID']);
|
||||
$crmCustomer = CustomerInfo::getFromEmail($brandModel->brand, $contact[0]["Email"])->first();
|
||||
$contact = MailjetHelper::getContact($unsubscribedContact['ContactID']);
|
||||
|
||||
if ($crmCustomer) {
|
||||
$crmCustomer->opt_in = false;
|
||||
|
||||
if (!$crmCustomer->saveOrFail()) {
|
||||
throw new \Exception(sprintf('Optin status not changed for customer (%s) and brand (%d).', $crmCustomer->hashcode, $brandModel->brand->name));
|
||||
}
|
||||
} else {
|
||||
$singleOptin = SingleOptin::query()->where('email', $contact[0]['Email'])
|
||||
->whereHas('brand', function ($q) use ($brandModel) {
|
||||
$q->whereId($brandModel->brand->getKey());
|
||||
})->first();
|
||||
|
||||
if ($singleOptin) {
|
||||
if (!$singleOptin->delete()) {
|
||||
throw new \Exception(sprintf('SingleOptin (%s) not deleted for brand (%d).', $singleOptin->hashcode, $brandModel->brand->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
MailjetHelper::unsubscribeContact($brandModel->brand, $contact[0]["Email"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,32 @@
|
|||
|
||||
namespace App\Lib\Helpers;
|
||||
|
||||
use App\Models\Brand;
|
||||
use App\Models\CustomerInfo;
|
||||
use App\Models\SingleOptin;
|
||||
use Mailjet\Resources;
|
||||
|
||||
class MailjetHelper
|
||||
{
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param integer $campaignId
|
||||
* @return array
|
||||
*/
|
||||
public static function getCampaign(int $campaignId): array
|
||||
{
|
||||
$response = app('mailjetClient')->get(Resources::$Campaign, [
|
||||
'id' => $campaignId
|
||||
]);
|
||||
|
||||
if ($response->success()) {
|
||||
return $response->getData();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves contact lists
|
||||
*
|
||||
|
|
@ -106,7 +128,7 @@ class MailjetHelper
|
|||
|
||||
/**
|
||||
* Uploads a CSV file
|
||||
*
|
||||
*
|
||||
* @param integer $mailjetListId
|
||||
* @param string $csvFile
|
||||
* @return array
|
||||
|
|
@ -148,4 +170,35 @@ class MailjetHelper
|
|||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param \App\Models\Brand $brandModel
|
||||
* @param string $email
|
||||
* @return void
|
||||
*/
|
||||
public static function unsubscribeContact(Brand $brandModel, string $email): void
|
||||
{
|
||||
$crmCustomer = CustomerInfo::getFromEmail($brandModel, $email)->first();
|
||||
|
||||
if ($crmCustomer) {
|
||||
$crmCustomer->opt_in = false;
|
||||
|
||||
if (!$crmCustomer->saveOrFail()) {
|
||||
throw new \Exception(sprintf('Optin status not changed for customer (%s) and brand (%d).', $crmCustomer->hashcode, $brandModel->name));
|
||||
}
|
||||
} else {
|
||||
$singleOptin = SingleOptin::query()->where('email', $email)
|
||||
->whereHas('brand', function ($q) use ($brandModel) {
|
||||
$q->whereId($brandModel->getKey());
|
||||
})->first();
|
||||
|
||||
if ($singleOptin) {
|
||||
if (!$singleOptin->delete()) {
|
||||
throw new \Exception(sprintf('SingleOptin (%s) not deleted for brand (%d).', $singleOptin->hashcode, $brandModel->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use App\Http\Controllers\Api\V4\CustomerController as V4CustomerController;
|
|||
use App\Http\Controllers\Api\V4\OptinController as V4OptinController;
|
||||
use App\Http\Controllers\Api\V4\QuestionController as V4QuestionController;
|
||||
use App\Http\Controllers\Api\V4\StatsController as V4StatsController;
|
||||
use App\Http\Controllers\Api\WebhookController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|
|
@ -140,3 +141,5 @@ Route::prefix('v4')->name('apiV4.')->group(function () {
|
|||
Route::post('/claim', [V4ClaimController::class, 'store'])->name('claim.store');
|
||||
});
|
||||
});
|
||||
|
||||
Route::post('/webhook/mailjet', [WebhookController::class, 'handleMailjetWebhook'])->name('webhook.mailjet');
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue