#!/usr/bin/env python3 """P05 portal -> HTTP -> SMTP/IMAP acceptance; loopback fixtures only. Requires sibling email-connect source and its owned GreenMail harness on 3025/3143. No production configuration or recipients are loaded. """ import imaplib import json from pathlib import Path import sys import tempfile from threading import Thread from wsgiref.simple_server import make_server, WSGIRequestHandler ROOT = Path(__file__).resolve().parents[1] sys.path[:0] = [ str(ROOT / "src"), str(ROOT / "tests"), str(ROOT.parent / "email-connect/src"), ] from email_connect.transactional import ( SMTPProvider, SQLiteDeliveryStore, TransactionalApplication, ) from user_engine.adapters.delivery import HTTPOutboxDeliveryAdapter from test_service_operations import ServiceOperations class Quiet(WSGIRequestHandler): def log_message(self, *args): pass with tempfile.TemporaryDirectory(prefix="p05-mail-") as directory: mail = TransactionalApplication( SQLiteDeliveryStore(directory + "/mail.db"), SMTPProvider( "127.0.0.1", 3025, "fixture", "fixture", "noreply@harness.email-connect.test", security="plaintext", ), "fixture-bearer", "https://users.example.test", ) calls = [] def receiver(env, start): if env["PATH_INFO"] == "/audit": calls.append(True) start( "503 Service Unavailable" if len(calls) == 1 else "202 Accepted", [("Content-Type", "application/json")], ) return [b"{}"] return mail(env, start) server = make_server("127.0.0.1", 0, receiver, handler_class=Quiet) thread = Thread(target=server.serve_forever, daemon=True) thread.start() fixture = ServiceOperations() fixture.setUp() try: event = fixture.seed() address = event.payload["primary_email"] with imaplib.IMAP4("127.0.0.1", 3143) as inbox: inbox.login(address, "fixture") inbox.select("INBOX") before = len(inbox.search(None, "ALL")[1][0].split()) base = "http://127.0.0.1:" + str(server.server_port) adapter = HTTPOutboxDeliveryAdapter( event_url=base + "/audit", event_bearer_token="fixture-bearer", mail_url=base + "/v1/send", mail_bearer_token="fixture-bearer", ) fixture.app.outbox_delivery = adapter assert adapter.mail_status()["checks"]["smtp_authentication"] == "ok" fixture.post( "/platform/operations/deliver", who="operator", event_id=event.event_id, confirmed=True, ) first = fixture.app.service.store.outbox_event(event.event_id) assert ( first.failed_at and first.claimed_by is None and first.delivered_at is None ) assert ( adapter.mail_delivery_status(event.event_id)["state"] == "provider_accepted" ) fixture.post( "/platform/operations/deliver", who="operator", event_id=event.event_id, confirmed=True, ) assert fixture.app.service.store.outbox_event(event.event_id).delivered_at with imaplib.IMAP4("127.0.0.1", 3143) as inbox: inbox.login(address, "fixture") inbox.select("INBOX") after = len(inbox.search(None, "ALL")[1][0].split()) assert after - before == 1 and len(calls) == 2 print( json.dumps( { "success": True, "scope": "loopback SMTP/IMAP fixtures only", "mail_received": 1, "audit_failure_recovered": True, "retry_did_not_duplicate_mail": True, } ) ) finally: server.shutdown() server.server_close() thread.join(timeout=5) fixture.tearDown()