#!/usr/bin/env python3 """Healthcare (NPI/Medicare) marketing emails, segmented by the compliance problem that needs correcting. Mirrors the trucking brand shell (scripts/campaign_template.html) so all PW outbound looks consistent. Each segment maps to a real PW service + order page: revalidation_overdue Medicare PECOS Revalidation Filing ($599) /order/npi-revalidation npi_reactivation NPI Reactivation ($449) /order/npi-reactivation nppes_outdated NPPES Data Update / Attestation ($349) /order/nppes-update oig_screening OIG/SAM Exclusion Screening ($299) /order/oig-sam-screening compliance_bundle Provider Compliance Bundle (annual) ($899) /order/provider-compliance-bundle Two uses: * `--render ` -> writes the listmonk campaign HTML to out/. * `--send-test ` -> sends every segment as a real test through the healthcare HOT SMTP stream (host :2526 -> hcout1 -> .107), so you see exactly what a provider receives. Personalization tokens are filled with sample data. Listmonk personalization tokens used (kept identical to trucking so the same subscriber-attribs convention applies on real sends): {{ .Subscriber.Name }} provider / practice name {{ .Subscriber.Attribs.npi }} NPI {{ .Subscriber.Attribs.practice }} practice / org name {{ .Subscriber.Attribs.detail }} segment-specific detail (e.g. due date) {{ UnsubscribeURL }} listmonk per-subscriber unsubscribe """ from __future__ import annotations import argparse, os, smtplib, ssl from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.utils import formataddr, make_msgid SITE = "https://performancewest.net" PHONE = "(888) 411-0383" FROM_NAME = "Performance West Compliance" FROM_EMAIL = "compliance@performancewest.net" REPLY_TO = "info@performancewest.net" OUT_DIR = os.path.join(os.path.dirname(__file__), "..", "data", "hc_campaigns") # ── Per-segment content ──────────────────────────────────────────────────── SEGMENTS = { "revalidation_overdue": { "subject": "Action needed: your Medicare revalidation is overdue", "alert": "Medicare Revalidation Alert", "subhead": "Your CMS revalidation deadline has passed", "headline": "Your Medicare billing privileges are at risk", "lede": ("CMS records indicate the Medicare enrollment revalidation for " "{{ .Subscriber.Attribs.practice }} " "(NPI {{ .Subscriber.Attribs.npi }}) is past due."), "issue_title": "What this means", "issue_html": ("If you do not revalidate, CMS will deactivate your " "Medicare billing privileges — claims stop paying " "and you must re-enroll from scratch, losing your effective date " "and any retroactive billing."), "detail_label": "Revalidation due", "cta_copy": "We file your PECOS revalidation for you, before the clock runs out.", "cta_sub": "Most filings submitted within 1-2 business days.", "cta_label": "Start my revalidation \u2192", "cta_path": "/order/npi-revalidation", "price": "$599", }, "npi_reactivation": { "subject": "Your NPI / Medicare enrollment appears deactivated", "alert": "Provider Enrollment Alert", "subhead": "Deactivated enrollment detected", "headline": "Your enrollment looks deactivated \u2014 let's fix it fast", "lede": ("Our compliance monitoring flagged the enrollment for " "{{ .Subscriber.Attribs.practice }} " "(NPI {{ .Subscriber.Attribs.npi }}) as deactivated or inactive."), "issue_title": "Why it matters", "issue_html": ("A deactivated enrollment means Medicare claims are being " "rejected. Reactivation restores your billing " "privileges — the sooner it's filed, the less revenue you lose."), "detail_label": "Status", "cta_copy": "We handle the CMS-855 reactivation end to end.", "cta_sub": "We verify every field against current CMS requirements.", "cta_label": "Reactivate my enrollment \u2192", "cta_path": "/order/npi-reactivation", "price": "$449", }, "nppes_outdated": { "subject": "Your NPPES record may be out of date", "alert": "NPPES Data Alert", "subhead": "Outdated registry information detected", "headline": "Outdated NPPES data can hold up your payments", "lede": ("The public NPPES registry record for " "{{ .Subscriber.Attribs.practice }} " "(NPI {{ .Subscriber.Attribs.npi }}) appears out of date."), "issue_title": "Why it matters", "issue_html": ("Payers, clearinghouses, and CMS pull from NPPES. A stale " "address, taxonomy, or contact can cause claim denials, " "mail you never receive, and failed credentialing. CMS " "also requires you to attest your NPPES data periodically."), "detail_label": "Record", "cta_copy": "We update and attest your NPPES record for you.", "cta_sub": "Address, taxonomy, contacts, and authorized official.", "cta_label": "Update my NPPES record \u2192", "cta_path": "/order/nppes-update", "price": "$349", }, "oig_screening": { "subject": "Are you screening for OIG / SAM exclusions?", "alert": "Exclusion Screening Notice", "subhead": "Annual OIG/SAM screening requirement", "headline": "One excluded individual can cost you everything", "lede": ("Federal rules require practices that bill Medicare/Medicaid to " "screen employees and vendors against the OIG LEIE and " "SAM exclusion lists \u2014 and to document it."), "issue_title": "Why it matters", "issue_html": ("Employing or contracting an excluded party triggers civil " "monetary penalties up to $20,000 per claim plus repayment. " "Most practices have no documented screening process."), "detail_label": "Practice", "cta_copy": "We run and document your OIG/SAM exclusion screening.", "cta_sub": "Monthly checks with an audit-ready record.", "cta_label": "Set up exclusion screening \u2192", "cta_path": "/order/oig-sam-screening", "price": "$299", }, "compliance_bundle": { "subject": "Get your provider compliance handled for the year", "alert": "Provider Compliance Review", "subhead": "Annual compliance, done for you", "headline": "Stop chasing deadlines \u2014 we'll handle the whole year", "lede": ("Between revalidation, NPPES attestation, and exclusion screening, " "provider compliance is a moving target for " "{{ .Subscriber.Attribs.practice }} " "(NPI {{ .Subscriber.Attribs.npi }})."), "issue_title": "What's included", "issue_html": ("Revalidation monitoring & filing, NPPES updates/attestation, " "and monthly OIG/SAM exclusion screening — one flat annual " "price, all tracked, all documented."), "detail_label": "Practice", "cta_copy": "One annual bundle covers your core CMS obligations.", "cta_sub": "We watch the deadlines so you never miss one.", "cta_label": "Get the compliance bundle \u2192", "cta_path": "/order/provider-compliance-bundle", "price": "$899/yr", }, } # Sample values for test sends (real sends use Listmonk subscriber attribs). SAMPLE = { "name": "Dr. Sample Provider", "practice": "Riverbend Family Medicine", "npi": "1234567890", "detail": "06/30/2024 (706 days overdue)", } def render(seg_key: str, *, test: bool = False) -> tuple[str, str]: s = SEGMENTS[seg_key] cta_url = f"{SITE}{s['cta_path']}?npi={{{{ .Subscriber.Attribs.npi }}}}" html = f"""
""" if test: # Fill listmonk tokens with sample data for a standalone test send. html = (html .replace("{{ .Subscriber.Name }}", SAMPLE["name"]) .replace("{{ .Subscriber.Attribs.npi }}", SAMPLE["npi"]) .replace("{{ .Subscriber.Attribs.practice }}", SAMPLE["practice"]) .replace("{{ .Subscriber.Attribs.detail }}", SAMPLE["detail"]) .replace("{{ UnsubscribeURL }}", f"{SITE}/unsubscribe?test=1")) return s["subject"], html def cmd_render(): os.makedirs(OUT_DIR, exist_ok=True) for key in SEGMENTS: subj, html = render(key) path = os.path.join(OUT_DIR, f"hc_{key}.html") open(path, "w").write(html) print(f" wrote {path} (subject: {subj})") def cmd_send_test(to_addr: str, host: str, port: int): from email.utils import formatdate n = 0 for key in SEGMENTS: subj, html = render(key, test=True) msg = MIMEMultipart("alternative") msg["Subject"] = f"[TEST] {subj}" msg["From"] = formataddr((FROM_NAME, FROM_EMAIL)) msg["To"] = to_addr msg["Reply-To"] = REPLY_TO msg["Date"] = formatdate(localtime=True) msg["Message-ID"] = make_msgid(domain="performancewest.net") # Bulk-mail deliverability headers (Gmail/GMX strongly reward these). msg["List-Unsubscribe"] = ( f", " f"<{SITE}/unsubscribe?e={to_addr}>") msg["List-Unsubscribe-Post"] = "List-Unsubscribe=One-Click" msg["List-Id"] = "Performance West Healthcare Compliance " msg["Precedence"] = "bulk" msg["X-Entity-Ref-ID"] = make_msgid(domain="performancewest.net") msg.attach(MIMEText("Please view this email in HTML.", "plain")) msg.attach(MIMEText(html, "html")) with smtplib.SMTP(host, port, timeout=15) as s: s.ehlo("hcmta01.performancewest.net") s.sendmail(FROM_EMAIL, [to_addr], msg.as_string()) print(f" sent [{key}] -> {to_addr} ({subj})") n += 1 print(f"done: {n} test emails sent via {host}:{port}") def main(): ap = argparse.ArgumentParser() ap.add_argument("--render", action="store_true", help="write listmonk HTML to data/hc_campaigns/") ap.add_argument("--send-test", metavar="EMAIL", help="send all segments as test to EMAIL") ap.add_argument("--smtp-host", default="127.0.0.1") ap.add_argument("--smtp-port", type=int, default=2526, help="hc HOT submission port") args = ap.parse_args() if args.render: cmd_render() if args.send_test: cmd_send_test(args.send_test, args.smtp_host, args.smtp_port) if not args.render and not args.send_test: ap.print_help() if __name__ == "__main__": main()