```html

Hardening Email Deliverability: Dark Theme HTML Tables, CloudFront Function Routing, and Uptime Monitoring for Queen of San Diego

What Was Done

This session involved three major infrastructure and content improvements:

  • Email template hardening — rebuilt a crew notification system using table-based HTML with explicit bgcolor attributes to survive Gmail Web's CSS stripping
  • CloudFront function deployment — implemented URL rewriting on the dangerouscentaur.com distribution to eliminate 404 errors for legacy paths
  • Uptime monitoring — created a scheduled Lambda function to continuously verify domain health and log results to a monitoring dashboard

Root Cause: Email Rendering Across Gmail Clients

The original crew notification email (sent May 17) used a <div>-wrapped structure with a dark background color set at the container level. While this renders correctly in many email clients, Gmail Web strips outer <div> styles. The result: cream-colored text (#f3efe7) landed on Gmail's white background, making the message unreadable to 14 crew members.

The fix required understanding email client CSS parsing rules and building defensively. Instead of relying on container-level styles, every table cell needed explicit bgcolor attributes with !important declarations, plus a color-scheme: dark meta tag for clients that support forced dark mode.

Email Delivery Architecture

HTML Structure Changes

Old approach (broken):

<div style="background: #0a1628; color: #f3efe7;">
  <!-- Gmail Web strips this outer div background -->
  <p>Uniform requirements...</p>
</div>

New approach (hardened):

<table width="100%" cellpadding="0" cellspacing="0" border="0" bgcolor="#0a1628" style="background-color: #0a1628 !important;">
  <tr>
    <td bgcolor="#0a1628" style="background-color: #0a1628 !important; color: #ffffff;">
      <!-- Content here is guaranteed readable -->
    </td>
  </tr>
</table>

Key differences:

  • All styling moved to table/td level instead of wrapper divs
  • Every bgcolor attribute duplicated in inline style with !important
  • Meta tags added: <meta name="color-scheme" content="light dark">
  • Text colors explicitly set on every td (no reliance on inheritance)

Resend Process and Tracking

The corrected email was sent via Amazon SES to 14 crew members on May 20. SES MessageId: 0100019e45b138ad-... (truncated for security). Deployment included:

  • New page created: /Users/cb/Documents/repos/sites/queenofsandiego.com/uniforms.html
  • Page hosted on S3 bucket (prod) and CloudFront distribution
  • Email template validated against Gmail Web, Apple Mail, and Outlook rendering engines
  • SMS notification sent to Travis Neel (530-262-5427) with link to uniforms page, bypassing email per his preference
  • Event logged to managercandy dashboard (progress.queenofsandiego.com) for team visibility

Memory update: Created /Users/cb/.claude/projects/.../feedback_email_light_theme.md to document the div-wrapper ban and table-based email requirements for future reference.

CloudFront Function Routing for dangerouscentaur.com

Problem Statement

The dangerouscentaur.com domain was returning 404 errors for valid legacy URLs due to mismatched S3 key naming and route expectations. No centralized rewrite logic existed.

Solution Architecture

Deployed a CloudFront function (viewer-request trigger) to the dangerouscentaur distribution:

  • Function location: AWS CloudFront > Functions > dc-sites-router (published to LIVE)
  • Distribution ID: (tracked in infrastructure registry; not hardcoded in docs)
  • Trigger: Viewer-request event (runs before S3 origin fetch)
  • Logic: Rewrites incoming paths to match S3 key structure; e.g., /whimsy/whimsy/index.html

Sample test invocation:

curl -X GET https://dangerouscentaur.com/whimsy
# Before: 404 error
# After: Returns /whimsy/index.html content via S3 rewrite

Function Logic

The function checks for directory-like paths and appends index.html

// Pseudo-code
if (request.uri !== '/' && !request.uri.includes('.')) {
  request.uri += '/index.html';
}
// Handles /about → /about/index.html
// Passes through /style.css unchanged

Deployment steps:

  1. Write function code to /tmp/dc-clean-urls.js
  2. Create function via AWS CloudFront API (create-function)
  3. Publish to LIVE stage (publish-function)
  4. Attach to distribution using update-distribution
  5. Test with curl and browser on live domain
  6. Monitor CloudFront metrics for rewrite hit rates

Uptime Monitoring Lambda

Infrastructure Setup

Created a DynamoDB table and Lambda function to continuously monitor domain health:

  • DynamoDB Table: dc-uptime-logs (on-demand billing, TTL enabled)
  • Lambda Function: dc_uptime_check (Python 3.12 runtime)
  • IAM Role: dc-uptime-lambda-execution-role with policies for DynamoDB PutItem and CloudWatch Logs
  • EventBridge Rule: Triggers Lambda every 1 minute via cron expression

Function Workflow

The Lambda function (/tmp/dc_uptime_lambda.py) performs these checks:

  1. HTTP GET to dangerouscentaur.com root and key paths (/whimsy, /parallax0, etc.)
  2. Records response status code, latency, and timestamp
  3. Writes record to DynamoDB with TTL set to 90 days