"""Unit tests for SMTP mail helpers.""" from __future__ import annotations import smtplib import unittest from types import SimpleNamespace from unittest.mock import MagicMock, patch from media_library_viewer_api.services.mailer import ( EmailAttachment, describe_smtp_error, html_to_text, send_email_message, ) class _SMTPContext: def __init__(self, smtp: MagicMock): self.smtp = smtp def __enter__(self): return self.smtp def __exit__(self, exc_type, exc, tb): return False class MailerTests(unittest.TestCase): def test_html_to_text_strips_tags(self) -> None: text = html_to_text("
Hello world
Line 2
") self.assertIn("Hello", text) self.assertIn("world", text) self.assertIn("Line 2", text) def test_send_email_message_uses_smtp_with_attachments(self) -> None: settings = SimpleNamespace( smtp_host="smtp.example.com", smtp_port=587, smtp_username="mailer@example.com", smtp_password="secret", smtp_from_address="mailer@example.com", smtp_from_name="Manage", smtp_use_tls=True, smtp_use_ssl=False, smtp_timeout=15, ) smtp = MagicMock() smtp.send_message.return_value = {} smtp_factory = MagicMock(return_value=_SMTPContext(smtp)) with patch("media_library_viewer_api.services.mailer.smtplib.SMTP", smtp_factory), patch( "media_library_viewer_api.services.mailer.smtplib.SMTP_SSL" ) as smtp_ssl: result = send_email_message( settings, recipients=["alex@example.com", "sam@example.com"], subject="Hello", html_body="Hi there
", attachments=[EmailAttachment(filename="note.txt", content_type="text/plain", data=b"note")], ) smtp_ssl.assert_not_called() smtp.starttls.assert_called_once() smtp.login.assert_called_once_with("mailer@example.com", "secret") smtp.send_message.assert_called_once() message = smtp.send_message.call_args.args[0] self.assertEqual(message["Subject"], "Hello") self.assertEqual(message["From"], "ManageHello
", ) self.assertEqual(result["selected_mode"]["label"], "Fastmail STARTTLS 587") self.assertEqual(result["authenticated_as"], "mailer@example.com") self.assertEqual(len(result["attempts"]), 2) self.assertEqual(result["attempts"][0]["status"], "failed") self.assertEqual(result["attempts"][1]["status"], "ok") fallback_smtp.send_message.assert_called_once() def test_send_email_message_rejects_unauthorized_from_address(self) -> None: settings = SimpleNamespace( smtp_host="smtp.example.com", smtp_port=587, smtp_username="mailer@example.com", smtp_password="secret", smtp_from_address="alias@example.com", smtp_from_name="Manage", smtp_use_tls=True, smtp_use_ssl=False, smtp_timeout=15, ) smtp = MagicMock() smtp.send_message.side_effect = smtplib.SMTPDataError( 551, b"5.7.1 Not authorised to send from this header address" ) smtp_factory = MagicMock(return_value=_SMTPContext(smtp)) with patch("media_library_viewer_api.services.mailer.smtplib.SMTP", smtp_factory), patch( "media_library_viewer_api.services.mailer.smtplib.SMTP_SSL" ) as smtp_ssl: with self.assertRaises(RuntimeError) as ctx: send_email_message( settings, recipients=["alex@example.com"], subject="Hello", html_body="Hello
", ) smtp_ssl.assert_not_called() self.assertIn("authorized alias", str(ctx.exception).lower()) self.assertEqual(smtp.send_message.call_count, 1) def test_describe_smtp_error_handles_timeout(self) -> None: detail = describe_smtp_error(TimeoutError("timed out")) self.assertIn("timed out", detail.lower()) if __name__ == "__main__": unittest.main()