File: /home/xedaptot/ai.naniguide.com/app/Http/Controllers/DeliveryController.php
<?php
namespace App\Http\Controllers;
use App\Library\StringHelper;
use App\Model\BounceLog;
use App\Model\Customer;
use App\Model\FeedbackLog;
use App\Model\TrackingLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
/**
* Wave F: legacy `notify()` endpoint + vendor-specific `handleAws/handleSendGrid`
* private methods deleted — vendor webhook ingestion lives in
* `SendingServerWebhookController::handle()` (route `webhook.handle`) which
* dispatches via the driver's `parseWebhook()` + listener fan-out.
*
* The `report()` endpoint remains — it is a generic third-party API
* (event=bounce|feedback) that does NOT depend on a specific vendor driver,
* so it is not part of the polymorphism rewrite.
*/
class DeliveryController extends Controller
{
/**
* Receive bounce/feedback report via API.
*/
public function report(Request $request)
{
$params = $request->all();
$rules = [
'event' => 'required|in:bounce,feedback',
'message_id' => 'required',
];
$msg = [
'event.in' => 'Invalid event. Possible values are: bounce, feedback',
'bounce_type.in' => 'Invalid bounce type. Possible values are: hard, soft',
'feedback_type.in' => 'Invalid feedback type. Possible values are: spam, abuse',
];
$validation = Validator::make($params, $rules, $msg);
$validation->sometimes('bounce_type', 'required|in:hard,soft', function ($input) {
return $input->event == 'bounce';
});
$validation->sometimes('feedback_type', 'required|in:spam,abuse', function ($input) {
return $input->event == 'feedback';
});
if ($validation->fails()) {
return response()->json(['error' => $validation->errors()->toArray()], 400);
}
$msgId = StringHelper::cleanupMessageId($params['message_id']);
$customer = Customer::getCustomerFromKey('runtime_message_id', $msgId);
if ($customer) {
$customer->setUserDbConnection();
} else {
return response()->json(['status' => 'failed', 'error' => 'Cannot find customer for message ID ' . $msgId], 400);
}
$trackingLog = TrackingLog::where('runtime_message_id', $msgId)->first();
if ($params['event'] == 'feedback') {
$feedbackLog = new FeedbackLog();
$feedbackLog->runtime_message_id = $msgId;
if ($trackingLog) {
$feedbackLog->tracking_log_id = $trackingLog->id;
}
$feedbackLog->message_id = $feedbackLog->runtime_message_id;
$feedbackLog->feedback_type = $params['feedback_type'];
$feedbackLog->raw_feedback_content = $params['response'] ?? '';
$feedbackLog->save();
Log::info('Feedback recorded (from API) for message ' . $feedbackLog->runtime_message_id);
$subscriber = $feedbackLog->findSubscriberByRuntimeMessageId();
if (!is_null($subscriber)) {
Log::info('Adding email to abuse list');
$subscriber->markAsSpamReported();
} else {
Log::warning('Subscriber not found');
}
} elseif ($params['event'] == 'bounce') {
$bounceLog = new BounceLog();
$bounceLog->runtime_message_id = $msgId;
if ($trackingLog) {
$bounceLog->tracking_log_id = $trackingLog->id;
}
$bounceLog->message_id = $bounceLog->runtime_message_id;
$bounceLog->bounce_type = $params['bounce_type'];
$bounceLog->raw = $params['response'] ?? '';
$bounceLog->save();
Log::info('Bounce recorded for message ' . $bounceLog->runtime_message_id);
$subscriber = $bounceLog->findSubscriberByRuntimeMessageId();
if (!is_null($subscriber)) {
Log::info('Adding email to blacklist');
$subscriber->sendToBlacklist($bounceLog->raw);
} else {
Log::warning('Subscriber not found');
}
}
return response()->json(['status' => 'ok'], 200);
}
}