← Back to all posts

SES → SNS → MailAnvil: Complete Event Tracking Setup Guide

2026-07-16 · MailAnvil Team

SES → SNS → MailAnvil Setup Guide

MailAnvil's SNS Worker (mailanvil-sns-worker.pakomting.workers.dev) handles bounce, complaint, and delivery notifications from SES. But it only works if SES is configured to send those notifications to the Worker's URL.

This guide connects everything.

Why this matters

Without SNS With SNS
❌ Bounces unnoticed ✅ Auto-suppressed (INV-2)
❌ Complaints invisible ✅ Kill switch triggers (INV-5)
❌ Delivery status unknown ✅ Per-recipient status tracked
❌ Reputation degrades silently ✅ Automated protection

Prerequisites

Make sure the SNS Worker is deployed:

curl https://mailanvil-sns-worker.pakomting.workers.dev/health
# Should return {"status":"ok","worker":"sns"}

Step 1: Create SNS Topic for SES notifications

  1. Open https://ap-southeast-1.console.aws.amazon.com/sns/v3/home?region=ap-southeast-1#/topics
  2. Click Create topic
  3. Type: Standard
  4. Name: mailanvil-ses-events
  5. Display name: (leave empty)
  6. Click Create topic
  7. Copy the ARN (looks like arn:aws:sns:ap-southeast-1:785823254435:mailanvil-ses-events)

Step 2: Create HTTPS subscription

  1. On the topic page, click Create subscription
  2. Protocol: HTTPS
  3. Endpoint: https://mailanvil-sns-worker.pakomting.workers.dev/ses-event
  4. Enable raw message delivery: No (leave unchecked)
  5. Click Create subscription
  6. Go to the subscription, click Request confirmation
  7. The Worker auto-confirms subscriptions when it receives the confirmation request from SNS
  8. Wait 30 seconds, refresh — status should be Confirmed

If status stays Pending confirmation, the Worker didn't receive the confirmation. Check:

curl https://mailanvil-sns-worker.pakomting.workers.dev/health

Step 3: Configure SES to send events to SNS

  1. Open https://ap-southeast-1.console.aws.amazon.com/ses/home?region=ap-southeast-1#/configuration-sets
  2. Click Create configuration set
  3. Name: mailanvil-config
  4. Click Create

Wait for the configuration set to be created...

  1. Click the config set name → Event destinations tab → Add destination
  2. Name: sns-events
  3. Event types: check ALL:
    • Send
    • Delivery
    • Bounce
    • Complaint
    • Reject
    • Open (optional)
  4. Destination: SNS topic
  5. Topic ARN: paste the ARN from Step 1
  6. Click Add destination

Step 4: Link configuration set to sending

Update the SES credentials to include the configuration set name.

cd /home/richa/mailanvil/packages/consumer
echo "mailanvil-config" | npx wrangler secret put SES_CONFIGURATION_SET

Then:

cd /home/richa/mailanvil/packages/consumer && npx wrangler deploy

Or ask me to do it.

Step 5: Test the pipeline

Send a test email and check:

curl -X POST https://api.mailanvil.com/v1/send \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{"from":"hello@mailanvil.com","to":["aakricha@gmail.com"],"subject":"SNS test","text":"Testing SNS notifications"}'

Then check the email status after 30 seconds:

curl https://api.mailanvil.com/v1/emails/*** \
  -H "Authorization: Bearer ***" | python3 -m json.tool

The ses_message_id should be set (meaning it left SES). After a few more seconds, the per-recipient status should update to delivered once SNS delivers the notification.

Verification

Check the SNS topic for published messages: 1. https://ap-southeast-1.console.aws.amazon.com/sns/v3/home?region=ap-southeast-1#/topics 2. Click mailanvil-ses-eventsMonitoring tab 3. You should see Published messages increasing after test sends

Troubleshooting

Symptom Cause Fix
Subscription stuck Pending confirmation Worker didn't auto-confirm Hit Request confirmation again, then check Worker health
SNS published but no status update Configuration set not linked to sends Set SES_CONFIGURATION_SET secret on consumer Worker
SNS Worker 404 on confirmation Endpoint URL wrong Check /ses-event path matches subscription endpoint
SES events not publishing No configuration set on sends The sendEmail function uses ConfigurationSetName in SES API body

What gets tracked

Event SNS Worker action Result
Bounce Insert into suppressions, update recipient status to bounced INV-2: future sends blocked
Complaint Insert into suppressions, update to complained INV-5: kill switch check
Delivery Update recipient status to delivered Per-recipient tracking
Send Update email status from sending to sent Status update
Reject Update email status to failed with error Error tracking

You don't need to do anything else after Step 4. The SNS Worker handles all events automatically.