MailDesk docs
Get MailDesk
Technical

Architecture

MailDesk is built on a clean, layered ("onion") design: a provider-agnostic core owns the data, and provider-specific logic (Gmail/Graph/IMAP) and Odoo-app integrations live at the edges. This page is the map; deeper write-ups live in each module's in-repo docs/ and in the developer-only internal/architecture/ set (ADRs, contracts, dataflows).

2 min read

MailDesk is built on a clean, layered ("onion") design: a provider-agnostic core owns the data, and provider-specific logic (Gmail/Graph/IMAP) and Odoo-app integrations live at the edges. This page is the map; deeper write-ups live in each module's in-repo docs/ and in the developer-only internal/architecture/ set (ADRs, contracts, dataflows).

Module dependency graph

graph TD
  web & contacts & mail & google_gmail & microsoft_outlook --> B[Basic<br/>maildesk_mail_client]
  B --> P[Pro<br/>maildesk_mail_client_pro<br/>AI · 2-way sync · mobile · realtime]
  P --> AUTO[Automation]
  P --> CAL[Calendar]
  P --> CHAT[Chatter]
  P --> CRM[CRM]
  P --> DOC[Documents]
  P --> HD[Helpdesk]
  P --> P360[Partner 360]
  P --> SALE[Sales]
  P --> COCK[Cockpit]
  AUTO --> COCK
  resource[resource] --> COCK

The single source of truth (SSOT)

Everything hangs off one principle: maildesk.message_index is the authoritative record of every message, keyed by a delivery_key of (account, provider, folder, uid). Bodies and attachment lists are kept in a separate time-limited cache (maildesk.ui_cache); importing into Odoo's native mail.thread happens through a durable queue. Derived/read-side views (Cockpit, Partner 360) never become a second owner of that truth. (See internal/architecture/adr/ADR-001-ssot-ownership.md.)

graph LR
  subgraph Providers
    G[Gmail API] ; O[Graph API] ; I[IMAP]
  end
  G & O & I -->|scheduled sync| MI[(maildesk.message_index<br/>SSOT)]
  MI --> UC[(maildesk.ui_cache<br/>bodies/attachments TTL)]
  MI --> IQ[[maildesk.ingest_queue]]
  IQ --> MT[(Odoo mail.thread / mail.message)]
  ES[(maildesk.email_state<br/>read/star/archive)] --- MI
  MI --> EL[(maildesk.email.link → Odoo records)]:::pro
  ES -->|Pro: 2-way| UQ[[maildesk.update_queue]]:::pro
  UQ -->|mutation executors| G & O & I
  classDef pro fill:#efe6ff,stroke:#714697;
  • Inbound (Basic): provider → SSOT → cache; the ingest queue materialises selected messages into mail.thread. One-way.
  • Outbound (Pro, two-way): a user action (mark read, move, delete, flag) updates maildesk.email_state and enqueues a coalesced mutation on maildesk.update_queue; per-provider executors apply it back to Gmail/Graph/IMAP with lease-locking and backoff.

Layers

Layer Responsibility Examples
Domain / use-cases Provider-agnostic business logic open_thread_messages, warm_message_cache, detect_imap_profile
Adapters Bridge use-cases to Odoo ORM / RPC *_adapter.py
Infrastructure Provider SDKs, persistence, transport gmail/, outlook/, imap/, repositories
Presentation OWL components, services, hooks (frontend) static/src/...

Provider-specific code is confined to the infrastructure layer (internal/architecture/adr/ADR-010-provider-boundaries.md); integration bridges must not become second platforms (ADR-007-bridge-addon-rules.md).

Synchronization (overview)

Stable builds deliver mail through scheduled jobs and refresh the open UI over Odoo's websocket bus; 4.2.0 adds true push for Gmail/Outlook and body prefetch. Full detail, including the exact mechanism per provider and the stable-vs-4.2.0 split, is in Synchronization and Realtime architecture.

AI (overview)

AI lives in Pro (and Cockpit for manager briefings) behind a single authorization chokepoint, with a deliberately narrow data boundary — the AI is handed only the email/thread in front of the user, never the whole inbox or arbitrary Odoo records. Provider abstraction supports OpenAI/Gemini/Claude/Grok/DeepSeek and self-hosted servers. See AI architecture and the user-facing AI permissions & data access.

Mobile (overview)

The adaptive phone/tablet UI is Pro-only and auto-detected (no configuration). Pro patches Basic's widgets and adds mobile OWL services/hooks/components plus a mobile dark theme. See Mobile and Frontend assets.

Further reading

  • In-module developer docs (current): Basic docs/architecture_overview.md, docs/clean_onion_architecture.md, docs/dataflow/*, docs/ui_cache_and_ssot.md, docs/invariants_and_guarantees.md.
  • Developer-only architecture/refactor set: internal/architecture/ (findings, contracts, ADRs 001–012, module inventory, roadmap).

Maps reflect the Basic + Pro source trees (v18) and the 4.2.0 branches; see linked pages for citations.