Fall back to an unhashed logo URL if ManifestStaticFilesStorage misses, and run collectstatic in the worker entrypoint.
84 lines
2.6 KiB
Python
84 lines
2.6 KiB
Python
"""Shared context for branded HTML/text emails (public site palette)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import html
|
|
import logging
|
|
import re
|
|
|
|
from django.conf import settings
|
|
from django.contrib.staticfiles.storage import staticfiles_storage
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_URL_RE = re.compile(r"(https?://[^\s<]+)")
|
|
_LOGO_STATIC_PATH = "brand/exit_logo.png"
|
|
|
|
|
|
def _absolute_static_url(site_url: str, relative: str) -> str:
|
|
"""
|
|
Build an absolute URL for a static asset.
|
|
|
|
Prefer the hashed Manifest URL when available. Fall back to the stable
|
|
path when the manifest is missing (dj-queue worker does not run
|
|
collectstatic) so sending mail never crashes.
|
|
"""
|
|
try:
|
|
path = staticfiles_storage.url(relative)
|
|
except ValueError:
|
|
logger.debug(
|
|
"staticfiles manifest miss for %s; using unhashed URL", relative
|
|
)
|
|
static_prefix = settings.STATIC_URL or "/static/"
|
|
path = f"{static_prefix}{relative.lstrip('/')}"
|
|
|
|
if path.startswith("http://") or path.startswith("https://"):
|
|
return path
|
|
if not path.startswith("/"):
|
|
path = f"/{path}"
|
|
return f"{site_url}{path}"
|
|
|
|
|
|
def email_brand_context(**extra):
|
|
site_url = (getattr(settings, "PUBLIC_SITE_URL", None) or "").rstrip("/")
|
|
if not site_url:
|
|
site_url = "https://mkdrealtor.com"
|
|
|
|
logo_url = _absolute_static_url(site_url, _LOGO_STATIC_PATH)
|
|
|
|
brand_name = getattr(settings, "SITE_NAME", None) or "Monica Dhillon"
|
|
brand_legal = getattr(settings, "CREDIT_NAME", None) or brand_name
|
|
tagline = getattr(settings, "SITE_TAGLINE", None) or ""
|
|
host_label = site_url.replace("https://", "").replace("http://", "")
|
|
|
|
return {
|
|
"site_url": site_url,
|
|
"logo_url": logo_url,
|
|
"brand_name": brand_name,
|
|
"brand_legal": brand_legal,
|
|
"brand_tagline": tagline,
|
|
"host_label": host_label,
|
|
**extra,
|
|
}
|
|
|
|
|
|
def plain_text_to_email_html(text: str) -> str:
|
|
"""Escape plain text and turn paragraphs / URLs into simple HTML."""
|
|
raw = (text or "").replace("\r\n", "\n").strip()
|
|
if not raw:
|
|
return ""
|
|
|
|
blocks: list[str] = []
|
|
for para in re.split(r"\n\s*\n", raw):
|
|
lines = [html.escape(line) for line in para.split("\n")]
|
|
joined = "<br>\n".join(lines)
|
|
joined = _URL_RE.sub(
|
|
r'<a href="\1" style="color:#00626c;text-decoration:underline;">\1</a>',
|
|
joined,
|
|
)
|
|
blocks.append(
|
|
f'<p style="margin:0 0 16px;color:#212121;font-size:15px;'
|
|
f'line-height:1.6;">{joined}</p>'
|
|
)
|
|
return "\n".join(blocks)
|