from __future__ import annotations import unittest from unittest.mock import patch from govoplan_core.security.outbound_http import OutboundHttpBlocked from govoplan_mail.backend.config import SmtpConfig from govoplan_mail.backend.sending.smtp import ( SmtpConfigurationError, _open_smtp, _prepare_smtp_send, _smtp_send_result, ) class SmtpSendHelperTests(unittest.TestCase): def test_real_smtp_connections_honor_deployment_egress_policy(self): config = SmtpConfig(host="smtp.internal", port=587, security="starttls") with patch( "govoplan_mail.backend.sending.smtp.validate_outbound_host", side_effect=OutboundHttpBlocked("private network blocked"), ), self.assertRaisesRegex(SmtpConfigurationError, "private network blocked"): _open_smtp(config) def test_smtp_revalidates_and_pins_at_connection_time(self): config = SmtpConfig(host="smtp.example.test", port=587, security="starttls") public = [(2, 1, 6, "", ("93.184.216.34", 587))] private = [(2, 1, 6, "", ("127.0.0.1", 587))] with patch.dict( "os.environ", {"APP_ENV": "production", "GOVOPLAN_CONNECTOR_ALLOW_PRIVATE_NETWORKS": "false"}, ), patch( "govoplan_core.security.outbound_http.socket.getaddrinfo", side_effect=(public, private), ), patch("govoplan_core.security.outbound_http.socket.socket") as socket_factory, self.assertRaisesRegex( OutboundHttpBlocked, "non-public network", ): _open_smtp(config) socket_factory.assert_not_called() def test_prepare_smtp_send_validates_envelope(self): config = SmtpConfig(host="smtp.example.org", port=587, security="starttls") with self.assertRaisesRegex(SmtpConfigurationError, "envelope sender"): _prepare_smtp_send(smtp_config=config, envelope_from="", envelope_recipients=["user@example.org"]) with self.assertRaisesRegex(SmtpConfigurationError, "recipient"): _prepare_smtp_send(smtp_config=config, envelope_from="sender@example.org", envelope_recipients=[""]) def test_prepare_smtp_send_filters_blank_recipients(self): config = SmtpConfig(host="smtp.example.org", port=587, security="starttls") self.assertEqual( _prepare_smtp_send( smtp_config=config, envelope_from="sender@example.org", envelope_recipients=["", "user@example.org"], ), ("smtp.example.org", 587, ["user@example.org"]), ) def test_smtp_send_result_decodes_refused_recipients(self): config = SmtpConfig(host="smtp.example.org", port=587, security="starttls") result = _smtp_send_result( smtp_config=config, host="smtp.example.org", port=587, envelope_from="sender@example.org", envelope_recipients=["ok@example.org", "blocked@example.org"], refused={"blocked@example.org": (550, b"blocked")}, ) self.assertEqual(result.accepted_count, 1) self.assertEqual(result.refused_recipients["blocked@example.org"], (550, "blocked")) if __name__ == "__main__": unittest.main()