Make email template placeholders configurable via environment variables
Mirror and run GitLab CI / build (push) Has been cancelled
Ruff / ruff (push) Has been cancelled

This commit is contained in:
admin
2026-06-14 15:11:53 +00:00
parent 85cdd9216a
commit 917a7b8f2f
3 changed files with 46 additions and 15 deletions
+31 -3
View File
@@ -4,6 +4,7 @@ Email sender module for ScrAIbe.
Sends transcription outputs (TXT, JSON, etc.) via SMTP.
All credentials are configured via environment variables.
Supports both plain text and HTML email bodies.
Template placeholders are primarily filled via environment variables.
"""
import os
@@ -13,7 +14,7 @@ from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from typing import List, Optional
from typing import List, Optional, Dict, Any
logger = logging.getLogger("scraibe.email_sender")
@@ -52,7 +53,31 @@ def get_email_config():
}
def load_template(template_name: str, **kwargs) -> str:
def build_template_context(**runtime_kwargs: Any) -> Dict[str, Any]:
"""
Build a context dict for templates from:
- environment variables (base, customizable)
- runtime-provided values (override env if present)
Environment variables:
- EMAIL_CONTACT_ADDRESS: value for {contact_email}
- EMAIL_CSS_PATH: value for {css_path}
Runtime kwargs are merged on top (e.g. queue_position, exception).
"""
ctx: Dict[str, Any] = {
"contact_email": os.getenv("EMAIL_CONTACT_ADDRESS", "support@example.com"),
"css_path": os.getenv("EMAIL_CSS_PATH", ""),
}
# Runtime values override env if provided
if runtime_kwargs:
ctx.update(runtime_kwargs)
return ctx
def load_template(template_name: str, **runtime_kwargs: Any) -> str:
"""
Load an HTML email template from misc/ and render placeholders.
@@ -70,9 +95,12 @@ def load_template(template_name: str, **kwargs) -> str:
with open(path, "r", encoding="utf-8") as f:
template = f.read()
# Build context from env + runtime
ctx = build_template_context(**runtime_kwargs)
# Replace {placeholder} style variables safely
try:
return template.format(**kwargs)
return template.format(**ctx)
except KeyError as e:
raise EmailError(f"Missing template variable: {e}")
+9 -12
View File
@@ -15,9 +15,6 @@ from .email_sender import send_email, EmailError, load_template
logger = logging.getLogger("scraibe.tasks")
# Contact email used in templates; can be overridden via env
CONTACT_EMAIL = os.getenv("EMAIL_CONTACT_ADDRESS", "support@example.com")
def get_queue_position(task_id: str) -> int:
"""
@@ -42,6 +39,7 @@ def get_queue_position(task_id: str) -> int:
def send_initial_email(to: str, queue_pos: int):
"""
Send initial confirmation email with queue position using HTML template.
Static placeholders (contact_email, css_path) come from env via load_template.
"""
subject = "ScrAIbe: Your transcription request has been received"
@@ -61,17 +59,16 @@ def send_initial_email(to: str, queue_pos: int):
"You will receive an email with your transcript (and summary, if requested) "
"once processing is complete.\n\n"
"If you have any questions, contact us at "
f"{CONTACT_EMAIL}.\n\n"
f"{os.getenv('EMAIL_CONTACT_ADDRESS', 'support@example.com')}.\n\n"
"This is an automated message from ScrAIbe.\n"
)
# Build HTML using template
# Build HTML using template; only dynamic value is queue_position
html = None
try:
html = load_template(
"upload_notification_template.html",
queue_position=str(queue_pos) if queue_pos > 0 else "the queue",
contact_email=CONTACT_EMAIL,
)
except EmailError as e:
logger.warning("Failed to render upload notification template: %s", e)
@@ -92,6 +89,7 @@ def send_success_email(
):
"""
Send final email with transcript and attachments using HTML template.
Static placeholders (contact_email, css_path) come from env via load_template.
"""
subject = "ScrAIbe: Your transcript is ready"
@@ -114,16 +112,15 @@ def send_success_email(
"\n"
"Job ID: " + str(task_id) + "\n\n"
"If you have any questions, contact us at "
f"{CONTACT_EMAIL}.\n\n"
f"{os.getenv('EMAIL_CONTACT_ADDRESS', 'support@example.com')}.\n\n"
"This is an automated message from ScrAIbe.\n"
)
# Build HTML using template
# Build HTML using template; no dynamic placeholders needed
html = None
try:
html = load_template(
"success_template.html",
contact_email=CONTACT_EMAIL,
)
except EmailError as e:
logger.warning("Failed to render success template: %s", e)
@@ -144,6 +141,7 @@ def send_success_email(
def send_error_email(to: str, error_message: str, task_id: str):
"""
Send error notification email using HTML template.
Static placeholders (contact_email, css_path) come from env via load_template.
"""
subject = "ScrAIbe: Error with your transcription request"
@@ -155,17 +153,16 @@ def send_error_email(to: str, error_message: str, task_id: str):
"Job ID: " + str(task_id) + "\n\n"
"Please contact your administrator if the problem persists.\n\n"
"If you have any questions, contact us at "
f"{CONTACT_EMAIL}.\n\n"
f"{os.getenv('EMAIL_CONTACT_ADDRESS', 'support@example.com')}.\n\n"
"This is an automated message from ScrAIbe.\n"
)
# Build HTML using template
# Build HTML using template; only dynamic placeholder is exception
html = None
try:
html = load_template(
"error_notification_template.html",
exception=str(error_message),
contact_email=CONTACT_EMAIL,
)
except EmailError as e:
logger.warning("Failed to render error template: %s", e)