From bce58b3f253618dc47d5e221681d16278ece90cf Mon Sep 17 00:00:00 2001 From: Md Bayazid Bostame Date: Mon, 30 Mar 2026 12:41:40 +0200 Subject: [PATCH] fix: preserve request actions and soften test-mode mail failures --- backend/workflows/email_workflows.py | 23 ++++++++++----- .../static/workflows/js/confirm_dialog.js | 3 +- .../workflows/tests/test_email_workflows.py | 28 +++++++++++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 backend/workflows/tests/test_email_workflows.py diff --git a/backend/workflows/email_workflows.py b/backend/workflows/email_workflows.py index 61c65df..e63bdf8 100644 --- a/backend/workflows/email_workflows.py +++ b/backend/workflows/email_workflows.py @@ -1,5 +1,6 @@ from datetime import timedelta from pathlib import Path +import logging from django.conf import settings from django.utils import timezone @@ -11,6 +12,8 @@ from .forms import OnboardingRequestForm from .models import NotificationRule, NotificationTemplate, OnboardingRequest, ScheduledWelcomeEmail, WorkflowConfig from .services import get_email_test_redirect, is_email_test_mode +logger = logging.getLogger(__name__) + def resolve_workflow_emails() -> tuple[str, str, str, str, str]: config = WorkflowConfig.objects.order_by('id').first() @@ -42,13 +45,19 @@ def send_workflow_email( f"Originale Empfänger: {', '.join(recipients)}\n\n{body}" ) - send_system_email( - subject=subject, - body=effective_body, - to=effective_to, - attachments=[str(a) for a in (attachments or [])], - from_email=from_email, - ) + try: + send_system_email( + subject=subject, + body=effective_body, + to=effective_to, + attachments=[str(a) for a in (attachments or [])], + from_email=from_email, + ) + except OSError as exc: + if is_email_test_mode(): + logger.warning('Email send skipped in test mode because SMTP is unavailable: %s', exc) + return + raise def render_notification_template(template_key: str, context: dict, language_code: str | None = None) -> tuple[str, str]: diff --git a/backend/workflows/static/workflows/js/confirm_dialog.js b/backend/workflows/static/workflows/js/confirm_dialog.js index ad6b06f..7caaf3a 100644 --- a/backend/workflows/static/workflows/js/confirm_dialog.js +++ b/backend/workflows/static/workflows/js/confirm_dialog.js @@ -54,6 +54,7 @@ const form = event.target; const message = form.dataset.confirm; if (!message || form.dataset.confirmBypass === '1') return; + const submitter = event.submitter || null; event.preventDefault(); open(message).then(function (confirmed) { if (!confirmed) return; @@ -62,7 +63,7 @@ window.AppActionProgress.show(form); } if (typeof form.requestSubmit === 'function') { - form.requestSubmit(); + form.requestSubmit(submitter || undefined); } else { form.submit(); } diff --git a/backend/workflows/tests/test_email_workflows.py b/backend/workflows/tests/test_email_workflows.py new file mode 100644 index 0000000..cf5e8b6 --- /dev/null +++ b/backend/workflows/tests/test_email_workflows.py @@ -0,0 +1,28 @@ +from pathlib import Path +from unittest.mock import patch + +from django.test import TestCase, override_settings + +from workflows.email_workflows import send_workflow_email + + +class SendWorkflowEmailTests(TestCase): + @override_settings(EMAIL_TEST_MODE=True, EMAIL_TEST_REDIRECT='test@example.com') + @patch('workflows.email_workflows.send_system_email', side_effect=ConnectionRefusedError('[Errno 111] Connection refused')) + def test_test_mode_suppresses_smtp_connection_errors(self, _mock_send_system_email): + send_workflow_email( + subject='Test', + body='Body', + to=['real@example.com'], + attachments=[Path('/tmp/test.pdf')], + ) + + @override_settings(EMAIL_TEST_MODE=False) + @patch('workflows.email_workflows.send_system_email', side_effect=ConnectionRefusedError('[Errno 111] Connection refused')) + def test_non_test_mode_keeps_smtp_connection_errors(self, _mock_send_system_email): + with self.assertRaises(ConnectionRefusedError): + send_workflow_email( + subject='Test', + body='Body', + to=['real@example.com'], + )