from __future__ import annotations from typing import Any from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel, ConfigDict, Field from app.auth.dependencies import ApiPrincipal, require_scope from app.mailer.dev.mock_mailbox import ( clear_records, get_failures, get_record, list_records, set_failures, ) router = APIRouter(prefix="/dev/mailbox", tags=["dev-mailbox"]) class MockMailboxListResponse(BaseModel): messages: list[dict[str, Any]] class MockMailboxMessageResponse(BaseModel): message: dict[str, Any] class MockMailboxClearResponse(BaseModel): deleted_count: int class MockMailboxFailureConfig(BaseModel): model_config = ConfigDict(extra="forbid") fail_next_smtp: bool | None = None fail_next_imap: bool | None = None smtp_reject_recipients_containing: str | None = Field(default=None, max_length=255) class MockMailboxFailureResponse(BaseModel): config: dict[str, Any] @router.get("/messages", response_model=MockMailboxListResponse) def list_mock_mailbox_messages( kind: str | None = None, limit: int = 100, principal: ApiPrincipal = Depends(require_scope("campaign:read")), ): """List messages captured by the integrated development mail sandbox.""" del principal return MockMailboxListResponse(messages=list_records(kind=kind, limit=limit)) @router.get("/messages/{message_id}", response_model=MockMailboxMessageResponse) def get_mock_mailbox_message( message_id: str, principal: ApiPrincipal = Depends(require_scope("campaign:read")), ): del principal message = get_record(message_id, include_raw=True) if not message: raise HTTPException(status_code=404, detail="Mock mailbox message not found") return MockMailboxMessageResponse(message=message) @router.delete("/messages", response_model=MockMailboxClearResponse) def clear_mock_mailbox_messages( principal: ApiPrincipal = Depends(require_scope("campaign:write")), ): del principal return MockMailboxClearResponse(deleted_count=clear_records()) @router.get("/failures", response_model=MockMailboxFailureResponse) def get_mock_failure_config( principal: ApiPrincipal = Depends(require_scope("campaign:read")), ): del principal return MockMailboxFailureResponse(config=get_failures()) @router.post("/failures", response_model=MockMailboxFailureResponse) def update_mock_failure_config( payload: MockMailboxFailureConfig, principal: ApiPrincipal = Depends(require_scope("campaign:write")), ): del principal config = set_failures( fail_next_smtp=payload.fail_next_smtp, fail_next_imap=payload.fail_next_imap, smtp_reject_recipients_containing=payload.smtp_reject_recipients_containing, ) return MockMailboxFailureResponse(config=config)