Files
dav-imap-mcp/src/config.py
Yigit Colakoglu bd8e1412e4
All checks were successful
Build And Test / publish (push) Successful in 47s
Use configured contacts address book
2026-01-01 15:55:00 -08:00

173 lines
5.8 KiB
Python

from pydantic_settings import BaseSettings
from pydantic import Field, SecretStr
from typing import Optional
class Settings(BaseSettings):
# MCP Server
server_name: str = Field(default="PIM MCP Server", alias="SERVER_NAME")
server_port: int = Field(default=8000, alias="PORT")
server_host: str = Field(default="0.0.0.0", alias="HOST")
environment: str = Field(default="development", alias="ENVIRONMENT")
# API Authentication
mcp_api_key: Optional[SecretStr] = Field(default=None, alias="MCP_API_KEY")
# IMAP Configuration
imap_host: Optional[str] = Field(default=None, alias="IMAP_HOST")
imap_port: int = Field(default=993, alias="IMAP_PORT")
imap_username: Optional[str] = Field(default=None, alias="IMAP_USERNAME")
imap_password: Optional[SecretStr] = Field(default=None, alias="IMAP_PASSWORD")
imap_use_ssl: bool = Field(default=True, alias="IMAP_USE_SSL")
# SMTP Configuration
smtp_host: Optional[str] = Field(default=None, alias="SMTP_HOST")
smtp_port: int = Field(default=587, alias="SMTP_PORT")
smtp_username: Optional[str] = Field(default=None, alias="SMTP_USERNAME")
smtp_password: Optional[SecretStr] = Field(default=None, alias="SMTP_PASSWORD")
smtp_use_tls: bool = Field(default=True, alias="SMTP_USE_TLS")
smtp_from_email: Optional[str] = Field(default=None, alias="SMTP_FROM_EMAIL")
smtp_from_name: Optional[str] = Field(default=None, alias="SMTP_FROM_NAME")
# CalDAV Configuration
caldav_url: Optional[str] = Field(default=None, alias="CALDAV_URL")
caldav_username: Optional[str] = Field(default=None, alias="CALDAV_USERNAME")
caldav_password: Optional[SecretStr] = Field(default=None, alias="CALDAV_PASSWORD")
ics_calendars: Optional[str] = Field(default=None, alias="ICS_CALENDARS")
ics_calendar_timeout: int = Field(default=20, alias="ICS_CALENDAR_TIMEOUT")
# CardDAV Configuration
carddav_url: Optional[str] = Field(default=None, alias="CARDDAV_URL")
carddav_username: Optional[str] = Field(default=None, alias="CARDDAV_USERNAME")
carddav_password: Optional[SecretStr] = Field(default=None, alias="CARDDAV_PASSWORD")
contacts_addressbook_url: Optional[str] = Field(
default=None,
alias="CONTACTS_ADDRESSBOOK_URL",
)
# SQLite Cache
sqlite_path: str = Field(default="/data/cache.db", alias="SQLITE_PATH")
cache_ttl_seconds: int = Field(default=300, alias="CACHE_TTL_SECONDS")
# Feature Flags
enable_email: bool = Field(default=True, alias="ENABLE_EMAIL")
enable_calendar: bool = Field(default=True, alias="ENABLE_CALENDAR")
enable_contacts: bool = Field(default=True, alias="ENABLE_CONTACTS")
# Email Notification Settings
enable_email_notifications: bool = Field(
default=False,
alias="ENABLE_EMAIL_NOTIFICATIONS"
)
notification_mailboxes: str = Field(
default="INBOX",
alias="NOTIFICATION_MAILBOXES",
)
notification_poll_interval: int = Field(
default=60,
alias="NOTIFICATION_POLL_INTERVAL",
)
notification_idle_timeout: int = Field(
default=1680, # 28 minutes (RFC recommends refresh before 29 min)
alias="NOTIFICATION_IDLE_TIMEOUT",
)
# Poke Webhook Settings
poke_webhook_url: Optional[str] = Field(
default="https://poke.com/api/v1/inbound-sms/webhook",
alias="POKE_WEBHOOK_URL",
)
poke_api_key: Optional[SecretStr] = Field(
default=None,
alias="POKE_API_KEY",
)
poke_webhook_timeout: int = Field(
default=30,
alias="POKE_WEBHOOK_TIMEOUT",
)
poke_webhook_max_retries: int = Field(
default=3,
alias="POKE_WEBHOOK_MAX_RETRIES",
)
model_config = {
"env_file": ".env",
"env_file_encoding": "utf-8",
"populate_by_name": True,
"extra": "ignore",
}
def is_email_configured(self) -> bool:
return all([
self.enable_email,
self.imap_host,
self.imap_username,
self.imap_password,
])
def is_smtp_configured(self) -> bool:
return all([
self.smtp_host,
self.smtp_username,
self.smtp_password,
self.smtp_from_email,
])
def is_caldav_configured(self) -> bool:
return all([
self.enable_calendar,
self.caldav_url,
self.caldav_username,
self.caldav_password,
])
def is_calendar_configured(self) -> bool:
return all([
self.enable_calendar,
(self.is_caldav_configured() or self.get_ics_calendars()),
])
def get_ics_calendars(self) -> list[tuple[Optional[str], str]]:
if not self.ics_calendars:
return []
calendars: list[tuple[Optional[str], str]] = []
for entry in self.ics_calendars.split(","):
item = entry.strip()
if not item:
continue
if "|" in item:
name, url = item.split("|", 1)
name = name.strip() or None
url = url.strip()
else:
name = None
url = item
if url:
calendars.append((name, url))
return calendars
def is_contacts_configured(self) -> bool:
return all([
self.enable_contacts,
self.carddav_url,
self.carddav_username,
self.carddav_password,
self.contacts_addressbook_url,
])
def is_notification_configured(self) -> bool:
return all([
self.enable_email_notifications,
self.is_email_configured(),
self.poke_api_key,
self.poke_webhook_url,
])
def get_notification_mailboxes(self) -> list[str]:
return [m.strip() for m in self.notification_mailboxes.split(",") if m.strip()]
settings = Settings()