from datetime import datetime, timezone from datetime import date from typing import Literal from uuid import UUID from pydantic import BaseModel, ConfigDict, EmailStr, Field class AccountRegister(BaseModel): account_type: Literal["individual", "company"] email_name: str = Field( min_length=1, max_length=64, pattern=r"^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,62}[A-Za-z0-9])?$", ) company_domain: str | None = Field(default=None, max_length=253) first_name: str = Field(min_length=1, max_length=80) last_name: str = Field(min_length=1, max_length=80) date_of_birth: date phone_number: str = Field( min_length=7, max_length=24, pattern=r"^\+?[0-9][0-9 ()-]{5,22}[0-9]$", ) password: str = Field(min_length=8, max_length=128) class AccountRead(BaseModel): id: UUID account_type: str email: EmailStr first_name: str last_name: str date_of_birth: date phone_number: str company_domain: str | None created_at: datetime model_config = ConfigDict(from_attributes=True) class LoginRequest(BaseModel): email: EmailStr password: str = Field(min_length=1, max_length=128) class AuthResponse(BaseModel): access_token: str token_type: Literal["bearer"] = "bearer" account: AccountRead class EmailCreate(BaseModel): recipients: list[EmailStr] = Field(min_length=1) cc: list[EmailStr] = Field(default_factory=list) bcc: list[EmailStr] = Field(default_factory=list) subject: str = Field(default="", max_length=998, pattern=r"^[^\r\n]*$") body_text: str = "" body_html: str | None = None class EmailRead(EmailCreate): id: str sender: EmailStr status: str created_at: datetime class MailAddress(BaseModel): name: str address: str class AttachmentRead(BaseModel): filename: str content_type: str size: int content_id: str | None = None disposition: str = "attachment" class MessageSummary(BaseModel): id: str mailbox: Literal["inbox", "sent", "trash"] direction: Literal["inbound", "outbound"] sender: MailAddress recipients: list[MailAddress] subject: str snippet: str status: str created_at: datetime is_read: bool is_starred: bool = False trashed_at: datetime | None = None attachments: list[AttachmentRead] = Field(default_factory=list) class MessageRead(MessageSummary): cc: list[MailAddress] = Field(default_factory=list) bcc: list[MailAddress] = Field(default_factory=list) reply_to: list[MailAddress] = Field(default_factory=list) body_text: str = "" body_html: str | None = None message_id: str | None = None class MessageReadState(BaseModel): is_read: bool class MessageStarState(BaseModel): is_starred: bool class StickyNoteCreate(BaseModel): title: str = Field(min_length=1, max_length=120) body: str = Field(default="", max_length=2000) tags: list[str] = Field(default_factory=list, max_length=5) color: Literal["yellow", "green", "blue", "pink"] = "yellow" class StickyNoteUpdate(BaseModel): title: str | None = Field(default=None, min_length=1, max_length=120) body: str | None = Field(default=None, max_length=2000) tags: list[str] | None = Field(default=None, max_length=5) color: Literal["yellow", "green", "blue", "pink"] | None = None class StickyNoteRead(StickyNoteCreate): id: str created_at: datetime updated_at: datetime class MessagePage(BaseModel): items: list[MessageSummary] next_cursor: str | None = None class DomainCreate(BaseModel): domain_name: str = Field(min_length=3, max_length=253) account_id: UUID | None = None class DnsRecordRead(BaseModel): id: UUID record_type: str host: str value: str purpose: str ttl: int model_config = ConfigDict(from_attributes=True) class DnsVerificationCheck(BaseModel): purpose: str verified: bool message: str class DnsVerificationResponse(BaseModel): domain: str status: str verified: bool checks: list[DnsVerificationCheck] class MailDomainRead(BaseModel): id: UUID domain_name: str domain_type: str account_id: UUID | None mail_host: str dkim_selector: str status: str created_at: datetime dns_records: list[DnsRecordRead] = [] model_config = ConfigDict(from_attributes=True) class SmtpCredentialCreate(BaseModel): label: str = Field(default="default", min_length=1, max_length=120) class SmtpCredentialRead(BaseModel): id: UUID username: str label: str is_active: bool created_at: datetime model_config = ConfigDict(from_attributes=True) class SmtpCredentialCreated(SmtpCredentialRead): password: str smtp_host: str smtp_port: int use_tls: bool class DnsSetupRequest(BaseModel): domain: str = Field(min_length=3, max_length=253) mail_server_ip: str = Field(min_length=3, max_length=45) class DnsSetupRecord(BaseModel): record_type: str host: str value: str purpose: str ttl: int priority: int | None = None class DnsSetupResponse(BaseModel): domain: str mail_host: str app_public_host: str mail_server_ip: str is_platform_domain: bool sections: dict[str, list[DnsSetupRecord]] notes: list[str] = Field(default_factory=list) def utc_now() -> datetime: return datetime.now(timezone.utc)