Merge pull request #513 from christianlouis/copilot/fix-email-template-issue

fix(email): create missing email template and decouple delivery SMTP from auth SMTP
This commit is contained in:
Christian Krakau-Louis
2026-03-08 11:58:40 +01:00
committed by GitHub
14 changed files with 260 additions and 82 deletions
+7 -7
View File
@@ -75,13 +75,13 @@ class TestValidateStorageConfigs:
assert "Neither SFTP_KEY_PATH nor SFTP_PASSWORD is configured" in result["sftp"]
def test_email_storage_missing_config(self):
"""Test validation when email storage config is missing."""
"""Test validation when email destination storage config is missing."""
with patch("app.utils.config_validator.validators.settings") as mock_settings:
mock_settings.email_host = None
mock_settings.email_default_recipient = None
mock_settings.dest_email_host = None
mock_settings.dest_email_default_recipient = None
result = validate_storage_configs()
assert "EMAIL_HOST is not configured" in result["email"]
assert "EMAIL_DEFAULT_RECIPIENT is not configured" in result["email"]
assert "DEST_EMAIL_HOST is not configured" in result["email"]
assert "DEST_EMAIL_DEFAULT_RECIPIENT is not configured" in result["email"]
@pytest.mark.unit
@@ -438,8 +438,8 @@ class TestValidateStorageConfigsEdgeCases:
# Configure all services
mock_settings.sftp_host = "sftp.example.com"
mock_settings.sftp_password = "pass"
mock_settings.email_host = "smtp.example.com"
mock_settings.email_default_recipient = "test@example.com"
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_default_recipient = "test@example.com"
mock_settings.s3_bucket_name = "my-bucket"
mock_settings.aws_access_key_id = "key"
mock_settings.aws_secret_access_key = "secret"
+7
View File
@@ -620,6 +620,13 @@ def _set_minimal_provider_settings(mock_settings):
"email_password": None,
"email_use_tls": True,
"email_sender": None,
"dest_email_host": None,
"dest_email_default_recipient": None,
"dest_email_port": 587,
"dest_email_username": None,
"dest_email_password": None,
"dest_email_use_tls": True,
"dest_email_sender": None,
"ftp_host": None,
"ftp_username": None,
"ftp_password": None,
+4 -4
View File
@@ -120,10 +120,10 @@ class TestShouldUploadFunctions:
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_email_configured(self, mock_settings):
"""Test email upload check."""
mock_settings.email_host = "smtp.example.com"
mock_settings.email_username = "user"
mock_settings.email_password = "pass"
mock_settings.email_default_recipient = "recipient@example.com"
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_username = "user"
mock_settings.dest_email_password = "pass"
mock_settings.dest_email_default_recipient = "recipient@example.com"
assert _should_upload_to_email() is True
+25 -25
View File
@@ -229,7 +229,7 @@ class TestPrepareRecipients:
@patch("app.tasks.upload_to_email.settings")
def test_uses_default_recipient_when_none_provided(self, mock_settings):
"""Test uses default recipient when none provided."""
mock_settings.email_default_recipient = "default@example.com"
mock_settings.dest_email_default_recipient = "default@example.com"
result, error = _prepare_recipients(None)
@@ -239,7 +239,7 @@ class TestPrepareRecipients:
@patch("app.tasks.upload_to_email.settings")
def test_returns_error_when_no_recipients_and_no_default(self, mock_settings):
"""Test returns error when no recipients and no default."""
mock_settings.email_default_recipient = None
mock_settings.dest_email_default_recipient = None
result, error = _prepare_recipients(None)
@@ -256,11 +256,11 @@ class TestSendEmailWithSMTP:
@patch("app.tasks.upload_to_email.settings")
def test_sends_email_successfully(self, mock_settings, mock_gethostbyname, mock_smtp):
"""Test sends email successfully."""
mock_settings.email_host = "smtp.example.com"
mock_settings.email_port = 587
mock_settings.email_use_tls = True
mock_settings.email_username = "user@example.com"
mock_settings.email_password = "password"
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_port = 587
mock_settings.dest_email_use_tls = True
mock_settings.dest_email_username = "user@example.com"
mock_settings.dest_email_password = "password"
mock_server = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_server
@@ -292,8 +292,8 @@ class TestSendEmailWithSMTP:
@patch("app.tasks.upload_to_email.settings")
def test_handles_connection_refused_error(self, mock_settings, mock_gethostbyname, mock_smtp):
"""Test handles connection refused error."""
mock_settings.email_host = "smtp.example.com"
mock_settings.email_port = 587
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_port = 587
mock_smtp.return_value.__enter__.side_effect = ConnectionRefusedError("Connection refused")
@@ -309,11 +309,11 @@ class TestSendEmailWithSMTP:
@patch("app.tasks.upload_to_email.settings")
def test_sends_email_without_tls(self, mock_settings, mock_gethostbyname, mock_smtp):
"""Test sends email without TLS."""
mock_settings.email_host = "smtp.example.com"
mock_settings.email_port = 25
mock_settings.email_use_tls = False
mock_settings.email_username = "user@example.com"
mock_settings.email_password = "password"
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_port = 25
mock_settings.dest_email_use_tls = False
mock_settings.dest_email_username = "user@example.com"
mock_settings.dest_email_password = "password"
mock_server = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_server
@@ -333,11 +333,11 @@ class TestSendEmailWithSMTP:
@patch("app.tasks.upload_to_email.settings")
def test_sends_email_without_authentication(self, mock_settings, mock_gethostbyname, mock_smtp):
"""Test sends email without authentication credentials."""
mock_settings.email_host = "smtp.example.com"
mock_settings.email_port = 25
mock_settings.email_use_tls = False
mock_settings.email_username = None
mock_settings.email_password = None
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_port = 25
mock_settings.dest_email_use_tls = False
mock_settings.dest_email_username = None
mock_settings.dest_email_password = None
mock_server = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_server
@@ -356,8 +356,8 @@ class TestSendEmailWithSMTP:
@patch("app.tasks.upload_to_email.settings")
def test_handles_timeout_error(self, mock_settings, mock_gethostbyname, mock_smtp):
"""Test handles timeout error."""
mock_settings.email_host = "smtp.example.com"
mock_settings.email_port = 587
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_port = 587
mock_smtp.return_value.__enter__.side_effect = TimeoutError("Connection timeout")
@@ -392,10 +392,10 @@ class TestUploadToEmailTask:
@patch("app.tasks.upload_to_email.os.path.exists")
@patch("app.tasks.upload_to_email.settings")
def test_skips_when_email_host_not_configured(self, mock_settings, mock_exists, mock_log, mock_basename):
"""Test skips when email host not configured."""
"""Test skips when email destination host not configured."""
mock_exists.return_value = True
mock_basename.return_value = "test.pdf"
mock_settings.email_host = None
mock_settings.dest_email_host = None
mock_self = Mock()
mock_self.request.id = "test-task-id"
@@ -403,7 +403,7 @@ class TestUploadToEmailTask:
result = upload_to_email(mock_self, "/tmp/test.pdf")
assert result["status"] == "Skipped"
assert "Email host is not configured" in result["reason"]
assert "DEST_EMAIL_HOST" in result["reason"]
@patch("app.tasks.upload_to_email.os.path.basename")
@patch("app.tasks.upload_to_email._prepare_recipients")
@@ -414,7 +414,7 @@ class TestUploadToEmailTask:
"""Test skips when no valid recipients."""
mock_exists.return_value = True
mock_basename.return_value = "test.pdf"
mock_settings.email_host = "smtp.example.com"
mock_settings.dest_email_host = "smtp.example.com"
mock_prepare.return_value = (None, "No recipients specified")
mock_self = Mock()
+7 -7
View File
@@ -364,12 +364,12 @@ def test_upload_to_email_accepts_file_id(sample_text_file):
patch("app.tasks.upload_to_email.attach_logo") as mock_logo,
):
# Setup settings
mock_settings.email_host = "smtp.example.com"
mock_settings.email_port = 587
mock_settings.email_username = "test@example.com"
mock_settings.email_password = _TEST_CREDENTIAL
mock_settings.email_use_tls = True
mock_settings.email_sender = "sender@example.com"
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_port = 587
mock_settings.dest_email_username = "test@example.com"
mock_settings.dest_email_password = _TEST_CREDENTIAL
mock_settings.dest_email_use_tls = True
mock_settings.dest_email_sender = "sender@example.com"
mock_settings.external_hostname = "docuelevate.example.com"
# Setup mocks
@@ -503,7 +503,7 @@ def test_send_to_all_calls_upload_tasks_with_keyword_argument():
mock_settings.webdav_url = None
mock_settings.ftp_host = None
mock_settings.sftp_host = None
mock_settings.email_host = None
mock_settings.dest_email_host = None
mock_settings.onedrive_client_id = None
mock_settings.workdir = "/tmp"