""" Schemi Pydantic per Message, Attachment e operazioni correlate. """ import uuid from datetime import datetime from typing import Optional from pydantic import BaseModel, model_validator from app.schemas.label import LabelResponse class AttachmentResponse(BaseModel): id: uuid.UUID message_id: uuid.UUID filename: str content_type: Optional[str] = None size_bytes: Optional[int] = None storage_path: str checksum_sha256: Optional[str] = None created_at: datetime model_config = {"from_attributes": True} class MessageResponse(BaseModel): id: uuid.UUID tenant_id: uuid.UUID mailbox_id: uuid.UUID message_id_header: Optional[str] = None imap_uid: Optional[int] = None imap_folder: str direction: str pec_type: str state: str subject: Optional[str] = None from_address: Optional[str] = None to_addresses: list[str] = [] cc_addresses: list[str] = [] sent_at: Optional[datetime] = None received_at: Optional[datetime] = None size_bytes: Optional[int] = None body_text: Optional[str] = None body_html: Optional[str] = None has_attachments: bool = False parent_message_id: Optional[uuid.UUID] = None is_read: bool = False is_starred: bool = False is_archived: bool = False archived_at: Optional[datetime] = None is_trashed: bool = False trashed_at: Optional[datetime] = None is_pending_conservation: bool = False pending_conservation_at: Optional[datetime] = None is_conserved: bool = False conserved_at: Optional[datetime] = None raw_eml_path: Optional[str] = None created_at: datetime updated_at: datetime labels: list[LabelResponse] = [] @model_validator(mode="before") @classmethod def coerce_arrays(cls, data: object) -> object: """Normalizza i campi array a liste vuote se None (da ORM).""" if hasattr(data, "__dict__"): # ORM object for field in ("to_addresses", "cc_addresses"): val = getattr(data, field, None) if val is None: object.__setattr__(data, field, []) elif isinstance(data, dict): for field in ("to_addresses", "cc_addresses"): if data.get(field) is None: data[field] = [] return data model_config = {"from_attributes": True} class MessageListResponse(BaseModel): items: list[MessageResponse] total: int page: int page_size: int class MessageUpdateRequest(BaseModel): is_read: Optional[bool] = None is_starred: Optional[bool] = None is_archived: Optional[bool] = None is_trashed: Optional[bool] = None is_pending_conservation: Optional[bool] = None is_conserved: Optional[bool] = None class MessageBulkUpdateRequest(BaseModel): ids: list[uuid.UUID] is_read: Optional[bool] = None is_starred: Optional[bool] = None is_archived: Optional[bool] = None is_trashed: Optional[bool] = None is_pending_conservation: Optional[bool] = None is_conserved: Optional[bool] = None class MessageBulkUpdateResponse(BaseModel): updated: int items: list[MessageResponse]