Executive Visibility Through Automated Multi-Stakeholder Reporting: SES, Lambda, and the Art of Communicating Technical Risk
When you're managing a portfolio of four distinct ventures—JADA, Queen of San Diego, QuickDumpNow, and Dangerous Centaur—plus ancillary services like Expert Yacht Delivery and 3028 51st St Rental, stakeholder alignment becomes your primary engineering challenge. This post covers how we automated the generation and delivery of five specialized executive reports, each tailored to a different C-suite perspective, using AWS SES, Python, and careful attention to what each audience actually needs to know.
What Was Done
Over a development session spanning dozens of Lambda deployments and frontend iterations, we built a reporting pipeline that sends five distinct executive briefings, each synthesizing operational data through a different lens:
- CEO Report: Asset inventory, shortfall analysis, KPI gaps, and 30-day action plan across all four entities
- CTO Report: Stack-by-stack security audit, cost analysis, UX gaps, and development cycle improvements
- Accounting Report: Revenue recognition, chart of accounts, expense audit, and profitability roadmap
- CMO Report: Channel-by-channel visibility, OTA sequencing strategy, and 30/60/90-day marketing milestones
- CFO Report: Burn rate modeling, capital deployment framework, break-even analysis, and monthly targets
The implementation required three key components: a Python report generation engine, SES integration for verified sender infrastructure, and a deployment verification loop to ensure emails actually landed in the right inboxes.
Technical Architecture
Report Generation: Python and Environment Injection
The primary implementation lives in /Users/cb/Documents/repos/tools/send_exec_reports.py. This script:
# Pseudocode structure (no actual credentials shown)
import os
import boto3
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
ses_client = boto3.client('ses', region_name='us-west-1')
# Load SES credentials from repos.env via environment variables
SES_FROM_ADDRESS = os.getenv('SES_FROM_ADDRESS')
SES_REGION = os.getenv('SES_REGION', 'us-west-1')
# Report templates are loaded as multi-part MIME messages
# Each report is structured as HTML with fallback plain text
The script reads SES credentials from a repos.env file that must be sourced into the shell environment before execution. This approach avoids hardcoding credentials while allowing CI/CD systems to inject secrets at runtime. The from-address validation was critical: AWS SES requires that any sender email address be verified in the SES console first. We verified admin@queenofsandiego.com as the primary sender.
Report Content Generation
Each report is generated as a complete HTML document with embedded styling. The CEO report, for example, includes:
- A structured asset inventory across JADA, Queen of San Diego, QuickDumpNow, and Dangerous Centaur
- Eight critical shortfalls with business impact assessment (e.g., "empty pipeline = zero revenue visibility")
- Nine missing KPIs organized by domain (e.g., customer acquisition cost, lifetime value, utilization rate)
- A 30-day priority agenda with owners and success metrics
The CTO report digs into the technical stack for each domain:
- JADA: Node.js backend, Stripe integration, DynamoDB for persistence
- Queen of San Diego: Lambda for SCC tool, S3-hosted frontend, CloudFront distribution
- QuickDumpNow: Python backend, Shopify integration, broken funnel between landing page and checkout
- Dangerous Centaur: Basic marketing site, no backend instrumentation, zero analytics
Security findings are presented with remediation priority:
- Hardcoded Stripe keys in environment variables (move to Secrets Manager)
- Plaintext
repos.envin git history (rotate all credentials, add to .gitignore) - Unauthenticated GAS endpoints (add JWT validation at API Gateway)
- No WAF on CloudFront distributions (add AWS WAF with IP allowlisting and rate limiting)
SES Integration and Delivery
The script uses boto3.client('ses') to invoke the SendEmail API. Key parameters:
# Actual command structure (no credentials)
ses_client.send_email(
Source='admin@queenofsandiego.com',
Destination={
'ToAddresses': ['c.b.ladd@gmail.com'],
'BccAddresses': ['admin@queenofsandiego.com'] # Track delivery
},
Message={
'Subject': {'Data': 'Executive Report: CEO Briefing'},
'Body': {
'Html': {'Data': html_content},
'Text': {'Data': text_content}
}
}
)
All five reports are sent in a single script execution. The BCC to admin@queenofsandiego.com ensures a copy lands in the operational inbox for audit purposes.
Infrastructure and Deployment Decisions
Why SES Over Email Marketing Platforms
We chose AWS SES (Simple Email Service) over platforms like SendGrid or Mailgun because:
- Cost: SES is $0.10 per 1,000 emails in us-west-1; SendGrid's free tier maxes at 100/day
- Integration: Already using boto3 for Lambda/DynamoDB; no additional SDK required
- Compliance: Emails stay within AWS infrastructure; reduces third-party data exposure
- Scalability: Can burst to 50 emails/second without pre-warming (adequate for our volume)
The tradeoff: SES requires sender verification and domain-level DKIM/SPF configuration. We verified admin@queenofsandiego.com via the console and confirmed SPF/DKIM records for queenofsandiego.com in Route53.
Report Storage and Archival
While reports are sent immediately, we also save rendered HTML to s3://queen-of-san-diego-reports/ (bucket name sanitized) with a timestamped key structure:
s3://queen-of-san-diego-reports/2025-01/ceo_report_2025-01-15.html
s3://queen-of-san-diego-reports/2025-01/cto_report_2025-01-15.html
s3://queen-of-san-diego-reports/2025-01/accounting_report_2025-01-15.html
s3://queen-of-san-diego-reports/2025-01/cmo_report_2025-01-15.html
s3://queen-of-san-diego-reports/2025-01/cfo_report_2025-01-15.html
This allows historical queries and serves as the source of truth for what