Permanent price cuts: - MCS-150 Biennial Update: $69 -> $39 - UCR Annual Registration: $69 -> $39 (+ gov fee unchanged) - MC Operating Authority: $349 -> $199 (+ $300 FMCSA fee unchanged) - State compliance programs (IRP, IFTA, weight-distance/HUT/HUF/KYU, intrastate, OSOW, state DOT, state emissions): -> $109 - California MCP + CARB: $349 -> $229 Updated source of truth (compliance-orders.ts, intake_manifest SERVICE_META), stale dot-lookup recommendation prices, all static trucking landing/marketing pages (services/trucking/*, order/dot-compliance, pricing), and the email campaign scripts (setup_trucking_campaigns, create_state_campaigns). FE/BE price cross-check: all 16 changed slugs consistent. tsc clean, fulfillment consistency 24/24, site build OK.
294 lines
22 KiB
Python
294 lines
22 KiB
Python
#!/usr/bin/env python3
|
|
"""Create non-MCS-150 trucking Listmonk campaigns and send owner tests.
|
|
|
|
Creates draft campaigns only. It does not schedule or start any bulk send.
|
|
|
|
Usage:
|
|
python3 scripts/setup_trucking_campaigns.py
|
|
LISTMONK_URL=https://lists.performancewest.net CAMPAIGN_TEST_EMAIL=carrierone@gmx.com python3 scripts/setup_trucking_campaigns.py
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import base64
|
|
import json
|
|
import os
|
|
import urllib.error
|
|
import urllib.parse
|
|
import urllib.request
|
|
|
|
LISTMONK_URL = os.getenv("LISTMONK_URL", "https://lists.performancewest.net").rstrip("/")
|
|
LISTMONK_USER = os.getenv("LISTMONK_USER", "api")
|
|
LISTMONK_PASS = os.getenv("LISTMONK_PASS", "6X1rKPea61N4rZ1S65Hx5zvqzbCj30F6nvEe9oVGH_Y")
|
|
TEST_EMAIL = os.getenv("CAMPAIGN_TEST_EMAIL", "carrierone@gmx.com")
|
|
FROM_EMAIL = "Performance West <noreply@performancewest.net>"
|
|
REPLY_TO = "info@performancewest.net"
|
|
|
|
AUTH = base64.b64encode(f"{LISTMONK_USER}:{LISTMONK_PASS}".encode()).decode()
|
|
|
|
|
|
def api(path: str, data: dict | None = None, method: str | None = None) -> dict:
|
|
headers = {
|
|
"Authorization": f"Basic {AUTH}",
|
|
"Content-Type": "application/json",
|
|
"Accept": "application/json",
|
|
}
|
|
req = urllib.request.Request(f"{LISTMONK_URL}/api{path}", headers=headers)
|
|
if data is not None:
|
|
req.data = json.dumps(data).encode()
|
|
if method:
|
|
req.method = method
|
|
try:
|
|
raw = urllib.request.urlopen(req, timeout=45).read()
|
|
return json.loads(raw or b"{}")
|
|
except urllib.error.HTTPError as exc:
|
|
body = exc.read().decode(errors="replace")[:1000]
|
|
raise RuntimeError(f"Listmonk {path} HTTP {exc.code}: {body}") from exc
|
|
|
|
|
|
def list_map() -> dict[str, dict]:
|
|
resp = api("/lists?per_page=all")
|
|
results = resp.get("data", {}).get("results", [])
|
|
return {row["name"]: row for row in results}
|
|
|
|
|
|
def get_or_create_list(name: str, tags: list[str]) -> int:
|
|
lists = list_map()
|
|
if name in lists:
|
|
return int(lists[name]["id"])
|
|
resp = api("/lists", {"name": name, "type": "private", "optin": "single", "tags": tags}, "POST")
|
|
return int(resp["data"]["id"])
|
|
|
|
|
|
def service_rows(rows: list[tuple[str, str]]) -> str:
|
|
body = "".join(
|
|
f'<tr><td style="padding:6px 0;"><strong>{name}</strong></td>'
|
|
f'<td style="padding:6px 0;text-align:right;font-weight:700;color:#f97316;">{price}</td></tr>'
|
|
for name, price in rows
|
|
)
|
|
return f'<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="font-size:13px;color:#374151;font-family:Inter,sans-serif;">{body}</table>'
|
|
|
|
|
|
def requirement_rows(rows: list[str]) -> str:
|
|
cells = "".join(
|
|
f'<tr><td style="padding:10px 14px;font-size:13px;color:#991b1b;border-bottom:1px solid #fee2e2;font-family:Inter,sans-serif;">{row}</td></tr>'
|
|
for row in rows[:-1]
|
|
)
|
|
cells += f'<tr><td style="padding:10px 14px;font-size:13px;color:#991b1b;font-family:Inter,sans-serif;">{rows[-1]}</td></tr>'
|
|
return f'<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:0 0 22px;">{cells}</table>'
|
|
|
|
|
|
def build_email(cfg: dict) -> str:
|
|
cta_url = cfg["cta_url"]
|
|
cta = f"{cta_url}{'&' if '?' in cta_url else '?'}utm_source=listmonk&utm_medium=email&utm_campaign={cfg['slug']}"
|
|
return f'''<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>@media only screen and (max-width:600px){{.pw-wrap{{width:100%!important;border-radius:0!important;}}.pw-pad{{padding:24px 16px!important;}}}}body,table,td,p,a{{-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}}table{{border-collapse:collapse!important;}}img{{border:0;outline:none;text-decoration:none;}}</style></head><body style="margin:0;padding:0;background:#eef0f3;">
|
|
<center><table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:#eef0f3;"><tr><td style="padding:24px 10px;"><table role="presentation" class="pw-wrap" width="620" cellpadding="0" cellspacing="0" style="margin:0 auto;border-radius:10px;overflow:hidden;background:#fff;">
|
|
<tr><td style="background:#1a2744;padding:24px 28px;"><img src="https://performancewest.net/images/logo.png" alt="Performance West" style="height:44px;margin-bottom:10px;display:block" /><h1 style="color:#fff;margin:0;font-size:22px;font-weight:700;font-family:Inter,system-ui,sans-serif;">{cfg['headline']}</h1><p style="color:#94a3b8;margin:6px 0 0;font-size:13px;font-family:Inter,sans-serif;">Compliance report for {{{{ .Subscriber.Attribs.company }}}}</p></td></tr>
|
|
<tr><td style="background:#f97316;height:4px;font-size:0;"> </td></tr>
|
|
<tr><td class="pw-pad" style="padding:28px;font-family:Inter,system-ui,sans-serif;color:#1f2937;">
|
|
<p style="font-size:15px;margin:0 0 18px;line-height:1.5;">Hi {{{{ .Subscriber.Name }}}},</p>
|
|
<p style="font-size:14px;line-height:1.7;margin:0 0 18px;">We reviewed DOT and state compliance data for <strong>{{{{ .Subscriber.Attribs.company }}}}</strong> (DOT# {{{{ .Subscriber.Attribs.dot_number }}}}). Based on the carrier profile and operating state data, the following requirements may need attention.</p>
|
|
<h3 style="font-size:15px;font-weight:700;color:#1e3a5f;margin:24px 0 12px;font-family:Inter,sans-serif;">What may apply</h3>
|
|
{requirement_rows(cfg['requirements'])}
|
|
<h3 style="font-size:15px;font-weight:700;color:#1e3a5f;margin:24px 0 12px;font-family:Inter,sans-serif;">Check Your Full Compliance Status</h3>
|
|
<p style="font-size:14px;line-height:1.7;margin:0 0 18px;">Run our free DOT compliance check to see federal and state requirements in one report.</p>
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:0 0 22px;"><tr><td style="text-align:center;padding:8px 0;"><a href="https://performancewest.net/tools/dot-compliance-check?dot={{{{ .Subscriber.Attribs.dot_number }}}}&utm_source=listmonk&utm_medium=email&utm_campaign={cfg['slug']}" style="display:inline-block;padding:16px 48px;background:#f97316;color:#fff;font-weight:700;border-radius:8px;text-decoration:none;font-size:16px;font-family:Inter,sans-serif;box-shadow:0 4px 12px rgba(249,115,22,0.4);">Check My DOT Compliance →</a><p style="font-size:11px;color:#6b7280;margin:10px 0 0;font-family:Inter,sans-serif;">Free, no account required. Your DOT# is pre-filled.</p></td></tr></table>
|
|
<h3 style="font-size:15px;font-weight:700;color:#1e3a5f;margin:24px 0 12px;font-family:Inter,sans-serif;">How We Can Help</h3>
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:0 0 22px;"><tr><td style="background:#f0f4f8;border-radius:10px;padding:18px;">{service_rows(cfg['services'])}<p style="font-size:12px;color:#64748b;margin:10px 0 0;font-family:Inter,sans-serif;">We handle the paperwork. You focus on driving.</p></td></tr></table>
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:0 0 22px;"><tr><td style="text-align:center;padding:8px 0;"><a href="{cta}" style="display:inline-block;padding:14px 36px;background:#1a2744;color:#fff;font-weight:700;border-radius:8px;text-decoration:none;font-size:15px;font-family:Inter,sans-serif;">{cfg['cta_text']} →</a></td></tr></table>
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:12px 0 0;"><tr><td style="background:#eff6ff;border:1px solid #bfdbfe;border-radius:10px;padding:14px;text-align:center;"><p style="font-size:14px;color:#1e3a5f;margin:0 0 6px;font-weight:600;font-family:Inter,sans-serif;">Reply to this email or reach us at:</p><p style="font-size:20px;color:#1e3a5f;margin:0;font-weight:800;font-family:Inter,sans-serif;"><a href="mailto:info@performancewest.net" style="color:#1e3a5f;text-decoration:none;">info@performancewest.net</a></p><p style="font-size:12px;color:#6b7280;margin:6px 0 0;font-family:Inter,sans-serif;">or call (888) 411-0383</p></td></tr></table>
|
|
<p style="font-size:14px;line-height:1.7;margin:18px 0 0;">Best,</p><p style="font-size:14px;line-height:1.5;margin:4px 0 0;"><strong>Justin Hannah</strong><br>Performance West Inc.<br><span style="font-size:12px;color:#64748b;">DOT Compliance Services</span></p>
|
|
</td></tr><tr><td style="padding:16px 28px;background:#f8fafc;border-top:1px solid #e5e7eb;font-size:11px;color:#9ca3af;text-align:center;font-family:Inter,sans-serif;"><p style="margin:0;">Performance West Inc. · 525 Randall Ave Ste 100-1195, Cheyenne, WY 82001 · <a href="https://performancewest.net" style="color:#6b7280;">performancewest.net</a></p><p style="margin:6px 0 0;"><a href="{{{{ UnsubscribeURL }}}}" style="color:#6b7280;">Unsubscribe</a></p></td></tr>
|
|
</table></td></tr></table></center></body></html>'''
|
|
|
|
|
|
CAMPAIGNS = [
|
|
{
|
|
"slug": "ca-mcp-carb", "list": "FMCSA State - California (MCP/CARB)",
|
|
"name": "CA Motor Carrier Permit + CARB Compliance Alert", "headline": "California Compliance Alert",
|
|
"subject": "California MCP + CARB requirements for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>Motor Carrier Permit (MCP)</strong> — California requires many for-hire carriers and qualifying CMVs to maintain an MCP through CA DMV.",
|
|
"<strong>CA Number / CHP requirements</strong> — California carriers may need a state carrier number in addition to USDOT.",
|
|
"<strong>CARB emissions compliance</strong> — diesel vehicles can face California emissions restrictions and enforcement.",
|
|
],
|
|
"services": [("California MCP + CARB Compliance", "$229"), ("IRP Registration Assistance", "$109"), ("IFTA Application + Decals", "$109"), ("State Compliance Bundle", "$599")],
|
|
"cta_url": "https://performancewest.net/services/trucking/california/", "cta_text": "View California Compliance Services",
|
|
},
|
|
{
|
|
"slug": "or-weight-mile", "list": "FMCSA State - Oregon (Weight-Mile Tax)",
|
|
"name": "Oregon Weight-Mile Tax Compliance Alert", "headline": "Oregon Weight-Mile Alert",
|
|
"subject": "Oregon Weight-Mile Tax registration for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>Weight-Mile Tax</strong> — Oregon trucks over 26,000 lbs generally need weight-mile tax registration and filings.",
|
|
"<strong>IRP / apportioned plates</strong> — interstate Oregon operations often require apportioned registration.",
|
|
"<strong>ODOT authority</strong> — some for-hire intrastate operations require state authority.",
|
|
],
|
|
"services": [("Oregon Weight-Mile Tax Setup", "$109"), ("IRP Registration Assistance", "$109"), ("IFTA Application + Decals", "$109"), ("State Compliance Bundle", "$599")],
|
|
"cta_url": "https://performancewest.net/services/trucking/oregon/", "cta_text": "View Oregon Compliance Services",
|
|
},
|
|
{
|
|
"slug": "ny-hut", "list": "FMCSA State - New York (HUT)",
|
|
"name": "NY Highway Use Tax Compliance Alert", "headline": "New York HUT Alert",
|
|
"subject": "New York HUT registration for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>Highway Use Tax (HUT)</strong> — New York requires HUT registration for many vehicles over 18,000 lbs.",
|
|
"<strong>Quarterly filings</strong> — HUT is not just a one-time registration. Reporting may be recurring.",
|
|
"<strong>Intrastate authority</strong> — for-hire NY intrastate carriers may need NY authority.",
|
|
],
|
|
"services": [("NY Highway Use Tax Registration", "$109"), ("HUT Quarterly Filing", "$99"), ("Intrastate Operating Authority", "$109"), ("State Compliance Bundle", "$599")],
|
|
"cta_url": "https://performancewest.net/services/trucking/new-york/", "cta_text": "View New York Compliance Services",
|
|
},
|
|
{
|
|
"slug": "ky-kyu", "list": "FMCSA State - Kentucky (KYU)",
|
|
"name": "Kentucky KYU Weight-Distance Tax Alert", "headline": "Kentucky KYU Alert",
|
|
"subject": "Kentucky KYU number requirements for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>KYU number</strong> — Kentucky requires weight-distance tax registration for vehicles over 59,999 lbs combined license weight.",
|
|
"<strong>Mileage reporting</strong> — KYU tax is based on miles operated in Kentucky and requires ongoing filings.",
|
|
"<strong>Permit exposure</strong> — operating without proper KYU setup can create roadside and tax issues.",
|
|
],
|
|
"services": [("Kentucky KYU Number Setup", "$109"), ("KYU Quarterly Filing", "$99"), ("State Compliance Bundle", "$599")],
|
|
"cta_url": "https://performancewest.net/services/trucking/kentucky/", "cta_text": "View Kentucky Compliance Services",
|
|
},
|
|
{
|
|
"slug": "nm-weight-distance", "list": "FMCSA State - New Mexico (Weight-Distance)",
|
|
"name": "New Mexico Weight-Distance Tax Alert", "headline": "New Mexico Weight-Distance Alert",
|
|
"subject": "New Mexico Weight-Distance Tax for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>Weight-Distance Tax</strong> — New Mexico requires qualifying commercial vehicles to register and file weight-distance returns.",
|
|
"<strong>Trip and mileage records</strong> — filings depend on New Mexico miles and vehicle weight class.",
|
|
"<strong>Operating state gap</strong> — carriers passing through NM can trigger requirements even if based elsewhere.",
|
|
],
|
|
"services": [("New Mexico Weight-Distance Setup", "$109"), ("Quarterly Filing", "$99"), ("State Compliance Bundle", "$599")],
|
|
"cta_url": "https://performancewest.net/services/trucking/new-mexico/", "cta_text": "View New Mexico Compliance Services",
|
|
},
|
|
{
|
|
"slug": "ct-huf", "list": "FMCSA State - Connecticut (Highway Use Fee)",
|
|
"name": "Connecticut Highway Use Fee Alert", "headline": "Connecticut Highway Use Fee Alert",
|
|
"subject": "Connecticut Highway Use Fee for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>Highway Use Fee</strong> — Connecticut applies a per-mile highway use fee to certain heavy vehicles over 26,000 lbs.",
|
|
"<strong>Quarterly filing</strong> — HUF returns are recurring and based on mileage and weight class.",
|
|
"<strong>Multi-state exposure</strong> — CT trips can trigger filing duties even for carriers based outside Connecticut.",
|
|
],
|
|
"services": [("Connecticut HUF Registration", "$109"), ("Quarterly Filing", "$99"), ("State Compliance Bundle", "$599")],
|
|
"cta_url": "https://performancewest.net/services/trucking/connecticut/", "cta_text": "View Connecticut Compliance Services",
|
|
},
|
|
{
|
|
"slug": "tx-txdmv", "list": "FMCSA State - Texas (TxDMV)",
|
|
"name": "Texas TxDMV Number / Intrastate Authority Alert", "headline": "Texas TxDMV Alert",
|
|
"subject": "Texas TxDMV number requirements for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>TxDMV number</strong> — many Texas intrastate motor carriers need a TxDMV number in addition to USDOT.",
|
|
"<strong>Intrastate operating authority</strong> — for-hire Texas operations can trigger state authority and insurance filing requirements.",
|
|
"<strong>Insurance filing</strong> — Texas authority often requires proof of insurance on file with the state.",
|
|
],
|
|
"services": [("Texas TxDMV Number Filing", "$109"), ("Texas Intrastate Authority", "$109"), ("State Insurance Filing", "$99"), ("State Compliance Bundle", "$599")],
|
|
"cta_url": "https://performancewest.net/services/trucking/texas/", "cta_text": "View Texas Compliance Services",
|
|
},
|
|
{
|
|
"slug": "irp-ifta-starter", "list": "FMCSA Trucking - IRP IFTA Prospects",
|
|
"name": "IRP / IFTA Interstate Carrier Starter Campaign", "headline": "IRP / IFTA Filing Alert",
|
|
"subject": "Crossing state lines? IRP and IFTA checklist for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>IRP apportioned registration</strong> — qualifying interstate vehicles generally need apportioned plates through their base state.",
|
|
"<strong>IFTA fuel tax account</strong> — interstate fuel tax registration and decals may be required before operating across state lines.",
|
|
"<strong>Quarterly IFTA returns</strong> — IFTA continues after registration with quarterly fuel tax reporting.",
|
|
],
|
|
"services": [("IRP Registration Assistance", "$109"), ("IFTA Application + Decals", "$109"), ("Quarterly IFTA Filing", "$99"), ("IRP/IFTA Bundle", "$299")],
|
|
"cta_url": "https://performancewest.net/services/trucking/irp-ifta/", "cta_text": "Get IRP / IFTA Help",
|
|
},
|
|
{
|
|
"slug": "dot-drug-alcohol", "list": "FMCSA Trucking - Drug Alcohol Prospects",
|
|
"name": "DOT Drug & Alcohol Program Campaign", "headline": "DOT Drug & Alcohol Alert",
|
|
"subject": "DOT drug and alcohol testing requirements for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>CDL driver testing</strong> — carriers with CDL drivers generally need a DOT-compliant drug and alcohol testing program.",
|
|
"<strong>Random consortium</strong> — owner-operators usually need to be enrolled in a compliant random testing pool.",
|
|
"<strong>Audit exposure</strong> — missing testing records are common issues during safety audits and investigations.",
|
|
],
|
|
"services": [("DOT Drug & Alcohol Program", "$149/yr"), ("Clearinghouse / Driver File Review", "$99"), ("DOT Full Compliance Bundle", "$599")],
|
|
"cta_url": "https://performancewest.net/services/trucking/drug-alcohol-program/", "cta_text": "Enroll in DOT D&A Program",
|
|
},
|
|
{
|
|
"slug": "hazmat-compliance", "list": "FMCSA Trucking - Hazmat Prospects",
|
|
"name": "Hazmat Carrier Compliance Campaign", "headline": "Hazmat Compliance Alert",
|
|
"subject": "Hazmat compliance review for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>Hazmat registration</strong> — carriers transporting regulated hazardous materials may need PHMSA/HM registration.",
|
|
"<strong>Higher insurance and safety exposure</strong> — hazmat operations often trigger stricter insurance and audit requirements.",
|
|
"<strong>Driver and security records</strong> — training, endorsements, and emergency response documents need to be audit-ready.",
|
|
],
|
|
"services": [("Hazmat Compliance Review", "$199"), ("Safety Audit Prep", "$299"), ("Insurance / State Filing Review", "$99"), ("DOT Full Compliance Bundle", "$599")],
|
|
"cta_url": "https://performancewest.net/services/trucking/hazmat/", "cta_text": "Review Hazmat Compliance",
|
|
},
|
|
{
|
|
"slug": "new-carrier-startup", "list": "FMCSA Trucking - New Carrier Missing Startup Items",
|
|
"name": "New Carrier Startup Checklist Campaign", "headline": "New Carrier Startup Checklist",
|
|
"subject": "New DOT number? Startup checklist for {{ .Subscriber.Attribs.company }}",
|
|
"requirements": [
|
|
"<strong>Our startup checklist flagged these likely missing items for your carrier:</strong><br>{{ Safe .Subscriber.Attribs.missing_items_html }}",
|
|
"<strong>Startup filing sequence</strong> — LLC, EIN, USDOT, operating authority, BOC-3, UCR, D&A, insurance, IRP and IFTA can all stack up quickly.",
|
|
"<strong>Missed renewals</strong> — new carriers often miss UCR, MCS-150 timing, state permits, or quarterly fuel tax obligations.",
|
|
"<strong>Cash-flow friendly setup</strong> — bundling startup compliance prevents piecemeal filings and duplicate work.",
|
|
],
|
|
"services": [("New Carrier Starter Bundle", "$599"), ("LLC Formation", "$199"), ("BOC-3", "$49"), ("UCR Filing", "$39")],
|
|
"cta_url": "https://performancewest.net/services/trucking/new-carrier/", "cta_text": "Start Carrier Compliance",
|
|
},
|
|
]
|
|
|
|
|
|
def create_campaign(cfg: dict, list_id: int) -> int:
|
|
payload = {
|
|
"name": cfg["name"],
|
|
"subject": cfg["subject"],
|
|
"from_email": FROM_EMAIL,
|
|
"type": "regular",
|
|
"content_type": "html",
|
|
"body": build_email(cfg),
|
|
"lists": [list_id],
|
|
"template_id": 1,
|
|
"headers": [{"Reply-To": REPLY_TO}],
|
|
"tags": ["dot-compliance", "trucking", cfg["slug"]],
|
|
"messenger": "email",
|
|
}
|
|
resp = api("/campaigns", payload, "POST")
|
|
return int(resp["data"]["id"])
|
|
|
|
|
|
def send_test(campaign_id: int, cfg: dict, list_id: int) -> None:
|
|
body = build_email(cfg)
|
|
sample = {
|
|
"name": cfg["name"],
|
|
"subject": "[TEST] " + cfg["subject"].replace("{{ .Subscriber.Attribs.company }}", "Sample Carrier LLC"),
|
|
"from_email": FROM_EMAIL,
|
|
"type": "regular",
|
|
"content_type": "html",
|
|
"body": body,
|
|
"lists": [list_id],
|
|
"template_id": 1,
|
|
"headers": [{"Reply-To": REPLY_TO}],
|
|
"tags": ["dot-compliance", "trucking", cfg["slug"], "test"],
|
|
"messenger": "email",
|
|
"subscribers": [TEST_EMAIL],
|
|
}
|
|
api(f"/campaigns/{campaign_id}/test", sample, "POST")
|
|
|
|
|
|
def main() -> None:
|
|
print(f"Listmonk: {LISTMONK_URL}")
|
|
print(f"Sending tests to: {TEST_EMAIL}")
|
|
created: list[tuple[str, int, int]] = []
|
|
for cfg in CAMPAIGNS:
|
|
list_id = get_or_create_list(cfg["list"], ["trucking", "dot-compliance", cfg["slug"]])
|
|
campaign_id = create_campaign(cfg, list_id)
|
|
send_test(campaign_id, cfg, list_id)
|
|
created.append((cfg["name"], campaign_id, list_id))
|
|
print(f"created draft campaign {campaign_id} on list {list_id}: {cfg['name']} | test sent")
|
|
print("\nSummary:")
|
|
for name, campaign_id, list_id in created:
|
|
print(f"- #{campaign_id} list #{list_id}: {name}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|