64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
from __future__ import annotations
|
|
|
|
import sys
|
|
import threading
|
|
import time
|
|
from typing import cast
|
|
|
|
import pytest
|
|
|
|
from data.notifications.smtp_sender import SMTPDeliverySender, SMTPSettings
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
sys.version_info >= (3, 12), reason="stdlib smtpd/asyncore removed in Python 3.12+"
|
|
)
|
|
def test_smtp_delivery_sender_sends_message_over_local_stub():
|
|
import asyncore
|
|
import smtpd
|
|
|
|
class _CapturingSMTPServer(smtpd.SMTPServer):
|
|
def __init__(self, localaddr, remoteaddr):
|
|
super().__init__(localaddr, remoteaddr)
|
|
self.messages: list[dict[str, object]] = []
|
|
|
|
def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
|
|
self.messages.append({
|
|
"peer": peer,
|
|
"mailfrom": mailfrom,
|
|
"rcpttos": rcpttos,
|
|
"data": data,
|
|
})
|
|
return None
|
|
|
|
server = _CapturingSMTPServer(("127.0.0.1", 0), None)
|
|
port = server.socket.getsockname()[1]
|
|
thread = threading.Thread(
|
|
target=asyncore.loop, kwargs={"timeout": 0.1}, daemon=True
|
|
)
|
|
thread.start()
|
|
try:
|
|
sender = SMTPDeliverySender(
|
|
SMTPSettings(
|
|
host="127.0.0.1",
|
|
port=port,
|
|
sender="noreply@example.com",
|
|
)
|
|
)
|
|
result = sender.send_report_ready(
|
|
recipient="parent@example.com",
|
|
order_id="GKO-EMAIL-STUB",
|
|
subject="报告已就绪",
|
|
body="请查看 portal。",
|
|
)
|
|
deadline = time.time() + 2
|
|
while time.time() < deadline and not server.messages:
|
|
time.sleep(0.05)
|
|
assert server.messages, "stub smtp server did not receive message"
|
|
assert result["recipient"] == "parent@example.com"
|
|
raw = cast(bytes, server.messages[0]["data"])
|
|
assert b"Subject: =?utf-8?" in raw or b"Subject: " in raw
|
|
assert b"parent@example.com" in raw
|
|
finally:
|
|
server.close()
|