#!/usr/bin/env python3 """Send test compliance gap emails to justin@performancewest.net using real carrier data.""" import json import smtplib import subprocess from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText ISSUE_LABELS = { "ss_partial_note": "STIR/SHAKEN partial implementation \u2014 upstream provider not named in filing", "ss_vsp_no_shaken": "Voice Service Provider without STIR/SHAKEN implementation", "conflicting_classification": "Unusual provider classification \u2014 may need correction", "missing_kyc": "Missing Know Your Customer (KYC) procedures", "missing_material_change": "Missing 10-business-day material change update commitment", "missing_dno": "Missing Do-Not-Originate (DNO) list enforcement", "missing_traceback": "Missing 24-hour traceback response commitment", "missing_recertification": "Missing annual recertification acknowledgment", "missing_perjury": "Missing perjury declaration", "missing_mitigation": "Missing robocall mitigation program details", "no_classification": "No provider classification selected", "ss_intermediate_complete": "Intermediate provider claims Complete STIR/SHAKEN", } # Query real carrier data result = subprocess.run([ "docker", "exec", "performancewest-api-postgres-1", "psql", "-U", "pw", "performancewest", "-t", "-A", "-F", "|", "-c", """SELECT a.frn, a.business_name, a.total_deficiencies, a.severity, r.contact_email, r.implementation, r.last_recertified::text, a.structured_checks::text, a.pdf_checks::text FROM fcc_rmd_audit_results a JOIN fcc_rmd r ON r.frn = a.frn WHERE a.total_deficiencies > 0 AND a.severity IN ('major', 'critical') AND r.contact_email IS NOT NULL AND r.removed_from_rmd = FALSE ORDER BY a.total_deficiencies DESC LIMIT 5""" ], capture_output=True, text=True) with open("/tmp/campaign_template.html") as f: template = f.read() for line in result.stdout.strip().split("\n"): if not line.strip(): continue parts = line.split("|") if len(parts) < 9: continue frn = parts[0].strip() company = parts[1].strip() deficiency_count = parts[2].strip() severity = parts[3].strip() email_orig = parts[4].strip() implementation = parts[5].strip() last_recert = parts[6].strip() structured_json = parts[7].strip() pdf_json = parts[8].strip() # Merge both structured and PDF checks, prioritize major/critical all_checks = [] for cj in [structured_json, pdf_json]: try: checks = json.loads(cj) if isinstance(checks, list): all_checks.extend(checks) except Exception: pass # Sort: critical first, then major, then minor — skip minor for email severity_order = {"critical": 0, "major": 1, "minor": 2} all_checks.sort(key=lambda c: severity_order.get(c.get("severity", "minor"), 2)) items = [] seen_ids = set() for c in all_checks: cid = c.get("id", "") if cid in seen_ids: continue seen_ids.add(cid) sev = c.get("severity", "minor") if sev == "minor": continue # skip minor issues in email label = ISSUE_LABELS.get(cid, c.get("label", cid)) items.append(f"