From f7c9c70bfc8d95fbb751caa271eff48b36e445af Mon Sep 17 00:00:00 2001 From: admin Date: Sun, 14 Jun 2026 16:31:03 +0000 Subject: [PATCH] Robustly wire email subjects from env vars with safe fallbacks and logging --- scraibe/tasks.py | 60 +++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/scraibe/tasks.py b/scraibe/tasks.py index af7dc9f..8da6a9f 100644 --- a/scraibe/tasks.py +++ b/scraibe/tasks.py @@ -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. """ name = f"{base}-{local}-{date_tag}{ext}" - # Ensure uniqueness while preserving the logical name pattern 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) +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: """ 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. Subject is customizable via EMAIL_SUBJECT_UPLOAD. """ - subject = os.getenv( + subject = _get_subject( "EMAIL_SUBJECT_UPLOAD", "ScrAIbe: Your transcription request has been received", ) - # Build plain-text fallback body = ( "Hello,\n\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" ) - # Build HTML using template; only dynamic value is queue_position html = None try: html = load_template( @@ -133,12 +141,11 @@ def send_success_email( Send final email with transcript and attachments. Subject is customizable via EMAIL_SUBJECT_SUCCESS. """ - subject = os.getenv( + subject = _get_subject( "EMAIL_SUBJECT_SUCCESS", "ScrAIbe: Your transcript is ready", ) - # Build plain-text fallback body = ( "Hello,\n\n" "Your transcription is ready.\n\n" @@ -161,12 +168,9 @@ def send_success_email( "This is an automated message from ScrAIbe.\n" ) - # Build HTML using template; no dynamic placeholders needed html = None try: - html = load_template( - "success_template.html", - ) + html = load_template("success_template.html") except EmailError as 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. Subject is customizable via EMAIL_SUBJECT_ERROR. """ - subject = os.getenv( + subject = _get_subject( "EMAIL_SUBJECT_ERROR", "ScrAIbe: Error with your transcription request", ) - # Build plain-text fallback body = ( "Hello,\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" ) - # Build HTML using template; only dynamic placeholder is exception html = None try: html = load_template( @@ -243,19 +245,15 @@ def process_transcription_task( """ task_id = self.request.id - # Ensure logging log_level = os.getenv("LOG_LEVEL", "INFO") setup_logging(level=log_level) - # Track all temporary files to clean up later temp_files = [] - - # Derive naming components local = _local_part(email_to) date_tag = _date_tag() try: - # 1) Determine queue position and send initial email + # 1) Queue position and initial email queue_pos = get_queue_position(task_id) send_initial_email(to=email_to, queue_pos=queue_pos) @@ -270,7 +268,7 @@ def process_transcription_task( ) raise - # 3) Perform transcription + # 3) Transcription if task_type == "transcript_and_summarize": result = scraibe.transcript_and_summarize( audio_file=audio_path, @@ -296,21 +294,21 @@ def process_transcription_task( segments = result.get("segments", []) 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") with open(md_transcript_path, "w", encoding="utf-8") as f: f.write("# Transcript\n\n") f.write(transcript_text) temp_files.append(md_transcript_path) - # Transcript as .docx (with required style) + # Transcript .docx docx_transcript_path = _safe_filename("TRANSCRIPT", local, date_tag, ".docx") create_transcript_docx(transcript_text, docx_transcript_path) temp_files.append(docx_transcript_path) - # JSON with diarization as SOURCE + # JSON as SOURCE json_data = { "task": task_type, "transcript": transcript_text, @@ -320,10 +318,8 @@ def process_transcription_task( "job_id": task_id, }, } - if summary_text: json_data["summary"] = summary_text - if raw_result is not None: json_data["raw_result"] = raw_result @@ -332,7 +328,7 @@ def process_transcription_task( json.dump(json_data, f, indent=2, ensure_ascii=False) temp_files.append(json_path) - # Summary as .md (only when summary is available) + # Summary files (if present) if summary_text: md_summary_path = _safe_filename("SUMMARY", local, date_tag, ".md") with open(md_summary_path, "w", encoding="utf-8") as f: @@ -340,22 +336,17 @@ def process_transcription_task( f.write(summary_text) temp_files.append(md_summary_path) - # Summary as .docx docx_summary_path = _safe_filename("SUMMARY", local, date_tag, ".docx") create_summary_docx(summary_text, docx_summary_path) temp_files.append(docx_summary_path) - # All attachments attachments = [ md_transcript_path, docx_transcript_path, json_path, ] if summary_text: - attachments += [ - md_summary_path, - docx_summary_path, - ] + attachments += [md_summary_path, docx_summary_path] # 5) Send success email send_success_email( @@ -377,12 +368,9 @@ def process_transcription_task( ) raise e finally: - # 6) Cleanup temporary files (best-effort) + # 6) Cleanup for path in temp_files: _remove_file(path) - - # Also remove uploaded audio file if audio_path: _remove_file(audio_path) - logger.info("Cleanup completed for job %s.", task_id)