Initial commit
This commit is contained in:
143
references/MAIL_BOUNCE_SYSTEM.md
Normal file
143
references/MAIL_BOUNCE_SYSTEM.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Mail Bounce System Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
This system provides universal email bounce handling that works with any SMTP server by automatically intercepting all outgoing emails, checking for suppressed recipients, and processing bounce notifications from a dedicated mailbox.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Universal Protection**: Automatically protects ALL mailables (newsletters, contact forms, notifications, etc.)
|
||||
- **SMTP Server Agnostic**: Works with any SMTP server that supports Return-Path headers
|
||||
- **Threshold-Based Suppression**: Conservative approach with configurable bounce thresholds
|
||||
- **Multi-Profile Support**: Handles Users, Organizations, Banks, and Admins
|
||||
- **Email Verification Management**: Resets verification status based on bounce patterns
|
||||
- **Comprehensive Logging**: Tracks all bounce processing and suppression actions
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Outgoing Emails**: All emails automatically get Return-Path and tracking headers
|
||||
2. **Bounce Collection**: Bounces are sent to a dedicated mailbox (e.g., bounces@yourdomain.org)
|
||||
3. **Bounce Processing**: System reads the mailbox and categorizes bounces (hard/soft/unknown)
|
||||
4. **Threshold Checking**: Only definitive hard bounces count toward suppression thresholds
|
||||
5. **Automatic Protection**: Suppressed emails are blocked from all future mailings
|
||||
|
||||
## Configuration
|
||||
|
||||
Configure bounce thresholds in `config/timebank-cc.php` under `mailing.bounce_thresholds`:
|
||||
- **verification_reset_threshold**: Hard bounces before email_verified_at is reset (default: 2)
|
||||
- **suppression_threshold**: Hard bounces before email is suppressed (default: 3)
|
||||
- **counting_window_days**: Time window for counting bounces (default: 30 days)
|
||||
|
||||
Configure automatic cleanup in `config/timebank-cc.php` under `mailing.bounce_thresholds.automatic_cleanup`:
|
||||
- **day_of_week**: Day for cleanup (0=Sunday, 1=Monday, etc.) (default: 1)
|
||||
- **time**: Time to run cleanup in 24-hour format (default: '03:00')
|
||||
- **cleanup_days**: Days after which to delete soft bounces (default: 90)
|
||||
- **cleanup_bounce_types**: Bounce types to cleanup, hard bounces are preserved (default: ['soft', 'unknown'])
|
||||
|
||||
Set bounce mailbox in `.env`:
|
||||
- **BOUNCE_PROCESSING_ENABLED**: Enable/disable bounce processing (set to `false` on local/staging without IMAP)
|
||||
- **MAIL_BOUNCE_ADDRESS**: Return-Path address for bounces
|
||||
- **BOUNCE_MAILBOX**, **BOUNCE_HOST**, etc.: IMAP settings for bounce processing
|
||||
|
||||
## Artisan Commands
|
||||
|
||||
### Process Bounce Emails
|
||||
```bash
|
||||
# Test bounce processing (dry run)
|
||||
php artisan mailings:process-bounces --dry-run
|
||||
|
||||
# Process bounces and delete from mailbox
|
||||
php artisan mailings:process-bounces --delete
|
||||
|
||||
# Process with custom mailbox settings
|
||||
php artisan mailings:process-bounces --mailbox=bounces@example.com --host=imap.example.com --username=bounces@example.com --password=secret --ssl --delete
|
||||
```
|
||||
|
||||
### Manage Bounced Emails
|
||||
```bash
|
||||
# Show bounce statistics and threshold information
|
||||
php artisan mailings:manage-bounces stats
|
||||
|
||||
# List all bounced emails
|
||||
php artisan mailings:manage-bounces list
|
||||
|
||||
# Check bounce counts for specific email
|
||||
php artisan mailings:manage-bounces check-thresholds --email=user@example.com
|
||||
|
||||
# Check all emails against thresholds
|
||||
php artisan mailings:manage-bounces check-thresholds
|
||||
|
||||
# Manually suppress an email
|
||||
php artisan mailings:manage-bounces suppress --email=problem@example.com
|
||||
|
||||
# Remove suppression from an email
|
||||
php artisan mailings:manage-bounces unsuppress --email=fixed@example.com
|
||||
|
||||
# Clean up old soft bounces
|
||||
php artisan mailings:manage-bounces cleanup --days=90
|
||||
```
|
||||
|
||||
### Test Universal Bounce System
|
||||
```bash
|
||||
# Test with suppressed email (should be blocked)
|
||||
php artisan test:universal-bounce --scenario=suppressed --email=test@example.com
|
||||
|
||||
# Test with normal email (should work)
|
||||
php artisan test:universal-bounce --scenario=normal --email=test@example.com
|
||||
|
||||
# Test with mixed recipients
|
||||
php artisan test:universal-bounce --scenario=mixed
|
||||
|
||||
# Test specific mailable types
|
||||
php artisan test:universal-bounce --scenario=normal --mailable=contact
|
||||
```
|
||||
|
||||
### Test Bounce Threshold System
|
||||
```bash
|
||||
# Test single bounce (no action)
|
||||
php artisan test:bounce-system --scenario=single
|
||||
|
||||
# Test verification reset threshold (2 bounces)
|
||||
php artisan test:bounce-system --scenario=threshold-verification
|
||||
|
||||
# Test suppression threshold (3 bounces)
|
||||
php artisan test:bounce-system --scenario=threshold-suppression
|
||||
|
||||
# Test all scenarios
|
||||
php artisan test:bounce-system --scenario=multiple
|
||||
```
|
||||
|
||||
## Bounce Types
|
||||
|
||||
- **Hard Bounce**: Permanent failure (user unknown, invalid domain) - counts toward thresholds
|
||||
- **Soft Bounce**: Temporary failure (mailbox full, server down) - recorded but ignored
|
||||
- **Unknown**: Unclassified bounces - recorded but ignored
|
||||
|
||||
## Threshold Actions
|
||||
|
||||
- **1 Hard Bounce**: Recorded, no action taken
|
||||
- **2 Hard Bounces**: email_verified_at set to null for all profiles with this email
|
||||
- **3 Hard Bounces**: Email suppressed from all future mailings
|
||||
|
||||
## Automatic Scheduling
|
||||
|
||||
The system automatically schedules the following tasks in `app/Console/Kernel.php`:
|
||||
|
||||
**Bounce Processing**: Every hour (only when `BOUNCE_PROCESSING_ENABLED=true`)
|
||||
```php
|
||||
$schedule->command('mailings:process-bounces --delete')
|
||||
->hourly()
|
||||
->withoutOverlapping()
|
||||
->when(fn() => config('app.bounce_processing_enabled', false));
|
||||
```
|
||||
|
||||
**Note**: Set `BOUNCE_PROCESSING_ENABLED=false` in `.env` on local development and staging environments to prevent IMAP connection errors.
|
||||
|
||||
**Automatic Cleanup**: Configurable via `timebank-cc.php` config (default: Mondays at 3:00 AM)
|
||||
- Cleans up soft bounces older than the configured days (default: 90 days)
|
||||
- Preserves hard bounces for suppression decisions
|
||||
- Schedule automatically updates based on config settings
|
||||
|
||||
## Logging
|
||||
|
||||
The system logs all bounce processing and suppression actions with "MAILING:" prefix in Laravel logs. Monitor logs to track system activity and troubleshoot issues.
|
||||
Reference in New Issue
Block a user