from types import SimpleNamespace from unittest.mock import AsyncMock, patch import pytest from app.services.mail_sender import build_message, deliver_email, send_via_smtp, sign_message from app.services.mime_body_extractor import ExtractedMimePart def test_build_message_formats_named_sender_header(): message = build_message( sender="suyash@gentic.email", sender_name="Suyash Dixit", recipients=["recipient@example.com"], cc=[], subject="Named sender", body_text="Hello", body_html=None, ) assert message["From"] == "Suyash Dixit " def test_build_message_preserves_preformatted_transactional_sender(): message = build_message( sender="aGentic Email ", recipients=["recipient@example.com"], cc=[], subject="Welcome", body_text="Hello", body_html=None, ) assert message["From"] == "aGentic Email " def test_build_message_adds_safe_fallback_sender_name(): message = build_message( sender="notifications@gentic.email", recipients=["recipient@example.com"], cc=[], subject="Notification", body_text="Hello", body_html=None, ) assert message["From"] == "aGentic Email " def test_build_message_includes_file_attachments(): message = build_message( sender="suyash@gentic.email", sender_name="Suyash Dixit", recipients=["recipient@example.com"], cc=[], subject="Invoice", body_text="See attached", body_html="

See attached

", file_attachments=[ ExtractedMimePart( filename="invoice.pdf", content_type="application/pdf", payload=b"%PDF-1.4", ) ], ) filenames = [ part.get_filename() for part in message.walk() if part.get_filename() ] assert filenames == ["invoice.pdf"] def test_dkim_sign_uses_selector_before_domain(): message = build_message( sender="user@ritoesis.com", recipients=["recipient@example.com"], cc=[], subject="Test", body_text="Hello", body_html=None, ) domain = SimpleNamespace( domain_name="ritoesis.com", dkim_selector="agmail", dkim_private_key="private-key", ) with patch( "app.services.mail_sender.dkim.sign", return_value=b"DKIM-Signature: test\r\n", ) as signer: sign_message(message, domain) assert signer.call_args.args[1] == b"agmail" assert signer.call_args.args[2] == b"ritoesis.com" @pytest.mark.asyncio async def test_send_via_smtp_uses_configured_client_hostname(): with patch( "app.services.mail_sender.aiosmtplib.send", new_callable=AsyncMock, ) as send_mock: await send_via_smtp( b"raw", sender="noreply@gentic.email", recipients=["user@example.com"], ) assert send_mock.await_args.kwargs["local_hostname"] == "backend.gentic.email" @pytest.mark.asyncio async def test_deliver_email_uses_bare_address_for_smtp_envelope(): domain = SimpleNamespace( domain_name="gentic.email", dkim_selector="agmail", dkim_private_key="private-key", ) with ( patch( "app.services.mail_sender.sign_message", return_value=b"signed", ), patch( "app.services.mail_sender.send_via_smtp", new_callable=AsyncMock, ) as send_mock, ): await deliver_email( sender="notifications@gentic.email", sender_name="aGentic Email", recipients=["user@example.com"], cc=[], bcc=[], subject="Welcome", body_text="Hello", body_html=None, domain=domain, ) assert send_mock.await_args.kwargs["sender"] == "notifications@gentic.email" def test_build_message_sets_in_reply_to_and_references(): message = build_message( sender="suyash@gentic.email", recipients=["customer@gmail.com"], cc=[], subject="Re: fresh test", body_text="human said B", body_html=None, in_reply_to="", references=[""], message_id="", ) assert message["Message-ID"] == "" assert message["In-Reply-To"] == "" assert message["References"] == "" raw = message.as_bytes() assert b"In-Reply-To: " in raw assert b"References: " in raw def test_signed_mime_preserves_in_reply_to(): from unittest.mock import patch message = build_message( sender="suyash@gentic.email", recipients=["customer@gmail.com"], cc=[], subject="Re: fresh test", body_text="human said B", body_html=None, in_reply_to="", references=[""], message_id="", ) domain = SimpleNamespace( domain_name="gentic.email", dkim_selector="agmail", dkim_private_key="private-key", ) with patch( "app.services.mail_sender.dkim.sign", return_value=b"DKIM-Signature: test\r\n", ): signed = sign_message(message, domain) assert b"In-Reply-To: " in signed