import asyncio from types import SimpleNamespace from urllib.parse import unquote import pytest from pneumatube.lookup_server import _lookup class _StubBridge: def __init__(self, known, accepted=None): self.known = known self.accepted = known if accepted is None else accepted def user_exists(self, username): if username == "broken": return None return username in self.known def recipient_accepted_gateway(self, username): return username in self.accepted class _InlineWorker: async def run(self, fn, *args): return fn(*args) def _config(**overrides): defaults = {"email_domain": "gateway.example", "require_accepted_recipient": True} return SimpleNamespace(**{**defaults, **overrides}) def test_lookup_known_user_returns_ok(): bridge = _StubBridge({"alice"}) reply = asyncio.run(_lookup(bridge, _InlineWorker(), _config(), "alice@gateway.example")) code, _, text = reply.partition(" ") assert code == "200" assert unquote(text) == "OK" def test_lookup_unknown_user_returns_reject_action(): bridge = _StubBridge({"alice"}) reply = asyncio.run(_lookup(bridge, _InlineWorker(), _config(), "nobody@gateway.example")) code, _, text = reply.partition(" ") assert code == "200" assert unquote(text) == "550 5.1.1 no such user" def test_lookup_resolve_failure_is_temporary(): bridge = _StubBridge({"alice"}) reply = asyncio.run(_lookup(bridge, _InlineWorker(), _config(), "broken@gateway.example")) assert reply.startswith("400 ") def test_lookup_other_domain_has_no_opinion(): bridge = _StubBridge({"alice"}) reply = asyncio.run(_lookup(bridge, _InlineWorker(), _config(), "alice@other.example")) assert reply == "500 not found" def test_lookup_rejects_unaccepted_recipient_by_default(): bridge = _StubBridge({"alice"}, accepted=set()) reply = asyncio.run(_lookup(bridge, _InlineWorker(), _config(), "alice@gateway.example")) code, _, text = reply.partition(" ") assert code == "200" assert unquote(text) == "550 5.7.1 recipient has not accepted mail from this gateway" def test_lookup_allows_unaccepted_recipient_when_disabled(): bridge = _StubBridge({"alice"}, accepted=set()) config = _config(require_accepted_recipient=False) reply = asyncio.run(_lookup(bridge, _InlineWorker(), config, "alice@gateway.example")) code, _, text = reply.partition(" ") assert code == "200" assert unquote(text) == "OK"