diff --git a/scripts/build_trucking_campaigns.py b/scripts/build_trucking_campaigns.py index 043166e..d3de8da 100644 --- a/scripts/build_trucking_campaigns.py +++ b/scripts/build_trucking_campaigns.py @@ -263,13 +263,19 @@ def create_and_schedule_campaign( return cid -def send_test(base: dict, campaign_id: int, sample_row: tuple, label: str, tz: str) -> None: +def send_test(base: dict, campaign_id: int, sample_row: tuple, label: str, tz: str, + campaign_type: str) -> None: """Send one test email so the owner can approve before the real blast goes out.""" dot, email, name, state = sample_row body = base["body"] body = body.replace("{{ .Subscriber.Attribs.company }}", name or "Sample Carrier LLC") body = body.replace("{{ .Subscriber.Attribs.dot_number }}", dot or "0000000") body = body.replace("{{ .Subscriber.Attribs.state }}", state or "TX") + # Real subscribers get a populated lp_link attrib; the test send must mirror + # that or the CTA button (e.g. "Check My Emissions Status") renders as a bare + # "?dot=..." that links to nowhere. Build the same link the audience gets. + body = body.replace("{{ .Subscriber.Attribs.lp_link }}", + build_lp_link(campaign_type, state)) # NOTE: leave {{ UnsubscribeURL }} alone — Listmonk renders it into a real, # working per-subscriber unsubscribe link (even on test sends). Overwriting it # produced a dead /unsubscribe link with no subscriber identity. @@ -474,7 +480,7 @@ def run(send_date: date, dry_run: bool = False, preview: bool = False, "draft/preview" if preview else f"scheduled {send_at.isoformat()}") # Send a test to the owner so they can spot-check the rendered email - send_test(base, cid, rows[0], label, tz) + send_test(base, cid, rows[0], label, tz, campaign_type) # Mark carriers as sent only on a real run if not preview: