""" Modello Mailbox – casella PEC con credenziali IMAP/SMTP cifrate. """ import uuid from datetime import datetime from sqlalchemy import ( BigInteger, Boolean, DateTime, Enum, ForeignKey, Index, Integer, String, Text, UniqueConstraint, func, ) from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column, relationship from app.database import Base MailboxStatus = Enum( "active", "paused", "error", "deleted", name="mailbox_status", create_type=False, ) class Mailbox(Base): __tablename__ = "mailboxes" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4 ) tenant_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False ) email_address: Mapped[str] = mapped_column(String(255), nullable=False) display_name: Mapped[str | None] = mapped_column(String(255), nullable=True) provider: Mapped[str | None] = mapped_column(String(100), nullable=True) # Credenziali IMAP cifrate (AES-256-GCM) imap_host_enc: Mapped[str] = mapped_column(Text, nullable=False) imap_port_enc: Mapped[str] = mapped_column(Text, nullable=False) imap_user_enc: Mapped[str] = mapped_column(Text, nullable=False) imap_pass_enc: Mapped[str] = mapped_column(Text, nullable=False) imap_use_ssl: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) # Credenziali SMTP cifrate (AES-256-GCM) smtp_host_enc: Mapped[str] = mapped_column(Text, nullable=False) smtp_port_enc: Mapped[str] = mapped_column(Text, nullable=False) smtp_user_enc: Mapped[str] = mapped_column(Text, nullable=False) smtp_pass_enc: Mapped[str] = mapped_column(Text, nullable=False) smtp_use_tls: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) # Stato sincronizzazione status: Mapped[str] = mapped_column(MailboxStatus, nullable=False, default="active") last_sync_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) last_sync_uid: Mapped[int | None] = mapped_column(BigInteger, nullable=True) sent_last_sync_uid: Mapped[int | None] = mapped_column(BigInteger, nullable=True) sync_error_msg: Mapped[str | None] = mapped_column(Text, nullable=True) sync_error_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0) created_by: Mapped[uuid.UUID | None] = mapped_column( UUID(as_uuid=True), ForeignKey("users.id"), nullable=True ) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now() ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now(), onupdate=func.now() ) # Relazioni tenant: Mapped["Tenant"] = relationship("Tenant", back_populates="mailboxes") # noqa: F821 permissions: Mapped[list["MailboxPermission"]] = relationship( # noqa: F821 "MailboxPermission", back_populates="mailbox", cascade="all, delete-orphan" ) __table_args__ = ( UniqueConstraint("tenant_id", "email_address", name="uq_mailbox_email_tenant"), Index("idx_mailboxes_tenant", "tenant_id"), Index( "idx_mailboxes_status", "status", postgresql_where="status = 'active'", ), ) def __repr__(self) -> str: return f""