Fix Bestätigung email: send synchronously for immediate error feedback (STI-77)
The Bestätigung email was sent via Celery task (fire-and-forget), so the UI always showed "wird gesendet" even when the task failed silently in the worker. Now sends synchronously from the web process (matching the working test email pattern) with proper error display to the user. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -702,19 +702,16 @@ def send_onboarding_einladung(self, einladung_id, base_url=None):
|
||||
raise self.retry(exc=exc)
|
||||
|
||||
|
||||
@shared_task(bind=True, max_retries=3, default_retry_delay=300)
|
||||
def send_bestaetigung(self, destinataer_id, base_url=None):
|
||||
def _send_bestaetigung_sync(destinataer_id):
|
||||
"""
|
||||
Generiert ein Bestätigungsschreiben (PDF) für einen Destinatär und sendet es
|
||||
per E-Mail. Das PDF wird zusätzlich im DMS unter Kontext "korrespondenz" abgelegt.
|
||||
|
||||
Args:
|
||||
destinataer_id: UUID des Destinatärs
|
||||
base_url: Basis-URL der Anwendung (für Konsistenz mit anderen Tasks)
|
||||
Kann direkt (synchron) oder via Celery-Task aufgerufen werden.
|
||||
Bei Fehlern wird eine Exception geworfen (kein stilles Verschlucken).
|
||||
"""
|
||||
from decimal import Decimal
|
||||
from django.core.files.base import ContentFile
|
||||
from django.template.loader import render_to_string
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from django.utils import timezone
|
||||
|
||||
@@ -772,7 +769,7 @@ def send_bestaetigung(self, destinataer_id, base_url=None):
|
||||
pdf_bytes = HTML(string=html_content).write_pdf()
|
||||
except Exception as exc:
|
||||
logger.error("send_bestaetigung: PDF-Generierung fehlgeschlagen: %s", exc)
|
||||
raise self.retry(exc=exc)
|
||||
raise
|
||||
|
||||
# PDF im DMS ablegen
|
||||
filename = (
|
||||
@@ -803,17 +800,23 @@ def send_bestaetigung(self, destinataer_id, base_url=None):
|
||||
from_email = _get_smtp_from_email()
|
||||
to_email = destinataer.email
|
||||
|
||||
connection = _get_smtp_connection()
|
||||
msg = EmailMultiAlternatives(subject, "", from_email, [to_email], connection=connection)
|
||||
msg.attach_alternative(html_body, "text/html")
|
||||
if pdf_bytes:
|
||||
msg.attach(filename, pdf_bytes, "application/pdf")
|
||||
msg.send()
|
||||
logger.info("Bestätigung gesendet an %s (Destinatär %s)", to_email, destinataer_id)
|
||||
return {"status": "sent", "destinataer_id": str(destinataer_id), "email": to_email}
|
||||
|
||||
|
||||
@shared_task(bind=True, max_retries=3, default_retry_delay=300)
|
||||
def send_bestaetigung(self, destinataer_id, base_url=None):
|
||||
"""Celery-Wrapper für _send_bestaetigung_sync (für asynchronen Aufruf)."""
|
||||
try:
|
||||
connection = _get_smtp_connection()
|
||||
msg = EmailMultiAlternatives(subject, "", from_email, [to_email], connection=connection)
|
||||
msg.attach_alternative(html_body, "text/html")
|
||||
if pdf_bytes:
|
||||
msg.attach(filename, pdf_bytes, "application/pdf")
|
||||
msg.send()
|
||||
logger.info("Bestätigung gesendet an %s (Destinatär %s)", to_email, destinataer_id)
|
||||
return {"status": "sent", "destinataer_id": str(destinataer_id), "email": to_email}
|
||||
return _send_bestaetigung_sync(destinataer_id)
|
||||
except Exception as exc:
|
||||
logger.exception("send_bestaetigung: E-Mail-Versand fehlgeschlagen für %s: %s", to_email, exc)
|
||||
logger.exception("send_bestaetigung task fehlgeschlagen: %s", exc)
|
||||
raise self.retry(exc=exc)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user