spatie/laravel-mailcoach-ses-feedback
Add-on for spatie/laravel-mailcoach that processes Amazon SES feedback (bounces, complaints, deliveries) to keep campaign stats and subscriber status in sync. Designed to plug into Mailcoach and handle SES notifications automatically.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require spatie/laravel-mailcoach-ses-feedback
Publish the config file:
php artisan vendor:publish --provider="Spatie\MailcoachSesFeedback\MailcoachSesFeedbackServiceProvider"
Configure AWS SES:
Ensure your config/mailcoach-ses-feedback.php includes valid AWS credentials and SES region:
'aws' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
First Use Case: Run the feedback processor to fetch and process SES bounce/complaint notifications:
php artisan mailcoach:process-ses-feedback
Schedule this command in app/Console/Kernel.php:
$schedule->command('mailcoach:process-ses-feedback')->hourly();
config/mailcoach-ses-feedback.php (AWS settings, processing rules)artisan mailcoach:process-ses-feedback (core command)Spatie\MailcoachSesFeedback\Events\FeedbackProcessed (extendable hooks)SES Feedback Loop:
mailcoach:process-ses-feedback command to parse and update Mailcoach records.aws sns subscribe --topic-arn "arn:aws:sns:us-east-1:123456789012:mailcoach-feedback" --protocol sqs --notification-endpoint "https://sqs.us-east-1.amazonaws.com/123456789012/mailcoach-queue"
Campaign-Specific Processing:
campaignId config option:
'campaign_id' => env('MAILCOACH_CAMPAIGN_ID', null), // Process only this campaign
config/mailcoach-ses-feedback.php or per-command:
php artisan mailcoach:process-ses-feedback --campaign-id=123
Event-Driven Extensions:
FeedbackProcessed events to trigger custom logic (e.g., analytics, user notifications):
use Spatie\MailcoachSesFeedback\Events\FeedbackProcessed;
FeedbackProcessed::listen(function (FeedbackProcessed $event) {
// Log or act on processed feedback
Log::info('Processed feedback for email: ' . $event->email);
});
Batch Processing:
// In a custom command or service
$processor = app(\Spatie\MailcoachSesFeedback\FeedbackProcessor::class);
$processor->processFeedbackInBatches(100); // Process 100 records at a time
| Use Case | Implementation Pattern |
|---|---|
| Real-time feedback processing | Schedule mailcoach:process-ses-feedback via cron (e.g., every 5 minutes). |
| Campaign performance tracking | Extend FeedbackProcessed to update a custom campaign_performance table. |
| Automated suppression lists | Use FeedbackProcessed to add bounced/complained emails to a suppression_list table. |
| AWS SQS integration | Configure SES to publish feedback to SQS, then process via a queue worker. |
AWS Credentials:
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY).if (!app(\Spatie\MailcoachSesFeedback\FeedbackProcessor::class)->isAwsConfigured()) {
throw new \RuntimeException('AWS credentials not configured.');
}
SES Notification Format:
public function processFeedback(string $feedbackJson): void
{
$data = json_decode($feedbackJson, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \InvalidArgumentException('Invalid JSON feedback.');
}
// ... rest of processing
}
Duplicate Processing:
notificationId field to deduplicate:
// In your FeedbackProcessed listener
if (Feedback::where('notification_id', $event->notificationId)->exists()) {
return; // Skip duplicate
}
Timeouts:
$processor->processFeedbackInBatches(50); // AWS SES API limit is 100, but 50 is safer
Mailcoach Sync Issues:
if (!\Spatie\Mailcoach\Models\Email::where('email', $event->email)->exists()) {
Log::warning("Feedback for non-existent email: {$event->email}");
return;
}
Enable Verbose Logging:
php artisan mailcoach:process-ses-feedback --verbose
Or configure in config/mailcoach-ses-feedback.php:
'log_level' => 'debug',
Test with Mock SES:
Use the spatie/laravel-mailcoach-ses-feedback-mocker package to simulate feedback:
composer require --dev spatie/laravel-mailcoach-ses-feedback-mocker
Then run:
php artisan mailcoach:mock-ses-feedback
Check AWS SES Metrics:
Notifications Delivered metric in AWS CloudWatch for your SES topic.Custom Feedback Types:
Extend the FeedbackProcessor to handle non-standard SES feedback:
namespace App\Services;
use Spatie\MailcoachSesFeedback\FeedbackProcessor;
class CustomFeedbackProcessor extends FeedbackProcessor
{
protected function handleCustomFeedback(array $feedback): void
{
// Custom logic for non-bounce/complaint feedback
}
}
Database Observers:
Add observers to Spatie\MailcoachSesFeedback\Models\Feedback for real-time reactions:
use Spatie\MailcoachSesFeedback\Models\Feedback;
Feedback::observe(FeedbackObserver::class);
class FeedbackObserver
{
public function saved(Feedback $feedback)
{
if ($feedback->is_bounce) {
// Trigger suppression logic
}
}
}
Webhook Integration: Convert processed feedback into webhooks for third-party systems:
FeedbackProcessed::listen(function (FeedbackProcessed $event) {
Http::post('https://third-party-api.com/webhook', [
'email' => $event->email,
'status' => $event->type,
]);
});
Custom Feedback Storage:
Override the default Feedback model to store additional metadata:
namespace App\Models;
use Spatie\MailcoachSesFeedback\Models\Feedback;
class CustomFeedback extends Feedback
{
protected $casts = [
'custom_metadata' => 'array',
];
}
Then bind the model in AppServiceProvider:
\Spatie\MailcoachSesFeedback\FeedbackProcessor::setFeedbackModel(CustomFeedback::class);
AWS Region:
region in config/mailcoach-ses-feedback.php matches your SES endpoint.'region' => 'eu-central-1',
Notification Types:
bounce and complaint. Configure which to process:
'notification_types' => ['bounce', 'complaint'], // Default
Dry Runs:
How can I help you explore Laravel packages today?