diff --git a/scripts/bounce-watcher.sh b/scripts/bounce-watcher.sh index bf25382..2784ccb 100644 --- a/scripts/bounce-watcher.sh +++ b/scripts/bounce-watcher.sh @@ -23,8 +23,10 @@ CURRENT_UUID="" tail -F "$LOG" 2>/dev/null | while IFS= read -r line; do - # Track queue IDs originating from campaign sender - if echo "$line" | grep -q "from="; then + # Track queue IDs originating from campaign sender. Bulk now sends from the + # dedicated bulk subdomain (noreply@send.performancewest.net); the root-domain + # sender is kept so the pre-cutover queue still drains correctly. + if echo "$line" | grep -qE "from=|from="; then QID=$(echo "$line" | sed -n 's/.*postfix\/[^[]*\[\([0-9]*\)\]: \([A-Z0-9]*\):.*/\2/p') if [ -n "$QID" ]; then CAMPAIGN_QIDS[$QID]=1 diff --git a/scripts/build_healthcare_campaigns_cron.py b/scripts/build_healthcare_campaigns_cron.py index 490138f..8ac3865 100644 --- a/scripts/build_healthcare_campaigns_cron.py +++ b/scripts/build_healthcare_campaigns_cron.py @@ -54,8 +54,15 @@ WARMUP_STAMP = "/etc/postfix/hc-warmup-start" # re-mails them, regardless of segment or stale CMS data. Append + run --prune. SUPPRESS_FILE = os.getenv("HC_SUPPRESS_FILE", os.path.join(STATE_DIR, "hc_suppress.txt")) -FROM_EMAIL = "Performance West Compliance " -REPLY_TO = "info@performancewest.net" +# Bulk From — sends from the dedicated bulk subdomain so its sending reputation +# is isolated from the root domain (which stays clean for transactional / +# verification mail). Replies still go to the root domain via Reply-To, so the +# customer-facing reply experience is unchanged. See docs/deliverability.md. +FROM_EMAIL = os.getenv( + "HC_CAMPAIGN_FROM", + "Performance West Compliance ", +) +REPLY_TO = os.getenv("HC_CAMPAIGN_REPLY_TO", "info@performancewest.net") # Segment registry (subject, template file, list/campaign names, row selector) # is the single source of truth shared with build_healthcare_campaigns.py. diff --git a/scripts/build_trucking_campaigns.py b/scripts/build_trucking_campaigns.py index dc4bbc9..cc6b14c 100644 --- a/scripts/build_trucking_campaigns.py +++ b/scripts/build_trucking_campaigns.py @@ -342,6 +342,12 @@ TEST_EMAIL = os.getenv("CAMPAIGN_TEST_EMAIL", "carrierone@gmx.com") REPLY_TO_EMAIL = os.getenv("CAMPAIGN_REPLY_TO", "info@performancewest.net") REPLY_TO_HEADERS = [{"name": "Reply-To", "value": REPLY_TO_EMAIL}] +# Bulk From — sends from the dedicated bulk subdomain so its sending reputation +# is isolated from the root domain (which stays clean for transactional / +# verification mail). Replies still go to the root domain via Reply-To above, so +# the customer-facing reply experience is unchanged. See docs/deliverability.md. +FROM_EMAIL = os.getenv("CAMPAIGN_FROM", "Performance West ") + # Which verification results are safe to SEND to. We key ONLY off # email_verify_result, never the email_verified boolean: the verifier sets # email_verified=TRUE optimistically for 'mx_unreachable' (domain exists but its @@ -729,7 +735,7 @@ def create_and_schedule_campaign( "name": name, "subject": base["subject"], "lists": [list_id], - "from_email": base["from_email"], + "from_email": FROM_EMAIL, "type": "regular", "content_type": base["content_type"], "body": base["body"], @@ -776,7 +782,7 @@ def send_test(base: dict, campaign_id: int, sample_row: tuple, label: str, tz: s list_ids = [l["id"] for l in base.get("lists", []) if isinstance(l, dict)] or [1] payload = { "name": base.get("name", "Test"), "subject": subj, - "lists": list_ids, "from_email": base["from_email"], + "lists": list_ids, "from_email": FROM_EMAIL, "type": "regular", "content_type": base["content_type"], "body": body, "altbody": _altbody_for(base, body), "template_id": base["template_id"], diff --git a/scripts/hc-bounce-watcher.sh b/scripts/hc-bounce-watcher.sh index 4e99a08..7a62cb8 100644 --- a/scripts/hc-bounce-watcher.sh +++ b/scripts/hc-bounce-watcher.sh @@ -17,8 +17,12 @@ TOKEN_FILE=/opt/performancewest/.secrets/hc-listmonk-token TOKEN="$(cat "$TOKEN_FILE" 2>/dev/null)" AUTHHDR="Authorization: token api:${TOKEN}" -# hc campaign senders -HC_SENDER1="from=" +# hc campaign senders. Bulk now sends from the dedicated bulk subdomain +# (compliance@send.performancewest.net); the root-domain sender is kept so the +# pre-cutover queue still drains correctly. (Transport-based tracking below also +# catches everything that egresses an hcout transport, regardless of sender.) +HC_SENDER1="from=" +HC_SENDER_LEGACY="from=" get_campaign_uuid() { curl -s -H "$AUTHHDR" "$API/api/campaigns?status=running&per_page=1" 2>/dev/null \ @@ -43,7 +47,7 @@ post_bounce() { tail -F "$LOG" 2>/dev/null | while IFS= read -r line; do # Track queue IDs that originate from the hc sender OR go out an hcout transport. - if echo "$line" | grep -q "$HC_SENDER1"; then + if echo "$line" | grep -qE "$HC_SENDER1|$HC_SENDER_LEGACY"; then QID=$(echo "$line" | sed -n 's/.*postfix\/[^[]*\[\([0-9]*\)\]: \([A-Z0-9]*\):.*/\2/p') [ -n "$QID" ] && HC_QIDS[$QID]=1 fi