108 lines
4.5 KiB
Python
108 lines
4.5 KiB
Python
"""
|
|
app/utils/mail_utils.py
|
|
-----------------------
|
|
Helpers for constructing outbound email sender identities.
|
|
|
|
`branded_sender()` returns a Flask-Mail sender as a ``(display_name, address)``
|
|
tuple so outbound branded email (currently the customer invitation) shows a
|
|
per-domain identity that tracks the host the user is on — WITHOUT risking
|
|
deliverability.
|
|
|
|
Two independent things vary by domain:
|
|
|
|
1. DISPLAY NAME (what the recipient sees, e.g. "Gov Services QC")
|
|
Always applied. Costs nothing, needs no DNS. This is the safe default.
|
|
|
|
2. FROM ADDRESS (the actual @domain, e.g. jqc.noreply@govservicesinc.com)
|
|
Only used for domains that are KNOWN to authorize this mail server
|
|
(the authenticated sender's own domain, plus anything you add to
|
|
SENDER_AUTHORIZED_DOMAINS). Every other domain keeps the authenticated
|
|
address so the message still passes SPF/DMARC and delivers.
|
|
|
|
Result, with no DNS work:
|
|
Invited from jqc.govservicesinc.com ->
|
|
From: "Gov Services QC" <jqc.noreply@ltservicesinc.com>
|
|
(branded NAME, deliverable authenticated ADDRESS)
|
|
|
|
Once govservicesinc.com's DNS authorizes this mail server (SPF include + DKIM),
|
|
add it to SENDER_AUTHORIZED_DOMAINS and it upgrades to:
|
|
From: "Gov Services QC" <jqc.noreply@govservicesinc.com>
|
|
|
|
See CLAUDE.md rule 64.
|
|
"""
|
|
|
|
from urllib.parse import urlparse
|
|
from flask import current_app
|
|
|
|
# ── Per-domain display names (edit as new brands launch) ─────────────────────
|
|
# Keyed by registrable domain. A domain not listed here falls back to
|
|
# DEFAULT_BRAND_NAME so the From never renders an ugly auto-derived label.
|
|
BRAND_NAMES = {
|
|
'ltservicesinc.com': 'LT Services QC',
|
|
'govservicesinc.com': 'Gov Services QC',
|
|
'efs.com': 'EFS QC',
|
|
}
|
|
DEFAULT_BRAND_NAME = 'Janitorial QC'
|
|
|
|
# ── Domains cleared to use a BRANDED FROM ADDRESS ────────────────────────────
|
|
# Add a registrable domain here ONLY after its DNS authorizes this mail server
|
|
# (SPF `include:` + DKIM). Until then the domain still gets its branded display
|
|
# NAME but sends from the authenticated address, so it always delivers.
|
|
# The authenticated sender's own domain is always treated as authorized and does
|
|
# NOT need to be listed here.
|
|
SENDER_AUTHORIZED_DOMAINS = {
|
|
# 'govservicesinc.com', # ← uncomment once SPF+DKIM are live for it
|
|
# 'efs.com',
|
|
}
|
|
|
|
|
|
def _authenticated_sender() -> str:
|
|
"""The SMTP identity we authenticate as — always deliverable."""
|
|
return (current_app.config.get('MAIL_DEFAULT_SENDER')
|
|
or current_app.config.get('MAIL_USERNAME')
|
|
or 'jqc.noreply@janitorialqc.local')
|
|
|
|
|
|
def _host_domain(base_url: str | None) -> str | None:
|
|
"""Registrable domain (last two labels) of base_url, or None if unparseable."""
|
|
base = (base_url or current_app.config.get('APP_BASE_URL', '') or '').strip().rstrip('/')
|
|
if not base:
|
|
return None
|
|
netloc = urlparse(base).netloc or urlparse('//' + base).netloc
|
|
host = netloc.split('@')[-1].split(':')[0].strip().lower() # drop userinfo/port
|
|
if not host or '.' not in host:
|
|
return None
|
|
labels = [l for l in host.split('.') if l]
|
|
return '.'.join(labels[-2:]) if len(labels) >= 2 else host
|
|
|
|
|
|
def branded_sender(base_url: str | None = None):
|
|
"""Return a ``(display_name, address)`` sender tuple for branded email.
|
|
|
|
The display name always tracks the host's domain; the address is branded
|
|
only for the authenticated domain and any SENDER_AUTHORIZED_DOMAINS, and
|
|
otherwise stays the authenticated address so the mail still delivers.
|
|
|
|
Falls back to the bare authenticated sender string whenever the host cannot
|
|
be parsed (localhost, empty, no dot), so this can never yield an invalid From.
|
|
"""
|
|
auth_sender = _authenticated_sender()
|
|
if '@' not in auth_sender:
|
|
return auth_sender
|
|
local, auth_domain = auth_sender.rsplit('@', 1)
|
|
auth_domain = auth_domain.lower()
|
|
|
|
domain = _host_domain(base_url)
|
|
if not domain:
|
|
# Unknown host → safe authenticated address, generic brand name.
|
|
return (DEFAULT_BRAND_NAME, auth_sender)
|
|
|
|
display_name = BRAND_NAMES.get(domain, DEFAULT_BRAND_NAME)
|
|
|
|
if domain == auth_domain or domain in SENDER_AUTHORIZED_DOMAINS:
|
|
address = f'{local}@{domain}' # branded address — DNS-authorized
|
|
else:
|
|
address = auth_sender # keep deliverable authenticated address
|
|
|
|
return (display_name, address)
|