add smtp
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from app.core.config import settings
|
||||
from app.integrations.smtp import send_email
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def smtp_settings(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setattr(settings, "SMTP_HOST", "smtp.example.com")
|
||||
monkeypatch.setattr(settings, "SMTP_PORT", 587)
|
||||
monkeypatch.setattr(settings, "SMTP_USERNAME", "automation")
|
||||
monkeypatch.setattr(settings, "SMTP_PASSWORD", "secret")
|
||||
monkeypatch.setattr(settings, "SMTP_FROM_EMAIL", "noreply@example.com")
|
||||
monkeypatch.setattr(settings, "SMTP_FROM_NAME", "Home Automation")
|
||||
monkeypatch.setattr(settings, "SMTP_ENCRYPTION", "starttls")
|
||||
monkeypatch.setattr(settings, "SMTP_TIMEOUT", 10.0)
|
||||
|
||||
|
||||
def test_send_email_uses_starttls_and_login() -> None:
|
||||
smtp_client = MagicMock()
|
||||
|
||||
with patch("app.integrations.smtp.smtplib.SMTP", return_value=smtp_client) as smtp_class:
|
||||
send_email(
|
||||
subject="Door opened",
|
||||
recipients=["user@example.com"],
|
||||
text_body="The front door opened.",
|
||||
html_body="<p>The front door opened.</p>",
|
||||
reply_to="support@example.com",
|
||||
)
|
||||
|
||||
smtp_class.assert_called_once_with("smtp.example.com", 587, timeout=10.0)
|
||||
assert smtp_client.ehlo.call_count == 2
|
||||
smtp_client.starttls.assert_called_once_with()
|
||||
smtp_client.login.assert_called_once_with("automation", "secret")
|
||||
smtp_client.send_message.assert_called_once()
|
||||
smtp_client.quit.assert_called_once_with()
|
||||
|
||||
message = smtp_client.send_message.call_args.args[0]
|
||||
assert message["Subject"] == "Door opened"
|
||||
assert message["From"] == "Home Automation <noreply@example.com>"
|
||||
assert message["To"] == "user@example.com"
|
||||
assert message["Reply-To"] == "support@example.com"
|
||||
assert message.get_body(preferencelist=("plain",)).get_content().strip() == "The front door opened."
|
||||
assert message.get_body(preferencelist=("html",)).get_content().strip() == "<p>The front door opened.</p>"
|
||||
|
||||
|
||||
def test_send_email_uses_ssl_without_starttls(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
smtp_client = MagicMock()
|
||||
monkeypatch.setattr(settings, "SMTP_PORT", 465)
|
||||
monkeypatch.setattr(settings, "SMTP_ENCRYPTION", "ssl_tls")
|
||||
monkeypatch.setattr(settings, "SMTP_USERNAME", None)
|
||||
monkeypatch.setattr(settings, "SMTP_PASSWORD", None)
|
||||
|
||||
with patch("app.integrations.smtp.smtplib.SMTP_SSL", return_value=smtp_client) as smtp_ssl_class:
|
||||
send_email(
|
||||
subject="Alarm armed",
|
||||
recipients=["user1@example.com", "user2@example.com"],
|
||||
text_body="The alarm is armed.",
|
||||
)
|
||||
|
||||
smtp_ssl_class.assert_called_once_with("smtp.example.com", 465, timeout=10.0)
|
||||
smtp_client.starttls.assert_not_called()
|
||||
smtp_client.login.assert_not_called()
|
||||
smtp_client.send_message.assert_called_once()
|
||||
|
||||
message = smtp_client.send_message.call_args.args[0]
|
||||
assert message["To"] == "user1@example.com, user2@example.com"
|
||||
assert message.get_body(preferencelist=("plain",)).get_content().strip() == "The alarm is armed."
|
||||
|
||||
|
||||
def test_send_email_requires_host(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setattr(settings, "SMTP_HOST", None)
|
||||
|
||||
with pytest.raises(ValueError, match="SMTP_HOST"):
|
||||
send_email(subject="test", recipients=["user@example.com"], text_body="body")
|
||||
|
||||
|
||||
def test_send_email_requires_recipient() -> None:
|
||||
with pytest.raises(ValueError, match="At least one recipient"):
|
||||
send_email(subject="test", recipients=[], text_body="body")
|
||||
|
||||
|
||||
def test_send_email_rejects_unencrypted_mode(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setattr(settings, "SMTP_ENCRYPTION", "none")
|
||||
|
||||
with pytest.raises(ValueError, match="SMTP_ENCRYPTION"):
|
||||
send_email(subject="test", recipients=["user@example.com"], text_body="body")
|
||||
Reference in New Issue
Block a user