Robustly wire email subjects from env vars with safe fallbacks and logging
This commit is contained in:
+24
-36
@@ -39,7 +39,6 @@ def _safe_filename(base: str, local: str, date_tag: str, ext: str) -> str:
|
|||||||
Uses mktemp for uniqueness but keeps the desired name pattern.
|
Uses mktemp for uniqueness but keeps the desired name pattern.
|
||||||
"""
|
"""
|
||||||
name = f"{base}-{local}-{date_tag}{ext}"
|
name = f"{base}-{local}-{date_tag}{ext}"
|
||||||
# Ensure uniqueness while preserving the logical name pattern
|
|
||||||
return tempfile.mktemp(prefix=name.replace(".", ""), suffix=ext)
|
return tempfile.mktemp(prefix=name.replace(".", ""), suffix=ext)
|
||||||
|
|
||||||
|
|
||||||
@@ -56,6 +55,17 @@ def _remove_file(path: str):
|
|||||||
logger.warning("Failed to remove file %s: %s", path, e)
|
logger.warning("Failed to remove file %s: %s", path, e)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_subject(env_var: str, default: str) -> str:
|
||||||
|
"""
|
||||||
|
Safely read an email subject from an environment variable.
|
||||||
|
Uses default if unset or blank. Logs the final value.
|
||||||
|
"""
|
||||||
|
value = (os.getenv(env_var) or "").strip()
|
||||||
|
subject = value or default
|
||||||
|
logger.info("Email subject [%s] = %s", env_var, subject)
|
||||||
|
return subject
|
||||||
|
|
||||||
|
|
||||||
def get_queue_position(task_id: str) -> int:
|
def get_queue_position(task_id: str) -> int:
|
||||||
"""
|
"""
|
||||||
Estimate the job's position in the queue.
|
Estimate the job's position in the queue.
|
||||||
@@ -80,12 +90,11 @@ def send_initial_email(to: str, queue_pos: int):
|
|||||||
Send initial confirmation email with queue position.
|
Send initial confirmation email with queue position.
|
||||||
Subject is customizable via EMAIL_SUBJECT_UPLOAD.
|
Subject is customizable via EMAIL_SUBJECT_UPLOAD.
|
||||||
"""
|
"""
|
||||||
subject = os.getenv(
|
subject = _get_subject(
|
||||||
"EMAIL_SUBJECT_UPLOAD",
|
"EMAIL_SUBJECT_UPLOAD",
|
||||||
"ScrAIbe: Your transcription request has been received",
|
"ScrAIbe: Your transcription request has been received",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build plain-text fallback
|
|
||||||
body = (
|
body = (
|
||||||
"Hello,\n\n"
|
"Hello,\n\n"
|
||||||
"We have received your audio file for transcription.\n"
|
"We have received your audio file for transcription.\n"
|
||||||
@@ -105,7 +114,6 @@ def send_initial_email(to: str, queue_pos: int):
|
|||||||
"This is an automated message from ScrAIbe.\n"
|
"This is an automated message from ScrAIbe.\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build HTML using template; only dynamic value is queue_position
|
|
||||||
html = None
|
html = None
|
||||||
try:
|
try:
|
||||||
html = load_template(
|
html = load_template(
|
||||||
@@ -133,12 +141,11 @@ def send_success_email(
|
|||||||
Send final email with transcript and attachments.
|
Send final email with transcript and attachments.
|
||||||
Subject is customizable via EMAIL_SUBJECT_SUCCESS.
|
Subject is customizable via EMAIL_SUBJECT_SUCCESS.
|
||||||
"""
|
"""
|
||||||
subject = os.getenv(
|
subject = _get_subject(
|
||||||
"EMAIL_SUBJECT_SUCCESS",
|
"EMAIL_SUBJECT_SUCCESS",
|
||||||
"ScrAIbe: Your transcript is ready",
|
"ScrAIbe: Your transcript is ready",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build plain-text fallback
|
|
||||||
body = (
|
body = (
|
||||||
"Hello,\n\n"
|
"Hello,\n\n"
|
||||||
"Your transcription is ready.\n\n"
|
"Your transcription is ready.\n\n"
|
||||||
@@ -161,12 +168,9 @@ def send_success_email(
|
|||||||
"This is an automated message from ScrAIbe.\n"
|
"This is an automated message from ScrAIbe.\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build HTML using template; no dynamic placeholders needed
|
|
||||||
html = None
|
html = None
|
||||||
try:
|
try:
|
||||||
html = load_template(
|
html = load_template("success_template.html")
|
||||||
"success_template.html",
|
|
||||||
)
|
|
||||||
except EmailError as e:
|
except EmailError as e:
|
||||||
logger.warning("Failed to render success template: %s", e)
|
logger.warning("Failed to render success template: %s", e)
|
||||||
|
|
||||||
@@ -188,12 +192,11 @@ def send_error_email(to: str, error_message: str, task_id: str):
|
|||||||
Send error notification email.
|
Send error notification email.
|
||||||
Subject is customizable via EMAIL_SUBJECT_ERROR.
|
Subject is customizable via EMAIL_SUBJECT_ERROR.
|
||||||
"""
|
"""
|
||||||
subject = os.getenv(
|
subject = _get_subject(
|
||||||
"EMAIL_SUBJECT_ERROR",
|
"EMAIL_SUBJECT_ERROR",
|
||||||
"ScrAIbe: Error with your transcription request",
|
"ScrAIbe: Error with your transcription request",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build plain-text fallback
|
|
||||||
body = (
|
body = (
|
||||||
"Hello,\n\n"
|
"Hello,\n\n"
|
||||||
"We encountered an error while processing your transcription request.\n\n"
|
"We encountered an error while processing your transcription request.\n\n"
|
||||||
@@ -205,7 +208,6 @@ def send_error_email(to: str, error_message: str, task_id: str):
|
|||||||
"This is an automated message from ScrAIbe.\n"
|
"This is an automated message from ScrAIbe.\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build HTML using template; only dynamic placeholder is exception
|
|
||||||
html = None
|
html = None
|
||||||
try:
|
try:
|
||||||
html = load_template(
|
html = load_template(
|
||||||
@@ -243,19 +245,15 @@ def process_transcription_task(
|
|||||||
"""
|
"""
|
||||||
task_id = self.request.id
|
task_id = self.request.id
|
||||||
|
|
||||||
# Ensure logging
|
|
||||||
log_level = os.getenv("LOG_LEVEL", "INFO")
|
log_level = os.getenv("LOG_LEVEL", "INFO")
|
||||||
setup_logging(level=log_level)
|
setup_logging(level=log_level)
|
||||||
|
|
||||||
# Track all temporary files to clean up later
|
|
||||||
temp_files = []
|
temp_files = []
|
||||||
|
|
||||||
# Derive naming components
|
|
||||||
local = _local_part(email_to)
|
local = _local_part(email_to)
|
||||||
date_tag = _date_tag()
|
date_tag = _date_tag()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 1) Determine queue position and send initial email
|
# 1) Queue position and initial email
|
||||||
queue_pos = get_queue_position(task_id)
|
queue_pos = get_queue_position(task_id)
|
||||||
send_initial_email(to=email_to, queue_pos=queue_pos)
|
send_initial_email(to=email_to, queue_pos=queue_pos)
|
||||||
|
|
||||||
@@ -270,7 +268,7 @@ def process_transcription_task(
|
|||||||
)
|
)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# 3) Perform transcription
|
# 3) Transcription
|
||||||
if task_type == "transcript_and_summarize":
|
if task_type == "transcript_and_summarize":
|
||||||
result = scraibe.transcript_and_summarize(
|
result = scraibe.transcript_and_summarize(
|
||||||
audio_file=audio_path,
|
audio_file=audio_path,
|
||||||
@@ -296,21 +294,21 @@ def process_transcription_task(
|
|||||||
segments = result.get("segments", [])
|
segments = result.get("segments", [])
|
||||||
raw_result = result.get("raw_result")
|
raw_result = result.get("raw_result")
|
||||||
|
|
||||||
# 4) Prepare files for email with required naming
|
# 4) Prepare files
|
||||||
|
|
||||||
# Transcript as .md
|
# Transcript .md
|
||||||
md_transcript_path = _safe_filename("TRANSCRIPT", local, date_tag, ".md")
|
md_transcript_path = _safe_filename("TRANSCRIPT", local, date_tag, ".md")
|
||||||
with open(md_transcript_path, "w", encoding="utf-8") as f:
|
with open(md_transcript_path, "w", encoding="utf-8") as f:
|
||||||
f.write("# Transcript\n\n")
|
f.write("# Transcript\n\n")
|
||||||
f.write(transcript_text)
|
f.write(transcript_text)
|
||||||
temp_files.append(md_transcript_path)
|
temp_files.append(md_transcript_path)
|
||||||
|
|
||||||
# Transcript as .docx (with required style)
|
# Transcript .docx
|
||||||
docx_transcript_path = _safe_filename("TRANSCRIPT", local, date_tag, ".docx")
|
docx_transcript_path = _safe_filename("TRANSCRIPT", local, date_tag, ".docx")
|
||||||
create_transcript_docx(transcript_text, docx_transcript_path)
|
create_transcript_docx(transcript_text, docx_transcript_path)
|
||||||
temp_files.append(docx_transcript_path)
|
temp_files.append(docx_transcript_path)
|
||||||
|
|
||||||
# JSON with diarization as SOURCE
|
# JSON as SOURCE
|
||||||
json_data = {
|
json_data = {
|
||||||
"task": task_type,
|
"task": task_type,
|
||||||
"transcript": transcript_text,
|
"transcript": transcript_text,
|
||||||
@@ -320,10 +318,8 @@ def process_transcription_task(
|
|||||||
"job_id": task_id,
|
"job_id": task_id,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if summary_text:
|
if summary_text:
|
||||||
json_data["summary"] = summary_text
|
json_data["summary"] = summary_text
|
||||||
|
|
||||||
if raw_result is not None:
|
if raw_result is not None:
|
||||||
json_data["raw_result"] = raw_result
|
json_data["raw_result"] = raw_result
|
||||||
|
|
||||||
@@ -332,7 +328,7 @@ def process_transcription_task(
|
|||||||
json.dump(json_data, f, indent=2, ensure_ascii=False)
|
json.dump(json_data, f, indent=2, ensure_ascii=False)
|
||||||
temp_files.append(json_path)
|
temp_files.append(json_path)
|
||||||
|
|
||||||
# Summary as .md (only when summary is available)
|
# Summary files (if present)
|
||||||
if summary_text:
|
if summary_text:
|
||||||
md_summary_path = _safe_filename("SUMMARY", local, date_tag, ".md")
|
md_summary_path = _safe_filename("SUMMARY", local, date_tag, ".md")
|
||||||
with open(md_summary_path, "w", encoding="utf-8") as f:
|
with open(md_summary_path, "w", encoding="utf-8") as f:
|
||||||
@@ -340,22 +336,17 @@ def process_transcription_task(
|
|||||||
f.write(summary_text)
|
f.write(summary_text)
|
||||||
temp_files.append(md_summary_path)
|
temp_files.append(md_summary_path)
|
||||||
|
|
||||||
# Summary as .docx
|
|
||||||
docx_summary_path = _safe_filename("SUMMARY", local, date_tag, ".docx")
|
docx_summary_path = _safe_filename("SUMMARY", local, date_tag, ".docx")
|
||||||
create_summary_docx(summary_text, docx_summary_path)
|
create_summary_docx(summary_text, docx_summary_path)
|
||||||
temp_files.append(docx_summary_path)
|
temp_files.append(docx_summary_path)
|
||||||
|
|
||||||
# All attachments
|
|
||||||
attachments = [
|
attachments = [
|
||||||
md_transcript_path,
|
md_transcript_path,
|
||||||
docx_transcript_path,
|
docx_transcript_path,
|
||||||
json_path,
|
json_path,
|
||||||
]
|
]
|
||||||
if summary_text:
|
if summary_text:
|
||||||
attachments += [
|
attachments += [md_summary_path, docx_summary_path]
|
||||||
md_summary_path,
|
|
||||||
docx_summary_path,
|
|
||||||
]
|
|
||||||
|
|
||||||
# 5) Send success email
|
# 5) Send success email
|
||||||
send_success_email(
|
send_success_email(
|
||||||
@@ -377,12 +368,9 @@ def process_transcription_task(
|
|||||||
)
|
)
|
||||||
raise e
|
raise e
|
||||||
finally:
|
finally:
|
||||||
# 6) Cleanup temporary files (best-effort)
|
# 6) Cleanup
|
||||||
for path in temp_files:
|
for path in temp_files:
|
||||||
_remove_file(path)
|
_remove_file(path)
|
||||||
|
|
||||||
# Also remove uploaded audio file
|
|
||||||
if audio_path:
|
if audio_path:
|
||||||
_remove_file(audio_path)
|
_remove_file(audio_path)
|
||||||
|
|
||||||
logger.info("Cleanup completed for job %s.", task_id)
|
logger.info("Cleanup completed for job %s.", task_id)
|
||||||
|
|||||||
Reference in New Issue
Block a user