""" Schemi Pydantic per l'invio PEC (Fase 4). """ import uuid from datetime import datetime from pydantic import BaseModel, EmailStr, field_validator class SendPecRequest(BaseModel): """ Richiesta di invio PEC. Accettato come JSON body; gli allegati vengono gestiti in una fase successiva tramite endpoint multipart dedicato. """ mailbox_id: uuid.UUID """Casella PEC mittente.""" to_addresses: list[EmailStr] """Destinatari principali (almeno uno).""" cc_addresses: list[EmailStr] = [] """Destinatari in copia (opzionale).""" subject: str """Oggetto del messaggio.""" body_text: str = "" """Corpo in testo semplice.""" body_html: str | None = None """Corpo HTML (opzionale).""" reply_to_message_id: uuid.UUID | None = None """UUID del messaggio a cui si risponde (per threading, opzionale).""" @field_validator("to_addresses") @classmethod def at_least_one_recipient(cls, v: list[EmailStr]) -> list[EmailStr]: if not v: raise ValueError("Almeno un destinatario è obbligatorio") return v @field_validator("subject") @classmethod def subject_not_empty(cls, v: str) -> str: if not v.strip(): raise ValueError("Il campo Oggetto non può essere vuoto") return v.strip() class SendJobResponse(BaseModel): """Stato di un job di invio PEC.""" model_config = {"from_attributes": True} id: uuid.UUID tenant_id: uuid.UUID mailbox_id: uuid.UUID message_id: uuid.UUID | None = None status: str """Stato: pending | sending | sent | failed | retrying""" attempt_count: int max_attempts: int next_retry_at: datetime | None = None last_error: str | None = None queued_at: datetime sent_at: datetime | None = None created_by: uuid.UUID | None = None class SendJobListResponse(BaseModel): """Lista paginata di job di invio.""" items: list[SendJobResponse] total: int page: int page_size: int