agentic.email/backend/tests/test_mail_sender.py
2026-10-06 07:12:55 +05:30

165 lines
4.8 KiB
Python

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
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 <suyash@gentic.email>"
def test_build_message_preserves_preformatted_transactional_sender():
message = build_message(
sender="aGentic Email <notifications@gentic.email>",
recipients=["recipient@example.com"],
cc=[],
subject="Welcome",
body_text="Hello",
body_html=None,
)
assert message["From"] == "aGentic Email <notifications@gentic.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 <notifications@gentic.email>"
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="<CAHabc123@mail.gmail.com>",
references=["<CAHabc123@mail.gmail.com>"],
message_id="<B@gentic.email>",
)
assert message["Message-ID"] == "<B@gentic.email>"
assert message["In-Reply-To"] == "<CAHabc123@mail.gmail.com>"
assert message["References"] == "<CAHabc123@mail.gmail.com>"
raw = message.as_bytes()
assert b"In-Reply-To: <CAHabc123@mail.gmail.com>" in raw
assert b"References: <CAHabc123@mail.gmail.com>" 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="<CAHabc123@mail.gmail.com>",
references=["<CAHabc123@mail.gmail.com>"],
message_id="<B@gentic.email>",
)
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: <CAHabc123@mail.gmail.com>" in signed