spatie/laravel-mailcoach-mailgun-feedback
Add-on for spatie/laravel-mailcoach that processes Mailgun feedback for your email campaigns. Capture events like bounces, complaints, and other Mailgun webhooks to keep Mailcoach lists and stats in sync.
Installation
composer require spatie/laravel-mailcoach-mailgun-feedback
Publish the config file:
php artisan vendor:publish --provider="Spatie\MailcoachMailgunFeedback\MailcoachMailgunFeedbackServiceProvider"
Configuration
Update .env with your Mailgun API key and webhook URL:
MAILGUN_API_KEY=your_api_key
MAILGUN_WEBHOOK_URL=https://your-app.com/mailgun-webhook
Webhook Endpoint
Add the webhook route in routes/web.php:
Route::post('/mailgun-webhook', [\Spatie\MailcoachMailgunFeedback\MailgunFeedbackController::class, 'handle']);
First Use Case Trigger a Mailcoach campaign via Mailgun. The package will automatically process feedback (opens, clicks, bounces) when Mailgun sends webhook events.
Webhook Handling
opened, clicked, bounced) to your /mailgun-webhook endpoint.FeedbackProcessed event.Event Processing
FeedbackProcessed in an event handler:
use Spatie\MailcoachMailgunFeedback\Events\FeedbackProcessed;
public function handle(FeedbackProcessed $event) {
$feedback = $event->feedback;
// Log, update analytics, or trigger actions (e.g., unsubscribe)
}
Integration with Mailcoach
Mailcoach facade to fetch campaigns/recipients:
use Spatie\Mailcoach\Facades\Mailcoach;
$campaign = Mailcoach::campaigns()->find($feedback->campaign_id);
Batch Processing
FeedbackProcessed event:
event(new FeedbackProcessed($feedback))->toQueue();
Custom Feedback Types
Extend the Feedback model to add custom fields:
use Spatie\MailcoachMailgunFeedback\Models\Feedback;
class CustomFeedback extends Feedback {
protected $casts = [
'custom_field' => 'string',
];
}
Webhook Retries
Implement a retry mechanism for failed webhook deliveries using Laravel’s retry helper or a queue job.
Analytics Dashboard
Aggregate feedback data in a custom table (e.g., feedback_stats) for reporting:
Feedback::query()
->where('event_type', 'opened')
->groupBy('campaign_id')
->get(['campaign_id', \DB::raw('count(*) as opens')]);
Webhook Signature Validation
X-Mailgun-Signature header. Ensure your .env has:
MAILGUN_WEBHOOK_SECRET=your_webhook_signing_key
X-Mailgun-Timestamp and X-Mailgun-Signature headers manually.Timezone Mismatches
$feedback->created_at = $feedback->created_at->setTimezone('Europe/Amsterdam');
Duplicate Events
feedback->event_id to deduplicate:
if (!Feedback::where('event_id', $feedback->event_id)->exists()) {
Feedback::create($feedbackData);
}
Rate Limiting
php artisan queue:work --sleep=3 --tries=3
Testing Webhooks
curl:
curl -X POST https://your-app.com/mailgun-webhook \
-H "X-Mailgun-Signature: YOUR_SIGNATURE" \
-H "X-Mailgun-Timestamp: 1234567890" \
-d 'event=opened&recipient=test@example.com'
Logging Feedback
\Log::debug('Mailgun feedback', ['data' => $request->all()]);
Extending Feedback Model
Feedback model to add custom logic:
namespace App\Models;
use Spatie\MailcoachMailgunFeedback\Models\Feedback as BaseFeedback;
class Feedback extends BaseFeedback {
protected static function booted() {
static::created(function ($feedback) {
// Trigger actions (e.g., send survey)
});
}
}
Performance Optimization
Feedback::insert($feedbackDataArray);
event_id, campaign_id, and recipient_email.Security
throttle middleware for abuse protection:
Route::post('/mailgun-webhook', [\Spatie\MailcoachMailgunFeedback\MailgunFeedbackController::class, 'handle'])
->middleware('throttle:100,1');
How can I help you explore Laravel packages today?