Release 4.2.0 — Realtime sync, IMAP autopilot, body prefetch
This release adds three things on top of the shipped 4.1.x synchronization engine:
Status: near-release, NOT yet merged to
18.0. The 4.2.0 work lives on two feature branches in both the Basic and Pro repositories —MailDesk-889-realtime-sync-v18andMailDesk-prefetch-cache-v18— tracked by merge requests !237 (Basic) and !124 (Pro). The implementation is complete and test-covered and includes migration18.0.4.2.0, but18.0HEAD does not yet contain these commits. Treat this page as forward-looking until the MRs land. Re-confirm merge status at publish time. The Basic diff is small (≈ +156 net lines, mostly no-op base hooks); the Pro diff is substantial (≈ +8960 net lines).
This release adds three things on top of the shipped 4.1.x synchronization engine:
- True provider push for Gmail and Outlook / Microsoft 365.
- IMAP autopilot — automatic capability profiling and per-account strategy selection.
- Body prefetch — bodies warmed into the UI cache before the user opens a message.
The scheduled background jobs from 4.1.x stay in place as the fallback path. Push does not replace the engine: a webhook stamps the account and triggers the existing sync cron, which still does the delta fetch and bus broadcast. Push shortens latency; it does not change what gets synced.
1. What "realtime" means, per provider
Be precise about the guarantee. Only Gmail and Outlook genuinely push; IMAP is smart polling plus fetch-on-open prefetch.
| Provider | Mechanism | Typical latency | Genuinely push? |
|---|---|---|---|
| Gmail | Cloud Pub/Sub topic + users.watch; webhook controllers/gmail_push.py validates the envelope and triggers the Gmail sync cron |
~3–8 s | Yes — push |
| Outlook / M365 | Graph /subscriptions change-notifications (+ clientState); webhook controllers/outlook_push.py triggers the Outlook sync cron |
~3–13 s | Yes — push |
| IMAP | Autopilot capability profiling + smart polling + fetch-on-open prefetch (IDLE is a hint, not a delivery channel here) | poll interval; instant on open from cache | No — polling/prefetch |
Honest framing for customer-facing copy: call it "near-realtime." Gmail and Outlook push within ~15 s; IMAP mail surfaces within the poll interval but opens instantly thanks to prefetch.
2. IMAP autopilot
A weekly probe (application/use_cases/detect_imap_profile.py, cron data/ir_cron_imap_profile.xml,
1 day) runs CAPABILITY against each IMAP account and classifies it:
| Profile | Capabilities | Strategy |
|---|---|---|
| A | IDLE + CONDSTORE + QRESYNC + UIDPLUS | cheapest deltas |
| B | IDLE only | full flag scan |
| C | basic IMAP | UID append detection |
| D | caps unreliable / broken | strict budget mode |
application/use_cases/sync_imap_folder_smart_pro.py then selects the cheapest correct strategy for
the profile. There are no tuning knobs — classification is deterministic and re-probed weekly.
3. Body prefetch (all providers)
A new model maildesk.message_prefetch_queue warms maildesk.ui_cache so message bodies are ready
before the user opens them. Two hooks on mailbox.account feed the queue:
- Post-upsert hook —
_maildesk_after_message_index_upserted(account_id, folder, uid, index_id, is_new), called bysync_imap_folder.py/sync_gmail_incremental.py/sync_outlook_delta.pyafter each upsert. Pro enqueues newly-inserted messages at priority 1 (reasonsync_new). The hook only enqueues — it does not itself notify the bus or index. - Folder-open hook —
_maildesk_enqueue_folder_open_prefetch(account_id, folder_id, top_index_ids), fired when a folder list renders. The top-N visible messages (default 30,maildesk.prefetch.folder_open_top_n) are enqueued at priority 5 (reasonfolder_open).
The base hooks are no-ops in Basic; Pro provides the real implementations.
A warming cron (data/ir_cron_prefetch.xml, every 1 min) runs WarmMessageCache with guards:
| Guard | Value |
|---|---|
| Batch per tick | 5 |
| Time budget per tick | 10 s |
| Per-account throttle | 200 / hour |
| Backoff | exponential, 10 s → … → 2 h |
| Max attempts | 8 |
| Terminal state | not_found |
4. Setup, renewal, and failure handling
- Setup wizards:
wizards/gmail_push_setup_wizard.pycreates the Pub/Sub topic +users.watch;wizards/outlook_push_setup_wizard.pycreates the Graph subscription. Subscriptions are stored onmaildesk.push_subscription. IMAP needs nothing — autopilot is automatic. - Renewal: Gmail watch (7-day max) is renewed ~6 days; Outlook subscription (3-day default) is
renewed via PATCH (
application/use_cases/renew_push_subscriptions.py). Crondata/ir_cron_push.xmlruns hourly. - Silence detection: if no push arrives within ~6 h, the account is marked for a full delta resync.
- Graceful degradation: if push fails, MailDesk silently falls back to the scheduled crons of 4.1.x; if a prefetch fails, the body is fetched on demand when the user opens the message. There is no feature-wide kill switch — each component handles its own errors.
- Large mailboxes: bootstrap is newest-first, incremental sync is capped per run and chunked, backfill stays progressive and lower-priority, and prefetch is throttled per account.
5. What an admin / user observes after merge
- Admin: run the Gmail and/or Outlook realtime setup wizard per account. IMAP needs no
configuration. Prefetch is on after the
18.0.4.2.0migration with sane defaults. Queue progress and subscription health are visible under Settings → Technical → Scheduled Actions; thebuild_diagnostic_bundle.pyuse case captures a support bundle. - User: with push enabled, new Gmail/Outlook mail appears in seconds and opening a folder shows already-loaded bodies for the top messages; IMAP mail appears within the poll interval but opens instantly from cache.
6. Source
Branch MailDesk-889-realtime-sync-v18 / MailDesk-prefetch-cache-v18:
controllers/gmail_push.py, controllers/outlook_push.py,
models/maildesk_message_prefetch_queue.py, models/maildesk_push_subscription.py,
application/use_cases/{handle_gmail_push, handle_outlook_push, register_gmail_watch,
register_outlook_subscription, renew_push_subscriptions, warm_message_cache, detect_imap_profile,
sync_imap_folder_smart_pro}.py, wizards/gmail_push_setup_wizard.py,
wizards/outlook_push_setup_wizard.py, migrations/18.0.4.2.0/post-migration.py, crons
data/ir_cron_prefetch.xml (1 min), data/ir_cron_imap_profile.xml (1 day), data/ir_cron_push.xml (1 h).
See also Realtime & synchronization architecture for the full stable-vs-4.2.0 split.