human hand off

This commit is contained in:
debu-2 2026-10-06 07:12:55 +05:30
parent d0fee5c8f7
commit 7af776196a
34 changed files with 2941 additions and 195 deletions

View file

@ -22,6 +22,7 @@ class FakeMessages:
async def update_one(self, *args, **kwargs):
self.updates += 1
return SimpleNamespace(upserted_id=ObjectId(), modified_count=0)
async def find_one(self, *args, **kwargs):
return {"_id": self.id}
@ -33,6 +34,12 @@ class FakeEntries:
async def update_one(self, *args, **kwargs):
self.updates += 1
return SimpleNamespace(upserted_id=ObjectId(), modified_count=0)
class FakeThreads:
async def update_one(self, *args, **kwargs):
return None
class FakeStorage:
@ -84,7 +91,7 @@ async def test_rcpt_rejects_unknown_account(monkeypatch):
async def test_rcpt_accepts_account_and_tracks_owner(monkeypatch):
account = SimpleNamespace(id="account-1")
monkeypatch.setattr(inbound_smtp, "SessionFactory", lambda: FakeSession(account))
target = SimpleNamespace(rcpt_tos=[], rcpt_options=[])
target = SimpleNamespace(rcpt_tos=[], rcpt_options=[], mail_from="sender@example.com")
response = await inbound_smtp.InboundHandler().handle_RCPT(
None,
@ -95,8 +102,8 @@ async def test_rcpt_accepts_account_and_tracks_owner(monkeypatch):
)
assert response.startswith("250 2.1.5")
assert target.rcpt_tos == ["user@gentic.email"]
assert target.account_ids == {"user@gentic.email": "account-1"}
assert target.rcpt_tos == ["user@getall.help"]
assert target.account_ids == {"user@getall.help": "account-1"}
@pytest.mark.asyncio
@ -106,15 +113,98 @@ async def test_data_returns_success_only_after_idempotent_records(monkeypatch):
monkeypatch.setattr(
inbound_smtp,
"mongo_db",
SimpleNamespace(messages=messages, mailbox_entries=entries),
SimpleNamespace(
messages=messages,
mailbox_entries=entries,
email_threads=FakeThreads(),
),
)
monkeypatch.setattr(inbound_smtp, "get_raw_mime_storage", lambda: FakeStorage())
async def no_handoff(*args, **kwargs):
return None
monkeypatch.setattr(inbound_smtp, "resolve_handoff_from_inbound", no_handoff)
monkeypatch.setattr(inbound_smtp, "maybe_trigger_handoff", no_handoff)
async def ensure_thread(*args, **kwargs):
return ObjectId()
monkeypatch.setattr(inbound_smtp, "ensure_thread_for_message", ensure_thread)
response = await inbound_smtp.InboundHandler().handle_DATA(None, None, envelope())
assert response.startswith("250 2.0.0")
assert messages.updates == 1
assert entries.updates == 1
assert messages.updates >= 1
assert entries.updates >= 1
@pytest.mark.asyncio
async def test_human_reply_stays_on_the_private_plane(monkeypatch):
messages = FakeMessages()
entries = FakeEntries()
monkeypatch.setattr(
inbound_smtp,
"mongo_db",
SimpleNamespace(
messages=messages,
mailbox_entries=entries,
email_threads=FakeThreads(),
),
)
monkeypatch.setattr(inbound_smtp, "get_raw_mime_storage", lambda: FakeStorage())
async def resolve(*args, **kwargs):
return {"_id": ObjectId()}
processed = []
async def process(*args, **kwargs):
processed.append(kwargs)
return {"_id": ObjectId()}
monkeypatch.setattr(inbound_smtp, "resolve_handoff_from_inbound", resolve)
monkeypatch.setattr(inbound_smtp, "process_human_reply", process)
response = await inbound_smtp.InboundHandler().handle_DATA(None, None, envelope())
assert response.startswith("250 2.0.0 Handoff message accepted")
assert processed
assert messages.updates == 0
assert entries.updates == 0
@pytest.mark.asyncio
async def test_data_still_accepted_when_handoff_trigger_fails(monkeypatch):
messages = FakeMessages()
entries = FakeEntries()
monkeypatch.setattr(
inbound_smtp,
"mongo_db",
SimpleNamespace(
messages=messages,
mailbox_entries=entries,
email_threads=FakeThreads(),
),
)
monkeypatch.setattr(inbound_smtp, "get_raw_mime_storage", lambda: FakeStorage())
async def no_handoff(*args, **kwargs):
return None
async def boom(*args, **kwargs):
raise RuntimeError("mirror queue unavailable")
monkeypatch.setattr(inbound_smtp, "resolve_handoff_from_inbound", no_handoff)
monkeypatch.setattr(inbound_smtp, "maybe_trigger_handoff", boom)
async def ensure_thread(*args, **kwargs):
return ObjectId()
monkeypatch.setattr(inbound_smtp, "ensure_thread_for_message", ensure_thread)
response = await inbound_smtp.InboundHandler().handle_DATA(None, None, envelope())
assert response.startswith("250 2.0.0")
assert messages.updates >= 1
@pytest.mark.asyncio