Inherit email link addresses from hosting and proxy settings
This commit is contained in:
@@ -32,7 +32,7 @@ def worker_enabled() -> bool:
|
||||
def delivery_ready() -> tuple[bool, str]:
|
||||
config = store.settings()
|
||||
if not config["public_url"]:
|
||||
return False, "Set the public Magent address for email links."
|
||||
return False, "Set the application URL in Hosting & proxy for email links."
|
||||
ready, detail = smtp_email_config_ready()
|
||||
if not ready:
|
||||
return False, detail
|
||||
@@ -147,7 +147,7 @@ async def preview(user: dict, month: str | None) -> dict:
|
||||
selected = completed_month(month)
|
||||
config = store.settings()
|
||||
if not config["public_url"]:
|
||||
raise RecapError("Save the public Magent address before previewing an email.")
|
||||
raise RecapError("Set the application URL in Hosting & proxy before previewing an email.")
|
||||
try:
|
||||
report = await asyncio.wait_for(get_monthly_report(account, selected), timeout=180)
|
||||
except HistoryLimitError as exc:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from .public_urls import magent_public_url
|
||||
"""Independent newsletter consent and immutable edition snapshots using the shared email queue."""
|
||||
|
||||
import hashlib
|
||||
@@ -63,6 +64,7 @@ def init_schema(conn):
|
||||
|
||||
def settings() -> dict:
|
||||
result = read_one('SELECT * FROM newsletter_settings WHERE id=1')
|
||||
result['public_url'] = magent_public_url(result['public_url'])
|
||||
result['enabled'] = bool(result['enabled'])
|
||||
return result
|
||||
|
||||
@@ -79,6 +81,7 @@ def next_due(now: datetime, weekday: int, hour: int) -> datetime:
|
||||
|
||||
|
||||
def save_settings(values: dict, now: datetime):
|
||||
values = {**values, "public_url": magent_public_url(values.get("public_url", ""))}
|
||||
with transaction() as conn:
|
||||
old = dict(conn.execute('SELECT * FROM newsletter_settings WHERE id=1').fetchone())
|
||||
if old['revision'] != values['revision']:
|
||||
@@ -246,7 +249,8 @@ def enqueue_test(sub, identity, revision, request_id, public_url, now):
|
||||
|
||||
def enqueue_due(now):
|
||||
with transaction() as conn:
|
||||
config = conn.execute('SELECT * FROM newsletter_settings WHERE id=1').fetchone()
|
||||
config = dict(conn.execute('SELECT * FROM newsletter_settings WHERE id=1').fetchone())
|
||||
config['public_url'] = magent_public_url(config['public_url'])
|
||||
rows = conn.execute("SELECT * FROM newsletter_editions WHERE state='scheduled' AND send_at<=?", (now,)).fetchall()
|
||||
for raw in rows:
|
||||
row = unpack(raw)
|
||||
|
||||
@@ -32,7 +32,7 @@ def playback_url(runtime) -> str:
|
||||
def delivery_ready(public_url=None):
|
||||
config = store.settings()
|
||||
if not (public_url if public_url is not None else config['public_url']):
|
||||
return False, 'Set the public Magent address for newsletter email links.'
|
||||
return False, 'Set the application URL in Hosting & proxy for newsletter email links.'
|
||||
runtime = get_runtime_settings()
|
||||
if not runtime.jellyfin_base_url or not runtime.jellyfin_api_key:
|
||||
return False, 'Connect Jellyfin to collect new arrivals.'
|
||||
@@ -150,7 +150,7 @@ async def preview(identity, revision):
|
||||
runtime = get_runtime_settings()
|
||||
config = store.settings()
|
||||
if not config['public_url'] or not playback_url(runtime):
|
||||
raise NewsletterError('Set the public Magent and Jellyfin addresses before previewing.')
|
||||
raise NewsletterError('Check the application URL in Hosting & proxy and the public playback URL in Jellyfin settings before previewing.')
|
||||
if row['content']['source'] != source_key(runtime.jellyfin_base_url) or row['content']['playback_url'] != playback_url(runtime):
|
||||
raise NewsletterError('The Jellyfin connection or public address changed. Create a fresh draft.')
|
||||
content = {**row['content'], 'subject': row['subject'], 'intro': row['intro']}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
"""Configured public email links, independent of request Host/forwarded headers."""
|
||||
from urllib.parse import urlsplit
|
||||
from ..runtime import get_runtime_settings
|
||||
|
||||
|
||||
def valid_public_url(value):
|
||||
value = str(value or '').strip().rstrip('/')
|
||||
try:
|
||||
parsed = urlsplit(value)
|
||||
if (parsed.scheme in {'http', 'https'} and parsed.hostname
|
||||
and not (parsed.username or parsed.password or parsed.query or parsed.fragment)
|
||||
and (parsed.port is None or parsed.port > 0)
|
||||
and not any(c.isspace() or ord(c) < 33 or c in '<>"\\' for c in value)):
|
||||
return value
|
||||
except ValueError:
|
||||
pass
|
||||
return ''
|
||||
|
||||
|
||||
def magent_public_url(legacy_url=''):
|
||||
runtime = get_runtime_settings()
|
||||
proxy = getattr(runtime, 'magent_proxy_base_url', None)
|
||||
application = getattr(runtime, 'magent_application_url', None)
|
||||
if getattr(runtime, 'magent_proxy_enabled', False) and str(proxy or '').strip():
|
||||
return valid_public_url(proxy)
|
||||
if str(application or '').strip():
|
||||
return valid_public_url(application)
|
||||
# Preserve pre-existing installations until Hosting & proxy has been configured.
|
||||
return valid_public_url(legacy_url)
|
||||
@@ -1,3 +1,4 @@
|
||||
from .public_urls import magent_public_url
|
||||
"""Durable consent, schedule and delivery records for personal email recaps."""
|
||||
|
||||
import hashlib
|
||||
@@ -73,6 +74,7 @@ def read_one(sql: str, args=()) -> dict | None:
|
||||
|
||||
def settings() -> dict:
|
||||
row = read_one("SELECT * FROM email_recap_settings WHERE id = 1")
|
||||
row["public_url"] = magent_public_url(row["public_url"])
|
||||
return {key: (bool(value) if key == "enabled" else value) for key, value in row.items() if key != "id"}
|
||||
|
||||
|
||||
@@ -82,6 +84,7 @@ def next_due(now: datetime, day: int, hour: int) -> datetime:
|
||||
|
||||
|
||||
def save_settings(values: dict, now: datetime) -> dict:
|
||||
values = {**values, "public_url": magent_public_url(values.get("public_url", ""))}
|
||||
with transaction() as conn:
|
||||
old = dict(conn.execute("SELECT * FROM email_recap_settings WHERE id = 1").fetchone())
|
||||
changed = any(old[key] != values[key] for key in ("day", "hour", "public_url"))
|
||||
@@ -174,6 +177,7 @@ def enqueue_test(sub: dict, month: str, request_id: str, public_url: str, now: f
|
||||
def enqueue_due(now: datetime) -> int:
|
||||
with transaction() as conn:
|
||||
config = dict(conn.execute("SELECT * FROM email_recap_settings WHERE id=1").fetchone())
|
||||
config["public_url"] = magent_public_url(config["public_url"])
|
||||
if not config["enabled"] or not config["next_send_at"] or config["next_send_at"] > now.timestamp():
|
||||
return 0
|
||||
# After long downtime, send only the latest due recap; never backfill a pile of old emails.
|
||||
|
||||
Reference in New Issue
Block a user