Implementing Autonomous Email Campaign Management with Dynamic Suppression Lists and Multi-Platform Outreach Orchestration
What Was Done
This session focused on hardening the email marketing infrastructure for JADA's multi-channel outreach engine. The core work involved three concurrent streams: (1) implementing SES suppression list integration into the blast script, (2) creating platform-specific task cards for non-live booking channels, and (3) establishing a widening-gap cadence strategy for contact engagement. Additionally, all customer-facing marketing materials were scrubbed of personal identifying information to maintain brand neutrality across public channels.
Technical Details: SES Suppression List Integration
The primary engineering challenge was preventing duplicate sends and reducing bounce rates by integrating AWS SES suppression list data into the blast workflow before contacts are loaded.
File Modified: /Users/cb/Documents/repos/tools/jada_blast.py
The suppression list export process queries SES for all bounced and complained addresses:
# Pseudo-code structure for suppression list retrieval
import boto3
ses_client = boto3.client('ses', region_name='us-west-2')
def get_suppression_list():
"""
Fetch all addresses from SES account suppression list.
Returns set of email addresses that should not receive campaigns.
"""
suppressed = set()
# Paginate through SES suppression list
paginator = ses_client.get_paginator('list_suppressed_destinations')
for page in paginator.paginate():
for entry in page.get('SuppressedDestinationSummaries', []):
suppressed.add(entry['EmailAddress'])
return suppressed
This function is called during campaign initialization, before template rendering. The contact loader then filters against this set:
suppressed_emails = get_suppression_list()
cleaned_contacts = [c for c in raw_contacts if c['email'] not in suppressed_emails]
Why this matters: AWS SES has strict bounce/complaint thresholds. If your bounce rate exceeds 5% or complaint rate exceeds 0.1%, SES can automatically pause sending from your account. By filtering suppressed addresses before campaign execution, we prevent wasted API calls, reduce bounce metrics, and maintain sender reputation.
Infrastructure: S3, CloudFront, and Email Template Distribution
SDCC (San Diego Comic-Con) email templates are stored in S3 with CloudFront distribution for low-latency delivery to web forms and preview systems.
S3 Bucket: Email templates stored in the primary JADA marketing assets bucket with versioning enabled.
CloudFront Distribution: Configured with cache invalidation rules. When templates are updated (e.g., correcting image URLs, removing PII), the invalidation process clears the edge cache:
# CloudFront cache invalidation example
aws cloudfront create-invalidation \
--distribution-id [DISTRIBUTION_ID] \
--paths "/email-templates/*"
Critical decision: Why versioning? Email campaigns sent across weeks or months may reference different template versions. Versioning ensures that preview links sent to stakeholders always render the exact template that was deployed, preventing discrepancies between what was approved and what was sent.
Platform Task Card Architecture
Rather than manually managing platform integrations (GetMyBoat, WeddingWire, Viator, etc.), a task-driven approach was implemented. Each non-live platform gets a dedicated card with:
- Platform name and API documentation link
- Authentication status (credentials needed, already configured, or integration complete)
- Acceptance criteria: contact volume predictions, template customization requirements, send schedule
- Blocking dependencies: missing credentials, API quota requests, or data mapping rules
These cards integrate with the dashboard system (likely update_dashboard.py) via the task management API. Commands like add-note allow async status updates without stopping the blast pipeline.
Widening-Gap Cadence Strategy
The widening-gap cadence is a contact re-engagement pattern: initial send on day 0, second send on day 3, third on day 7, then day 14, 21, and 30. This approach:
- Maximizes open rates by hitting different time zones and checking habits
- Reduces fatigue by spacing sends exponentially rather than daily blasts
- Identifies engaged vs. cold contacts through opens/clicks across each wave
- Maintains SES reputation by distributing sends across time, reducing per-hour spike patterns that trigger spam filters
Implementation in jada_blast.py uses scheduled job entries with time-delta calculations rather than real-time queueing:
# Pseudo-code for cadence scheduling
cadence_days = [0, 3, 7, 14, 21, 30]
contact_batch_id = generate_batch_id()
for day_offset in cadence_days:
send_time = campaign_start + timedelta(days=day_offset)
queue_send(
batch_id=contact_batch_id,
scheduled_time=send_time,
template_variant='wave_{}'.format(day_offset)
)
PII Removal and Brand Neutrality
All customer-facing files were scanned for personal names and branding that could create perception issues. Files modified include:
/tmp/sdcc-hotel-outreach-2026.html— email preview template/Users/cb/Documents/repos/sites/dangerouscentaur/demos/— demo site HTML files/Users/cb/Documents/repos/sites/queenofsandiego.com/— Google Apps Script files (FuneralOutreach.gs, CrewDispatch.gs, CrewScheduler.gs)/Users/cb/Documents/repos/sites/progress.queenofsandiego.com/index.html— progress dashboard
Removal was systematic rather than ad-hoc. A memory file was created (/Users/cb/.claude/projects/memory/feedback_no_cb_name_in_marketing.md) to document the policy for any future agent sessions, ensuring consistency.
Why this approach? Public-facing tools and marketing materials can be scraped, indexed, or shared outside intended audiences. Removing personal names decouples the brand from individual reputation risk and keeps focus on the service offering (JADA platform, Queen of San Diego brand, crew capabilities) rather than founder identity.
Key Decisions
- SES suppression filtering at campaign load time: Prevents wasted API calls and maintains sender reputation by filtering before send, not after bounces.
- S3 versioning for email templates: Ensures audit trail and allows rollback if deployed template has issues.
- Task-driven platform integration: Decouples platform readiness from blast script coupling, allowing parallel work and clearer dependency tracking.
- Exponential cadence spacing: Balances engagement lift against fatigue and infrastructure load.