user-engine/scripts/p05_mail_acceptance.py

124 lines
3.9 KiB
Python
Raw Normal View History

#!/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()