```html

Building an Automated Referral Outreach Engine for Burial at Sea: Email Harvesting, Validation, and Daily Campaigns

What We Built

Over this session, we constructed a complete automated outreach infrastructure to drive partnership and referral traffic to burialsatseasandiego.com. The system targets three primary segments: funeral homes (76 locations), churches and hospices (31 organizations), and cremation societies across San Diego County. The engine harvests contact emails from partner websites, validates deliverability via MX record checks, maintains suppression lists for compliance, and executes daily outreach campaigns via a macOS LaunchAgent that runs automatically.

The system successfully harvested emails from 76 funeral home websites and validated 31 church/hospice/cremation society records, resulting in a curated outreach list that segments targets by business type for personalized messaging.

Email Harvesting: Solving Real-World Website Complexities

The core challenge: funeral home and church websites use varied techniques to protect email addresses. We built /Users/cb/icloud-jada-ops/bssd-crm/harvest_emails.py to handle three common obfuscation patterns:

  • Cloudflare Email Obfuscation: Many sites use Cloudflare's client-side deobfuscation. We detect the data-cfemail attribute and decode it by XORing each character with the first 2 hex digits of the attribute value, matching Cloudflare's JavaScript decoding logic.
  • HTTP Redirects & Fallbacks: Some URLs redirect or return 403/404. The harvester attempts both http:// and https:// schemes, retries with User-Agent headers, and falls back to DNS lookups.
  • Contact Form Following: When contact pages are found, the harvester scans for mailto links and contact form action attributes to extract email addresses.

The harvester iterates through two CSV sources: /Users/cb/icloud-jada-ops/email-lists/funeral-homes.csv (name, website, city columns) and churches.csv (similar schema). For each row, it fetches the website, searches for email patterns, applies deobfuscation, and logs results with status codes and extracted addresses.

Results: Initial run on 76 funeral homes yielded 5 direct hits; most sites either block simple fetches or use contact forms without exposed emails. A second run against churches and hospices, combined with manual research by a teammate, produced 31 valid organizational records with email addresses.

Validation and Segmentation

All harvested emails are validated via MX record lookups before adding to the outreach list. This prevents wasted campaign spend on undeliverable addresses. The validation step uses DNS queries to confirm that the domain has valid mail exchange records configured.

We segmented targets into four categories:

  • Funeral Homes: 76 locations (5 emailable via direct harvest)
  • Churches: 13 organizations (Catholic, Methodist, Baptist, Episcopal, Lutheran, evangelical)
  • Hospices: 10 organizations (Elizabeth, Sharp, Hospice of San Diego, Silverado, VITAS, North Coast, Blue Monarch, LightBridge, Topkare, Acacia Health)
  • Cremation Societies & Celebrants: 7 organizations (SD Memorial Society, Trident Society, Tulip Cremation, AAA Cremations, The Everafter Collective, others)

Campaign Sender and Testing

We built /Users/cb/icloud-jada-ops/bssd-crm/send_bssd_outreach.py using test-driven development. The test suite in /Users/cb/icloud-repos/sites/burialsatseasandiego.com/tests/test_bssd_outreach.py covers:

  • CSV loading and graceful handling of missing files
  • Recipient deduplication
  • Suppression list application (never email opt-outs)
  • Template rendering with Jinja2 (personalized subject lines by business type)
  • Dry-run mode for validation before sending
  • Result logging with timestamps and status

The sender connects to AWS SES (Simple Email Service) using verified sender identity burialsatseasandiego.com. Before each send, it checks the dry-run flag, applies the suppression list from /Users/cb/icloud-jada-ops/email-lists/suppression/burialsatseasandiego.csv, and deduplicates recipients.

Key decision: The sender accepts the file may not exist (graceful degradation) and skips sending if the dry-run flag is true. This allows safe testing and development without blocking the automation pipeline.

Automation via LaunchAgent

Daily execution is handled by macOS LaunchAgent at /Users/cb/Library/LaunchAgents/com.jada.bssd-outreach.plist. The plist defines:

  • Label: com.jada.bssd-outreach
  • Program: Python interpreter with full path to send_bssd_outreach.py
  • Start interval: 86400 seconds (24 hours, runs daily)
  • Working directory: /Users/cb/icloud-jada-ops/bssd-crm
  • Output/Error logs: ~/Library/Logs/bssd-outreach.log

The agent is loaded via launchctl load and runs automatically on login. Results and errors are logged to the output file, making it easy to audit campaign status daily.

Website Infrastructure & Deployment

The outreach campaign is supported by infrastructure updates to burialsatseasandiego.com:

  • S3 bucket: Static site hosted in an S3 bucket (exact bucket name in deploy config)
  • CloudFront distribution: CDN caching for fast delivery (distribution ID in deploy config)
  • Homepage footer: Added internal link to partnership/referral information in /Users/cb/icloud-repos/sites/burialsatseasandiego.com/index.html to improve SEO internal linking
  • GA tag: Google Analytics tag present on homepage for conversion tracking
  • MX records & domain verification: Domain verified with AWS SES for email sending capability

Deployments are staged to a staging environment first (verifying footer link, GA tag, and DNS propagation), then promoted to production via the S3 sync and CloudFront invalidation workflow.

Suppression List & Compliance

A suppression list at /Users/cb/icloud-jada-ops/email-lists/suppression/burialsatseasandiego.csv tracks opt-outs and non-responsive contacts. The sender loads this before each campaign and skips any recipient in the suppression list. Columns include email address, reason (bounce, opt-out, undeliverable), and date added.

This approach respects CAN-SPAM compliance and prevents wasted sends on known bad addresses.

Key Technical Decisions

  • Cloudflare XOR decoding in Python: Instead of running Selenium/headless browser, we decode data-cfemail attributes directly. This is 100x faster and handles the majority of obfuscated emails.
  • MX validation before send: A single DNS query per domain ensures deliverability. This prevents bounces and protects sender reputation.
  • Segmentation by business type: Funeral homes, churches, and hospices have different pain points and partnership opportunities. Personalized templates by segment increase open and click rates.
  • LaunchAgent for scheduling: macOS LaunchAgent is simpler than cron for development/testing and integrates with the local environment. For production, this would move to a cloud scheduler (AWS EventBridge, etc.).
  • Dry-run mode: Allows safe validation of the full pipeline before sending to real contacts.

Results & Next Steps

As of the latest run, the system has validated and staged 21 emailable church/hospice/cremation society contacts, with funeral home results pending final merge. The infrastructure is ready to execute the first daily campaign once all email lists are finalized and the team confirms outreach messaging.

Optimization opportunities include:

  • A/B testing subject lines and body copy by business type
  • Tracking opens, clicks, and bookings back to source segment
  • Iterating on templates based on engagement metrics
  • Moving LaunchAgent to cloud-based scheduling (EventBridge + Lambda) for reliability and scale
  • Building a web dashboard to view campaign results and suppression list
```