Skip to content

Commit ffcb381

Browse files
committed
bounce and complaints handler
1 parent 582140f commit ffcb381

12 files changed

Lines changed: 1050 additions & 1 deletion

File tree

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
*.tfstate
44
*.tfstate.*
55
*.tfvars
6+
tfplan
7+
*.tfplan
68

79
# Python
810
*.pyc
@@ -19,6 +21,9 @@ env/
1921
*.egg-info/
2022
.pytest_cache/
2123
.mypy_cache/
24+
.coverage
25+
.coverage.*
26+
htmlcov/
2227

2328
# Build artifacts
2429
*.zip
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# SES Bounce and Complaint Handler
2+
3+
Lambda function that processes SES bounce and complaint notifications to maintain email sender reputation and automatically disable problematic email aliases.
4+
5+
## Overview
6+
7+
This Lambda function:
8+
- Receives bounce and complaint notifications from SES via SNS topics
9+
- Queries Airtable to find the affected email alias
10+
- Updates bounce/complaint counts and timestamps
11+
- Automatically disables aliases for permanent bounces and spam complaints
12+
13+
## Architecture
14+
15+
```
16+
SES Email → Bounce/Complaint → SNS Topic → Lambda → Airtable Update
17+
```
18+
19+
## Environment Variables
20+
21+
| Variable | Description | Example |
22+
|----------|-------------|---------|
23+
| `AIRTABLE_SECRET_NAME` | Name of secret in AWS Secrets Manager | `operation-code-automation` |
24+
| `ENVIRONMENT` | Environment name for Sentry tagging | `prod` |
25+
26+
## Secrets Manager
27+
28+
The function expects the following fields in the secret:
29+
- `airtable_api_key` - Airtable API key
30+
- `airtable_base_id` - Airtable base ID (e.g., `appXXXXXXXXXXXXXX`)
31+
- `airtable_table_name` - Table name (e.g., `Email Aliases`)
32+
- `sentry_dsn` - Sentry DSN for error monitoring (optional)
33+
34+
## Bounce Handling Logic
35+
36+
| Bounce Type | Action | Rationale |
37+
|-------------|--------|-----------|
38+
| **Permanent** | Set `Status = "bouncing"` immediately | Invalid email - stop forwarding |
39+
| **Transient** | Increment `bounce_count`, keep active | Temporary issue - allow retry |
40+
41+
## Complaint Handling Logic
42+
43+
All complaints immediately set `Status = "bouncing"` to protect sender reputation.
44+
45+
## Airtable Fields Updated
46+
47+
- `bounce_count` (Number) - Total bounce events
48+
- `last_bounce_date` (Date) - Most recent bounce
49+
- `last_bounce_type` (Single Select) - Permanent, Transient, or Undetermined
50+
- `complaint_count` (Number) - Total complaint events
51+
- `last_complaint_date` (Date) - Most recent complaint
52+
- `Status` (Single Select) - Set to "bouncing" for permanent bounces and complaints
53+
54+
## Testing
55+
56+
Run unit tests:
57+
```bash
58+
cd lambda/ses_bounce_handler
59+
python3 -m venv venv
60+
source venv/bin/activate
61+
pip install -r requirements.txt
62+
pip install pytest moto urllib3
63+
pytest tests/ -v
64+
```
65+
66+
Test with SES Mailbox Simulator:
67+
- `bounce@simulator.amazonses.com` - Permanent bounce
68+
- `ooto@simulator.amazonses.com` - Transient bounce
69+
- `complaint@simulator.amazonses.com` - Spam complaint
70+
71+
## Monitoring
72+
73+
CloudWatch Logs: `/aws/lambda/ses-bounce-handler`
74+
75+
Sentry errors are automatically captured and reported.
76+
77+
## Dependencies
78+
79+
- boto3 - AWS SDK
80+
- sentry-sdk - Error monitoring

0 commit comments

Comments
 (0)