Release v0.1.2
This commit is contained in:
@@ -6,7 +6,7 @@ from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||
|
||||
from govoplan_mail.backend.config import ImapConfig, SmtpConfig, TransportSecurity
|
||||
from govoplan_core.mail.config import ImapConfig, ImapServerConfig, SmtpConfig, SmtpServerConfig, TransportCredentials, TransportSecurity
|
||||
|
||||
|
||||
class StrictModel(BaseModel):
|
||||
@@ -108,12 +108,58 @@ class FieldDefinition(StrictModel):
|
||||
can_override: bool = True
|
||||
|
||||
|
||||
class MailServerCredentials(StrictModel):
|
||||
smtp: TransportCredentials = Field(default_factory=TransportCredentials)
|
||||
imap: TransportCredentials = Field(default_factory=TransportCredentials)
|
||||
|
||||
|
||||
class ServerConfig(StrictModel):
|
||||
mail_profile_id: str | None = None
|
||||
inherit_smtp_credentials: bool = True
|
||||
inherit_imap_credentials: bool = True
|
||||
smtp: SmtpConfig | None = None
|
||||
imap: ImapConfig | None = None
|
||||
smtp: SmtpServerConfig | None = None
|
||||
imap: ImapServerConfig | None = None
|
||||
credentials: MailServerCredentials = Field(default_factory=MailServerCredentials)
|
||||
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def normalize_legacy_credentials(cls, value: Any) -> Any:
|
||||
if not isinstance(value, dict):
|
||||
return value
|
||||
data = dict(value)
|
||||
credentials = data.get("credentials") if isinstance(data.get("credentials"), dict) else {}
|
||||
credentials = {key: dict(item) for key, item in credentials.items() if isinstance(item, dict)}
|
||||
for protocol in ("smtp", "imap"):
|
||||
transport = data.get(protocol)
|
||||
if not isinstance(transport, dict):
|
||||
continue
|
||||
next_transport = dict(transport)
|
||||
next_credentials = dict(credentials.get(protocol) or {})
|
||||
for field in ("username", "password"):
|
||||
if field in next_transport and field not in next_credentials:
|
||||
next_credentials[field] = next_transport[field]
|
||||
next_transport.pop(field, None)
|
||||
next_transport.pop("enabled", None)
|
||||
data[protocol] = next_transport
|
||||
if next_credentials:
|
||||
credentials[protocol] = next_credentials
|
||||
if credentials:
|
||||
data["credentials"] = credentials
|
||||
return data
|
||||
|
||||
def runtime_smtp_config(self) -> SmtpConfig | None:
|
||||
if self.smtp is None:
|
||||
return None
|
||||
payload = self.smtp.model_dump(mode="json")
|
||||
payload.update(self.credentials.smtp.model_dump(mode="json", exclude_none=True))
|
||||
return SmtpConfig.model_validate(payload)
|
||||
|
||||
def runtime_imap_config(self) -> ImapConfig | None:
|
||||
if self.imap is None:
|
||||
return None
|
||||
payload = self.imap.model_dump(mode="json")
|
||||
payload.update(self.credentials.imap.model_dump(mode="json", exclude_none=True))
|
||||
return ImapConfig.model_validate(payload)
|
||||
|
||||
|
||||
class RecipientConfig(StrictModel):
|
||||
@@ -180,10 +226,17 @@ class TemplateSourceConfig(StrictModel):
|
||||
return self
|
||||
|
||||
|
||||
class TemplateBodyMode(StrEnum):
|
||||
TEXT = "text"
|
||||
HTML = "html"
|
||||
BOTH = "both"
|
||||
|
||||
|
||||
class TemplateConfig(StrictModel):
|
||||
subject: str | None = None
|
||||
text: str | None = None
|
||||
html: str | None = None
|
||||
body_mode: TemplateBodyMode = TemplateBodyMode.BOTH
|
||||
source: TemplateSourceConfig | None = None
|
||||
|
||||
@model_validator(mode="after")
|
||||
@@ -343,6 +396,8 @@ class AttachmentConfig(StrictModel):
|
||||
include_subdirs: bool = False
|
||||
required: bool = True
|
||||
allow_multiple: bool = False
|
||||
message_filename_template: str | None = None
|
||||
zip_entry_name_template: str | None = None
|
||||
|
||||
@field_validator("type_", mode="before")
|
||||
@classmethod
|
||||
|
||||
Reference in New Issue
Block a user