feat(deliverability): send bulk campaigns from dedicated subdomain send.performancewest.net
Isolates bulk sending reputation onto a dedicated subdomain so the root domain stays clean for transactional/verification mail (and recovers faster). Replies still go to the root domain via Reply-To, so the customer-facing reply experience is unchanged. - build_trucking_campaigns.py: add env-overridable FROM_EMAIL (noreply@send.performancewest.net); use it for both scheduled + test sends instead of inheriting base["from_email"] from the DB base campaign. - build_healthcare_campaigns_cron.py: FROM_EMAIL -> compliance@send.performancewest.net (env-overridable). - bounce-watcher.sh / hc-bounce-watcher.sh: track the new subdomain envelope sender (keep legacy root-domain sender so the pre-cutover queue still drains; HC also tracks by hcout transport regardless of sender). Infra already live (separate, non-code): subdomain DNS (A/MX/SPF/DKIM selector=send/DMARC p=reject) on the Hestia master, OpenDKIM signs d=send.performancewest.net (verified end-to-end), egress .94/.107. Root SPF trimmed to the real IPs; pointless IP-rehab cron disabled.
This commit is contained in:
parent
1056705cf9
commit
5c3b4291e7
4 changed files with 28 additions and 9 deletions
|
|
@ -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=<noreply@performancewest.net>"; 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=<noreply@send.performancewest.net>|from=<noreply@performancewest.net>"; then
|
||||
QID=$(echo "$line" | sed -n 's/.*postfix\/[^[]*\[\([0-9]*\)\]: \([A-Z0-9]*\):.*/\2/p')
|
||||
if [ -n "$QID" ]; then
|
||||
CAMPAIGN_QIDS[$QID]=1
|
||||
|
|
|
|||
|
|
@ -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 <compliance@performancewest.net>"
|
||||
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 <compliance@send.performancewest.net>",
|
||||
)
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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 <noreply@send.performancewest.net>")
|
||||
|
||||
# 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"],
|
||||
|
|
|
|||
|
|
@ -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=<compliance@performancewest.net>"
|
||||
# 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=<compliance@send.performancewest.net>"
|
||||
HC_SENDER_LEGACY="from=<compliance@performancewest.net>"
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue