```html

Implementing Multi-Platform Email Campaign Infrastructure with Dynamic Suppression List Management

This session focused on building scalable email campaign infrastructure across multiple booking platforms while implementing robust contact hygiene through AWS SES suppression list integration. We tackled three core challenges: platform credential management, bounce list hygiene, and campaign cadence optimization.

What Was Done

  • Enhanced jada_blast.py to support dynamic platform-specific contact filtering
  • Integrated AWS SES suppression list export and contact cleaning pipeline
  • Implemented widening-gap email cadence for re-engagement campaigns
  • Created platform-specific task cards for GetMyBoat, WeddingWire, and other booking platforms
  • Cleaned and deployed SDCC hotel outreach email templates to S3/CloudFront
  • Removed all internal names from outward-facing marketing materials

Technical Implementation Details

Contact Hygiene Pipeline

The SES suppression list integration required a multi-step process. First, we exported the bounce/complaint list from AWS SES, which included permanent bounces and user complaints. The suppression data was then cross-referenced against our contact CSV files using Python set operations for O(1) lookup performance:


# Pseudo-code approach for suppression list cleaning
suppressed_emails = set(load_ses_suppression_list())
active_contacts = [c for c in load_contacts() if c['email'] not in suppressed_emails]
write_cleaned_contacts(active_contacts)

This filtering prevents SES from rejecting already-bounced addresses, reducing API errors and improving deliverability metrics. The cleaned contact list was written back to the platform-specific CSV files maintained in the repos directory structure.

jada_blast.py Enhancements

The blast script in /Users/cb/Documents/repos/tools/jada_blast.py was modified to support platform-specific send logic:

  • Template resolution: Dynamic loading from platform subdirectories (e.g., templates/getmyboat/welcome.html)
  • Credential injection: Platform credentials read from environment variables, validated before send operations
  • Contact filtering: Pre-send validation against suppression lists to prevent bounces
  • Cadence tracking: Widening-gap logic that increases send intervals for non-responders (day 1, day 3, day 7, day 14)

The widening-gap pattern allows re-engagement campaigns without aggressive frequency that triggers spam complaints. Each platform maintains its own send schedule in a companion metadata file, tracking last-contact timestamps and engagement tier.

Email Template Deployment

SDCC hotel outreach email templates were deployed through the following pipeline:

  1. Template validation: verified all image URLs resolve to S3 bucket paths
  2. Content audit: removed all internal references and personal identifiers
  3. S3 upload: pushed final HTML to s3://[jada-static-bucket]/sdcc/email-templates/
  4. CloudFront invalidation: purged cache for the distribution serving *.sailjada.com

The templates reference boat images via absolute S3 URLs (e.g., https://s3.amazonaws.com/bucket/images/boat-001.jpg), which were verified to return 200 status before deployment.

Infrastructure and Resource Management

File Structure Changes

Platform task management was centralized in dashboard cards, with the following directory structure established:


/repos/sites/queenofsandiego.com/
├── CrewDispatch.gs          (outreach automation)
├── CrewScheduler.gs         (send scheduling)
├── FuneralOutreach.gs       (event follow-up)
└── rady-shell-events/
    └── apps-script-replacement/
        ├── WorshipRsvp.gs
        └── ViatorApiFollowUp.gs

/repos/tools/
└── jada_blast.py            (core send engine)

/repos/demos/
├── 3028fiftyfirststreet.92105.dangerouscentaur.com/
├── demo.dangerouscentaur.com/
└── progress.queenofsandiego.com/

Each platform maintains its own contact list and template directory, enabling isolated testing and rollback capabilities.

AWS SES Integration

SES suppression list queries were implemented to check bounce counts before campaign launches. The suppression list export includes:

  • Permanent bounces (invalid addresses, domain rejections)
  • Transient bounces (temporary delivery failures, retry-eligible)
  • Complaint entries (user-reported spam)

Contact cleaning removed all permanent bounce and complaint entries, while transient bounces were retained for retry attempts on the next cadence window.

CloudFront and Cache Invalidation

After deploying updated HTML files for dangerouscentaur demo sites and the progress dashboard, CloudFront distributions were invalidated to ensure users received fresh content. Key distributions updated:

  • dangerouscentaur.com demo sites
  • progress.queenofsandiego.com dashboard
  • SDCC email template delivery

Invalidation was performed using wildcard patterns rather than individual file purges, ensuring consistency across all related assets.

Key Architectural Decisions

Why Widening-Gap Cadence?

The widening-gap pattern (1-3-7-14 days) balances engagement with deliverability. Aggressive daily sends increase complaint rates and trigger spam filters. By spacing sends exponentially, we allow user engagement signals to accumulate while reducing risk of complaints that harm sender reputation.

Why Suppression List Cleaning?

AWS SES enforces suppression list rules at send time. Attempting to send to a suppressed address results in a MessageRejected error, which counts against account limits. By cleaning contacts pre-send, we reduce error rates and improve throughput by eliminating failed delivery attempts.

Why Platform-Specific Credential Separation?

Each platform (GetMyBoat, WeddingWire, etc.) maintains separate SMTP credentials and template formats. Isolating credentials by platform in environment variables reduces the blast radius of credential compromise and enables granular permission scoping.

Content Cleanup and Compliance

A systematic audit of all outward-facing materials removed personal identifiers. Files scanned included:

  • FuneralOutreach.gs, CrewDispatch.gs, CrewScheduler.gs (Google Apps Script files)
  • HTML demo files across dangerouscentaur and progress sites
  • Email templates in SDCC outreach campaign
  • All marketing copy in /repos/tools/

References were replaced with generic team language (e.g., "JADA Team", "Queen of San Diego Events") to maintain brand consistency without personal attribution.

What's Next

Upcoming work includes:

  • A/B testing cadence intervals by platform to identify optimal re-engagement windows