Standalone multi-account client — CGP + any IMAP.
Mount your CGP file storage as a native drive.
Audit-proof e-mail journaling — GoBD / HGB §257 / AO §147.
With a new interface and newly designed helpers, you have instant access to all your data. Search through thousands of emails, attachments, and files instantly — without heavy data downloads or server load. Share and edit documents — like never before.
The same client, three deployment modes — from a zero-install browser skin with local cache, to a native desktop app with direct helper access and minimal data transfer, to a fully offline store with all your data on disk.
Open documents, edit in your browser, vote on a poll — no account, no setup, all running against a live CGP server through the drift gateway.
Try the full webmail client right now. No installation required — just log in and explore all modules.
Powered by CommuniGate Pro · Served via Cloudflare Tunnel
Pick a format below or drop an existing file. The page (running on the live demo server) creates a fresh, uniquely-named copy and opens it in Collabora. Copy the URL after editing starts — anyone with the link joins live for collaborative editing.
Opens in a new tab on the live demo server. Copy the URL once editing starts — anyone with the link joins live for collaborative editing.
External event poll — recipients pick the time slots that work for them (preferred / available / unavailable) and see live results, all without an account.
Welcome to the CGatePro.net website of Stalker Software GmbH, CommuniGate Pro distributor since 1992 and part of the CommuniGate Stalker vendor group till 2019.
The Stalker Software GmbH sells CommuniGate Pro since 1992, is authorized distributor for licenses for 6.3, 6.4 and 6.5 versions.
We are now actively developing around CommuniGate Pro. Try our new drift interface and the CommuniGate Pro Server helpers that leverage the interface's capabilities to a new level.
A complete collaboration platform with tightly integrated modules, all communicating through the real-time XIMSS protocol.
Conversation threads, rich HTML composer, multi-mailbox search, attachment search, labels, flags, and print/PDF export.
Event management with month, week, and day views. Recurring events, attendee management, invitations, and shared calendars.
Business card view, contact groups, domain directory, CSV import/export, vCard support, and presence indicators.
Full file manager with drag-and-drop, document editing via Collabora Online, file sharing with ACL, and templates.
Task management with priorities, due dates, progress tracking, sharing, and iCalendar (vTodo) support.
Quick note-taking with folder organization, real-time sync, search, and collaboration through shared notebooks.
Instant messaging with XMPP, buddy lists, presence indicators, typing notifications, and chat history.
Edit Office documents in-browser via Collabora Online. Word, Excel, PowerPoint — real-time co-editing with WOPI integration.
Import PFX/P12 certificates, sign and encrypt outgoing emails, unlock private keys per session. Full certificate management built in.
Enterprise-grade architecture with IP protection, offline support, and native desktop performance.
Server-side helper services that extend CommuniGate Pro with advanced indexing, sharing, and third-party integrations.
Collabora™ and Zoom™ are trademarks of their respective owners. We do not license or resell these products.
Full implementation of CommuniGate Pro's XML Interface for Messaging, Scheduling, and Signaling. 31 protocol modules, instant push updates.
Encrypted local caching with configurable sync scope. WASM-based in-memory indexing for instant search without server round-trips.
Server-side plugins and tools for CommuniGate Pro administration, security, and compliance.
The same powerful web client, wrapped in a native desktop shell. Available for Windows, Linux, and macOS. Persistent credential storage, offline access, and direct file system integration.
.NET 8 WebView2 (Windows), Tauri/WebKitGTK (Linux), and Tauri/WebKit (macOS). Self-contained, no runtime dependencies.
DPAPI-encrypted password storage on Windows. Remember per session or permanently.
Encrypted file-based cache with configurable sync. Access emails, contacts, and calendar offline.
drift-offline Desktop
The current desktop client
Everything drift-all did, plus a full local mail store • Windows, macOS & Linux
drift-offline Desktop
4.0 — Full offline mode
CGP + IMAP mail cached locally • work without a network
A drift-all fork with a fully local mail store. Bodies, attachments, contacts, calendar, notes, and tasks are cached to disk on first sync; every module renders instantly from the cache and refreshes in the background when a connection is available. On a plane, in a tunnel, or when the CGP server hiccups — the app keeps working.
Every mail body and every attachment stored locally in a compressed SQLite store. Reads never touch the network once the cache is warm.
External IMAP accounts (Gmail, GMX, Outlook, any provider) sync into the same offline store as your CGP account. One inbox to work from, all cached.
Reply, flag, move, delete while offline — changes queue in a local outbox and replay to the server automatically when the connection returns.
Same ribbon UI, same CGP integration, same modules (Mail, Calendar, Contacts, Notes, Tasks, Files, Chat). Just with a working-copy of your data on disk.
Right-click any file or folder to hand out a view link, a Collabora edit link, a PDF, an upload drop zone or a photo album — plus instant sync via server push.
File synchronization for CommuniGate Pro. Sync your CGP file storage to a local folder, share files with public links, and manage access control — all from Windows Explorer or the macOS Finder.
Files sync automatically between your local folder and CGP. Copy a file in — it uploads within seconds. Changes on the server pull down instantly.
Right-click → "CGP Drive" (macOS: Quick Actions → "Share via CGP") to manage access control, or copy a ready-to-send link: view page, Collabora edit, PDF, upload drop zone for folders, or a photo album. Recipients need no account.
Single ~6 MB native Rust executable. No installer needed — just run it. macOS build signed with Developer ID and notarized by Apple.
Lives in your system tray with live sync status, progress popup, and recent activity. Native login dialog with saved credentials and autostart.
CGP Drive
Beta 1.3.1 — Windows, macOS & Linux
Single executable • No dependencies
Captures every business e-mail passing through CommuniGate Pro — including BCC — into a write-once, content-addressed archive with encryption, retention, legal hold, tamper-evident integrity, search and audit export.
Rechtssichere Archivierung nach GoBD, HGB §257 and AO §147. Two self-contained Rust executables, no third-party services — static for Debian 10 / AstraLinux and modern Linux, static-CRT on Windows.
A CGP ExternalFilter captures every message from the queue envelope — all recipients incl. BCC. If journaling is unavailable, CGP holds the mail rather than deliver it uncaptured.
SHA-256 content-addressed write-once store, chained tamper-evident integrity manifests, optional RFC-3161 timestamps, and XChaCha20-Poly1305 encryption with a protected key system.
Retention classes (6 / 8 / 10 years), named legal holds, and an operator-initiated, audited purge — never automatic, never before the retention date.
Field and full-text search (incl. BCC), audit export with per-file checksums, a loopback admin web UI, and an auto-generated German GoBD Verfahrensdokumentation.
drift-journal
v1.0.0 — Debian 10 / Linux & Windows
Self-contained • No runtime dependencies
Real-time communications for CommuniGate Pro. A tray app that handles calls, meetings for up to 12 people, screen sharing, instant messaging, and live presence — all built directly against your CGP server. Self-contained binary, no plugins, no browser tab open.
WebRTC under the hood, opus / VP8 / H264. Falls back to audio-only automatically if the camera is busy. In-window controls for mic, camera, hangup, and screen share.
Native picker (Entire screen / Window / Tab) via getDisplayMedia. Mid-call renegotiation if the call started audio-only — no need to redial.
Live buddy list with online / away / busy / on-phone indicators. iMessage-style chat threads with toast notifications. Call history persisted across launches.
Start a meeting and invite contacts from the roster. Every participant gets the video quality their connection can handle (simulcast via the drift meeting server on your CGP host). iPhone app available as TestFlight beta.
XIMSS command construction and event parsing live in an encrypted WASM module. The native binary contains zero XIMSS protocol literals (verified via binary strings audit).
drift-Companion
Version 1.1.9 — Windows & macOS
Self-contained • Licensed with your drift key
iPhone app: TestFlight beta on request
Video meetings for up to 12 people, straight from the browser. Create a room with your drift account, set a meeting password, and share the link — guests join without an account and without installing anything. Video and audio run through your own CommuniGate Pro server, not a third-party cloud.
Each meeting gets a short code and link. Guests open it in Chrome, Edge or Safari — also on iPhone and iPad — enter their name and the meeting password, and they are in.
Each camera is sent in three quality layers; the server gives every participant the layer their connection and screen size can handle — no lag for the one on mobile data, full quality for the one on fibre.
Share a screen, window or tab from any desktop browser. Click a tile to enlarge a speaker or a shared screen.
Media is encrypted in transit (DTLS-SRTP) and handled by the drift meeting server on your own CGP host. Meeting passwords are stored only as hashes, and a meeting disappears as soon as the last participant leaves.
drift Meet
Up to 12 participants — in the browser
No account for guests • No app needed
Starting a meeting requires a drift account on a licensed CommuniGate Pro server.
Flexible licensing for organizations of any size. All tiers include email, calendaring, instant messaging, and collaboration.
| Feature |
SMB
25 – 1,000 accounts
|
Enterprise+
10,000+ accounts
|
Telco / Provider
1,000 – 10,000 accounts
|
|---|---|---|---|
| Email (IMAP, POP, SMTP) | |||
| Groupware (Calendar, Contacts, Tasks) | optional | ||
| MAPI / Outlook Connector | optional | ||
| ActiveSync (Mobile Devices) | optional | optional | |
| VoIP / SIP Telephony | optional | optional | |
| Dynamic Cluster / HA | optional | optional | optional |
| drift Web & Desktop App | optional | optional | optional |
| CGP Helpers (Search, Files, Sharing) | optional | optional | optional |
All tiers include XIMSS, LDAP, S/MIME, file storage, and Collabora document editing.
Estimate the infrastructure you need for your deployment
Percentage of total users
Estimates based on typical workloads. Actual requirements may vary.
High-performance native helper applications that run on the CommuniGate Pro server. Built in Rust for Windows and Linux. No runtime dependencies.
Full-text search indexing for email and contacts. Builds per-account SQLite FTS4 databases for instant search across thousands of messages.
Full-text search indexing for user file storage. Indexes file metadata, ACLs, and extracted document content for instant file search.
Unified API for managing mailbox sharing, file sharing, subscriptions, and Send-As delegation via XIMSS CLI commands.
Email header rewriting filter that removes CommuniGate Pro branding from outgoing messages. Persistent CGP content filter protocol.
Injects a per-recipient, HMAC-signed HTTPS unsubscribe URL into every subscriber's copy of a CGP LIST distribution. Recipients unsubscribe with a single browser click — no mailto: handoff, works on machines with no OS mail client configured (Chrome-only laptops, tablets, iOS). Wires as a Server-Wide Rule Execute [RCPT] action; loops the subscriber list from argv, writes one personalized copy per recipient into Submitted/, and removes on click via CGP CLI — no confirmation-email round-trip.
text/plain and text/html, base64 & QPLIST … UNSUBSCRIBE …X-Drift-Injected guard)Per-domain DKIM signing for outgoing mail. Selects the signing key by the sender's From-domain, so alias domains get an aligned signature that CGP's built-in per-domain DKIM cannot provide — mail passes DKIM & DMARC at GMX, web.de and Google.
d=)Deploy CGP WebSkins over XIMSS — no server restart. Upload a skin folder, browse & read the files already on the server, and view or change the default skin server-wide or per domain. Native GUI & CLI for all platforms.
Secure gateway for sharing with external, account-less users — event-poll voting, file uploads & downloads, and Collabora document viewing/editing that saves straight into your CGP storage. A localhost Rust service reached through a CGP WSSP forwarder (driftgw.wcgp), authenticating back over XIMSS.
127.0.0.1:9084) via WSSP + XIMSSv0.6.20 — 2026-10-13. Hardened build (helper-protect + obfuscated strings + RSA license.key gate). Windows 10 1809+. Linux static against glibc 2.28 — runs on Debian 10/11/12, Ubuntu 20.04+, RHEL/CentOS 8+, Astra SE 1.7/1.8.
Full TLS certificate lifecycle for every CommuniGate Pro domain: discover, issue, install, renew — end to end, no manual OpenSSL / GUI clicks. Talks CGP CLI on port 106, ACME (Let’s Encrypt), and Cloudflare DNS-01. Ships an embedded web dashboard so an operator can see every domain’s status at a glance.
CertificateType=Disabled for ineligible domains127.0.0.1:8765Real-time push relay. Publishes new-mail and change events from the index helper straight to connected drift clients, so inboxes and folders update instantly — no client polling.
127.0.0.1:9085)Schedule Zoom meetings from the calendar, with the join details injected directly into the invitations. No server helper to install — enable and configure it in the client.
The four indexing/management helpers work without a license key in demo mode — limited to 5 accounts and 1 domain, with all features enabled. The dkim-signer filter signs unlimited domains and aliases free until 31 December 2026; after that it passes mail through unsigned until licensed. All helpers ship for Windows & Linux with no runtime dependencies. For production use, a license key unlocks configurable limits and domain binding.
Inside your CGP base directory, create a subdirectory for each helper under Helpers/. Place the binary and .cfg file in each.
mmindex.cfg
Email & contacts search indexing. XIMSS credentials optional (needed for live indexing and domain verification).
# CGP base directory (auto-detected if omitted)
# Windows: C:\CommuniGate Files Linux: /var/CommuniGate
basedir=C:\CommuniGate Files
# XIMSS connection (optional — enables live indexing + domain verification)
server=127.0.0.1
port=11024
[email protected]
password=YourPassword
# Domains to index (* = all, or comma-separated: example.com,other.com)
domains=*
# Index storage path (relative to each account directory)
indexdir=account.web/private/index
# Log level: 0=none, 1=error, 2=warn, 3=info, 4=debug
loglevel=3
# Keyword extraction: on = deduplicate + remove stop words, off = raw text
keywords=on
# Stop word languages: all = 57 languages, or ISO codes: en,de,fr
keywords_languages=all
# Live indexing: off, ximss, file, both (requires XIMSS credentials)
liveindex=ximss
# Debounce delay in seconds for live changes (default: 2)
liveindex_debounce=2
# Periodic full re-index interval in seconds (0=disabled, 3600=hourly)
indexperiod=0
# Batch size for DB operations (default: 100)
batchsize=100
# Mailboxes to skip (comma-separated wildcard patterns)
ignoremailboxlist=Spam*,Junk*,Calendar*,Contacts*,Tasks*,Notes*,Drafts
files-index-helper.cfg
File storage search indexing. No XIMSS needed — reads files directly from disk.
# CGP base directory
basedir=C:\CommuniGate Files
# Domains to index (* = all)
domains=*
# Index storage path (relative to each account directory)
indexdir=account.web/private/index
# Log level: 0=none, 1=error, 2=warn, 3=info, 4=debug
loglevel=3
# Content extraction from documents: on/off
keywords=on
access-rights-helper.cfg
Sharing & ACL management. Requires postmaster XIMSS credentials (all operations use CLI commands).
# XIMSS connection (required)
server=127.0.0.1
port=11024
[email protected]
password=YourPassword
# Log level: 0=none, 1=error, 2=warn, 3=info, 4=debug
loglevel=3
whitelabel-filter.cfg
Email header rewriting. No XIMSS needed. Set modify_files=false first to test in dry-run mode.
# Brand name replaces "(CommuniGate Pro SMTP 6.x)" in Received headers
brand_name=SMTP
# Message-ID prefix replaces "ximss-" (e.g. <msg-12345@domain>)
messageid_prefix=msg-
# X-Mailer replacement (empty = strip the header entirely)
xmailer_replacement=
# Rewrite queue files: true = modify, false = dry run (log only)
modify_files=true
# Headers to strip entirely (comma-separated, case-insensitive prefix match)
strip_headers=X-TFF-CGPSA,X-ExtScanner,X-AttachExt,X-MIME-Autoconverted
# Hostname replacement map: old:new pairs (comma-separated)
# Replaces internal hostnames across ALL header values
hostname_map=
# CGP base directory (resolves relative queue file paths)
# Windows: C:\CommuniGate Files Linux: /var/CommuniGate
cgp_base_dir=C:\CommuniGate Files
# Log level: 0=none, 1=error, 2=warn, 3=info, 4=debug
log_level=3
Go to Settings → General → Helpers. Add mmindex-helper, files-index-helper, and access-rights-helper as External App Helpers. Add whitelabel-filter and dkim-signer as External Filters. Set RestartPause to 30s.
These two run as standalone services on loopback — not CGP External App Helpers. Start notification-helper on 127.0.0.1:9085 (mmindex-helper publishes new-mail & change events to it). Start drift-gateway-helper on 127.0.0.1:9084 and deploy its WSSP forwarder driftgw.wcgp into your WebSkins — see the helper's Setup Guide & WSSP Deployment. Put them behind your reverse proxy / Cloudflare Tunnel for external access.
Place license.key in each helper's directory to unlock production account and domain limits.
Small server-side companion that lets drift-all open Office documents (.docx, .xlsx, .pptx…) directly in-browser via
Collabora Online.
Runs on the same machine as your CommuniGate Pro server, listens on loopback only, self-contained single binary — no Node.js runtime needed.
wopi-bridge.exe.powershell -ExecutionPolicy Bypass -File install-service.ps1DriftWopiBridge is registered, starts at boot, restarts on crash.sudo install -m 0755 wopi-bridge-3.3.1-linux-x64 /usr/local/bin/wopi-bridge
sudo useradd --system --no-create-home --shell /usr/sbin/nologin drift-wopi
sudo touch /var/log/drift-wopi-bridge.log
sudo chown drift-wopi:drift-wopi /var/log/drift-wopi-bridge.log
sudo install -m 0644 wopi-bridge.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now wopi-bridge
127.0.0.1:8200. Never exposed to the public internet.
What's new in each release.
Presence works across all your sessions, buddy requests and display names, presence icons without avatars (includes 4.0.91–4.0.96)
signalBind from the always-mounted Feedback view replaced the real registration (readIM + presence), so contacts stayed offline and buddy requests never arrived live. The IM store now owns the one signal binding.IMAP ↔ CGP switch is now instant — no 3-second body re-hydrate, no stale IMAP folder-tree refetch, no cryptic path flash in the header
exitImapMode() → loadEmails('INBOX') → STEP 1 wholesale-replaced cgpEmails.value with cold IndexedDB rows (headers only — bodies live in bodies.db). hydrateCgpBodiesFromCache then round-tripped ~6000 bodies back from disk, confirmed in log as [cgp-hydrate] INBOX merged 5964 / 5968 bodies from bodies.db → cgpEmails. Fix: tag cgpEmails with the folder it belongs to on every setter write; on same-folder re-entry, merge htmlBody/textBody/attachments/syncRequest/iCalendarRequest/smime from the existing in-memory rows into the fresh IDB rows before the setter runs. Hydrate’s needsHydration.length === 0 early-return now fires — ~3 s → ~100 ms. Folder-safe: a true folder switch (INBOX → Sent → IMAP → back) can’t cross-contaminate bodies between folders that happen to share UID values.[BOOT-TIMING] getMailboxes network=2432ms items=41 → total=4488ms tree=17 — every sidebar click did await bridge.getMailboxes(accountId), a full IMAP LIST (2–4 s blocking, folder tree empty until it returned). The disk snapshot was already there (loadMailboxTreesFromDisk runs on init, logs [IMAP] restored mailbox trees for 1 account(s) from disk), but selectAccount ignored it in online mode. Fix: show cached mailboxes immediately, set loading=false, fire selectMailbox(inbox.path); run bridge.getMailboxes in the background and swap only when the path-set actually changed (sig(fresh) !== sig(cached)) — unchanged trees don’t fire reactive re-renders. Mirrors the CGP folder-tree snapshot pattern from 3.6.65. First-ever account select still blocks on fetch because there’s nothing to show.__imap__/<guid>/INBOX path before updating to “INBOX”. MainLayout.vue:621 renders the folder-name header as mail.currentMailbox?.name || mail.currentFolder. On IMAP→CGP, exitImapMode() flipped isImapMode=false and fired loadEmails('INBOX') without pre-assigning currentFolder (deliberately, to avoid the top-level short-circuit at mail.ts:1417). loadEmails ran synchronously up to await mailApi.closeFolder(targetFolder) at mail.ts:1458, which yielded back to the event loop. Vue flushed DOM at that point with isImapMode=false AND currentFolder still __imap__/<accountId>/INBOX — mail.currentMailbox?.name returned undefined because no CGP mailbox has that path, so the header rendered the raw IMAP path for 100–500 ms until closeFolder’s XIMSS round-trip resolved. Fix: moved currentFolder.value = targetFolder and markMailboxKnown(targetFolder) to BEFORE the await closeFolder. isFolderSwitch was captured earlier at mail.ts:1400 with the old value, so the switch-detection logic is unaffected.Signed-mail green frame now renders in preview, full-screen viewer, and the drift-bar webskin
#070, dark-mode #0a0) hugging the content. Scrollbars live on <html> outside the frame — same layout the stock Samoware webmail uses (mail.samoware.css: .signed-part { border: 5px #070 solid }).ring-2 ring-inset: iframe compositing paved over the inset shadow. 4.0.69 outer-wrapper bg-green-500 p-[3px]: wrapped the iframe and its scrollbars. 4.0.70 body { border } inside the srcdoc: never shipped because samoware-tauri/overlay-patch has a wholly separate SandboxedEmailContent implementation (uses doc.open()/write() + allow-scripts + a WebView2 remote-image proxy) that build step 3 copies on top of master. The 4.0.72 fix lands the signed-part prop and CSS in both master and the overlay-patch copy, plus wires :signed="email.smime?.signed" through drift-all overlay EmailViewer so webskin picks it up.folderRead + x509 cert fetch — CGP verifies the signature server-side); normal mails continue the parallel-safe raw-MIME fast path. The signed-part wrapper is one extra div with CSS inside the sandboxed iframe — no runtime cost.Prefetch newest-first + tier-1 RAM hydration — freshest INBOX mails ready to open first
bodies.db on first launch. The old priority formula enqueued folder-by-folder in insertion order — the laptop log showed 50+ consecutive Gesendete Elemente (Sent) fetches before the INBOX got any attention. New formula: 100 (base) + max(0, 500 − daysOld) + (pinned ? 100 : 0) + (INBOX ? 300 : 0) so an INBOX mail from today ranks 900, a Sent mail from today ranks 600, and a 2-year-old Trash mail ranks 100. The scheduler’s existing priority-insert queue drains them in that order.drift:body-cached CustomEvent right after each successful bodyPut, carrying {folder, uid, html, text, attachments, headers}. The mail store listens, filters on currentFolder.value, and runs updateEmailInStore so the freshly-cached body lands in cgpEmails/searchResultContent without waiting for hydrateCgpBodiesFromCache on next folder-open. Pairs with the newest-first priority: by the time the user clicks their newest INBOX mail, both the bodies.db row AND the RAM entry are populated — no round-trip. Scope-limited to the current folder so this doesn’t pin thousands of out-of-folder mails into RAM.Mail now arrives automatically after sleep-wake / long disconnect (no re-enter needed)
doRecover chain already does the right dance (clearFolderCache + folderOpen + mailboxSync) but is gated behind terminal signals (<bye/> / 404 / 550 / errorText). Between 2026-09-23 (circuit breaker) and 2026-09-28 (single-poll-owner generation guard) that terminal path got hardened enough that sleep-wake now routes through the non-terminal watchdog-kick path — which fires drift-ximss-network-recovered but never reached the folder-reopen logic.stores/mail.ts now listens for drift-ximss-network-recovered and runs syncSingleFolder() on each folder in cgpAlwaysSync (= INBOX today) plus the currently-focused CGP folder. syncSingleFolder under the hood calls openFolderWithMeta (= folderOpen, which re-arms the push subscription if CGP reaped it; no-op otherwise) followed by mailboxSync against the stored syncID (= catch-up delta of accumulated UIDs). Idempotent + debounced via the existing RECENT_SYNC_MS guard inside syncSingleFolder, so a 24-error wifi-off/on burst collapses to one re-arm per folder rather than a thundering herd.__imap__/{accountId}/…) are skipped — the Rust-side IMAP IDLE loop recovers independently.Collapsible per-slot poll results page + Copy button in the Feedback dashboard
<details> slot rows. Each slot shows the ★/✓/✗ tally in its summary line; click to expand into three columns — Preferred, Available, Unavailable — each listing voter names with their email on a second line. Winner slots and the picked slot auto-expand on first load so the important ones are visible by default.localStorage so the organiser doesn’t re-toggle on every page load.[email protected] anchors — defeating the Show-emails toggle entirely. Wrapped each rendered email in the documented <!--email_off--> opt-out marker so emails pass through verbatim. Internal/local addresses (e.g. postmaster@laptop-…) that didn’t match Cloudflare’s rewrite heuristic came through clean the whole time — which is how we spotted it.Shareable view-only poll results URL — aggregate tally + per-participant grid
accessPwd like the per-voter links, but doesn't require allowSelfInvite since nothing can be written through the endpoint. URL shape: /sys/driftgw.wcgp/poll-results/~{organizer}/{pollId}/pwd/{pwd}/.emailSynthetic: true guests who joined without a real address) are hidden from the grid since they aren't meaningful contact info.PollResponseView for the organizer, with a one-click Copy button. Always visible — no toggle, since it's safe to share by construction.Poll votes no longer silently dropped — two stacked bugs fixed in drift + gateway
participants[] on disk showed only the organizer. Two bugs stacked: drift's savePoll overwrote gateway writes, and the gateway's submit_vote silently discarded votes for emails not already in the array (while still sending the organizer "voted on" email, which is how the organizer thought the vote landed).savePoll is now read-merge-write (samoware-vue/src/lib/ximss/polls.ts). Before: the local poll object got written as-is — any gateway writes between our last loadPoll and this save (self-invited joins, recorded votes) were overwritten by our stale snapshot. Any save path that fired between join-time and vote-time clobbered the gateway writes — including PollResponseView:72, which auto-saves on mount when the organizer opens the poll and the UI fills their own default votes. After: loadPoll runs first, non-organizer participants' votes + responded come from the fresh on-disk copy (gateway-authoritative), metadata and the organizer's own participant row come from local, fresh participants we haven't seen are appended. Falls through to a plain write if the fresh read fails (new poll, transient XIMSS error) rather than drop the save.submit_vote recover-inserts missing participants (drift-gateway-helper 0.6.11). The vote URL already proves email ownership via the accessPwd gate, so when no participants[] row matches req.email, we insert a new one with the submitted votes rather than let them vanish. The inserted row carries recoverInserted: true so the drift UI can show "recovered — organizer should check name/type". No spoofing surface: everything above the array scan still requires the per-poll password.Per-user native cache — fixes cross-account body/attachment poisoning
bodies.db + outbox.db) lived at one shared offline/ root and was keyed by a hard-coded __cgp__ synthetic account id. Switch CGP logins (A → B) and B's EmailViewer would hit A's cached body + attachment metadata at any colliding UID — handing A's filename + partId list to the Collabora opener, which then 404'd against B's live XIMSS session (Failed to fetch attachment: HTTP 404 on the Session/MIME URL in the console).bodies.db and outbox.db live under offline/users/<username>/. The Rust side holds a current-user slot (Mutex<Option<(username, Arc<Mutex<Connection>>)>>), new tauri commands offline_set_current_user / offline_clear_current_user wire the JS login/logout path to the slot. bodies_conn() transparently reopens against the new user's DB on first call after a switch; in-flight queries on the old Arc complete safely because the handle lives until last-ref-drop.offline/blobs/aa/bb/<sha256> is content-addressed by SHA-256, so dedup across users still saves disk; no leak, because the row that points at the blob (filename, partId, which user owns it) is in the per-user bodies.db.samoware-vue/src/lib/ximss/client.ts invokes offline_set_current_user({ username }) right after session.userName lands (both fresh-login and resume paths); logout() invokes offline_clear_current_user. Both guarded by isTauriRuntime() so the webskin build no-ops cleanly.offline/bodies.db + offline/outbox.db at the shared root are orphaned on upgrade (not read, not written). They age out via retention cleanup or can be deleted manually from the drift-offline app-data directory. Cache repopulates on first use under the new per-user path — expected after a fresh login.Bulk "Move to…" / "Copy to…" dialog + multi-item drag-drop in Files
FilesView.vue — once per operation. The picker reuses the existing recursive FileTree (same tree the sidebar uses), ESC cancels, Enter confirms. Confirm button stays disabled until a valid target is picked: refuses the source's own parent (no-op), refuses the source itself, refuses any descendant of a source (into-itself cycle). The picked path is shown as /foo/bar in a code chip above the buttons.handleDragStart now carries the whole selection when the dragged item is part of a selection > 1 (Finder / Explorer convention). Shift+click / Ctrl+click to build the selection, grab any of them, drop on a folder — all N items move at once. Previously a drag only ever carried the single item under the cursor and the other N-1 selected items stayed put._moveBatch / _copyBatch iterate the batch and call fileRename / fileCopy once per item. Errors are collected and shown as a single bulk-count alert (failedMoveBulk / failedCopyBulk) rather than aborting at the first failure. Same architecture as the 4.0.43 realignment: file operations are standard CGP XIMSS and must work against a naked CGP without any skin-specific .wcgp dispatcher.mv (FolderInput icon) and cp (Copy icon) between Rename and Delete, with bulk-count titles. The webskin master ribbon is a stub (no onClick handlers), so master gets only the drag-drop + dialog machinery, not the ribbon buttons.moveTo, copyTo, moveToN, copyToN, moveToTitle, copyToTitle, moveHere, copyHere, target, pickFolderHint, failedMoveBulk, failedCopyBulk — both en.ts and de.ts.Nice Vue dialog for Files delete — no more native WebView prompt
AppConfirmDialog (already used by mail + settings) with the variant: 'danger' style — red trash icon, "Permanent delete" heading, red "Delete" primary button. Replaces window.confirm() which rendered as the ugly native WebView2 window prompt on Tauri Windows and silently fails entirely on Tauri macOS WKWebView.FilesView.vue and the drift-all overlay copy.AppConfirmDialog is already mounted globally in App.vue; just imported appConfirm() from composables/useAppConfirm in both FilesView.vue files.Bulk file ops realigned to Samoware's native XIMSS pattern — works against a naked CGP
driftbatchfiles.wcgp server-side batch handler introduced in 4.0.39, along with its batchFileOps.ts client wrapper and the file deployed to WebSkins/drift-bar/. CGP skin cache cleared..wcgp dispatcher for file operations — main.production.js calls pure XIMSS commands (request("fileRemove", {fileName: s}, …)) in a loop. The copymove.wcgp + HTML-form POST pattern belongs to Crystalq, a different (pre-JS, server-rendered) CGP skin that happens to live in the same WebSkins/ folder. drift's 4.0.39 implementation was a Crystalq-pattern mimic mis-labelled as "Samoware's pattern". It worked in webskin by accident (session skin-binding lined up with the deployment location) and failed in Tauri because the session there binds to the server default skin.fileRemove / fileDirRemove XIMSS commands in a loop, exactly like Samoware. Works against any CGP install, no skin deployment, no CORS gymnastics, no HTTP-session SID juggling. Multi-select UI (Ctrl/Cmd+click, Shift+click range, "Delete (N)" ribbon) is unchanged — those are purely client-side.wcgp-wssp-use-http-sid-not-xmss.md) with the full rule set: file ops → XIMSS; .wssp → HTTP SID + Basic skin + proxy_fetch; /sys/driftgw.wcgp/* → gateway helper; never ship a custom .wcgp into a skin folder.Bulk delete actually deletes now — wrong CGP session type
.wcgp URLs need the WebUser HTTP session SID, not the XIMSS urlID. CGP's two session types are hard-disjoint by design: XIMSS sessions (/ximsslogin/) serve XIMSS XML at /Session/<sid>/sync; WebUser HTTP sessions (POST /) serve .wcgp / .wssp handlers at /Session/<sid>/*.wcgp. .wcgp URLs hit with an XIMSS SID return an empty <XIMSS/> envelope. 4.0.39–4.0.41's batchFileOps.ts wired the XIMSS urlID into the URL, so the handler never ran: the parse of <XIMSS/> as JSON failed, the error was swallowed, and the code reported "0 errors" without deleting anything. Webskin worked by accident — same-origin cookie authenticated independently.client.getHttpSessionId(). drift already bootstraps the parallel WebUser HTTP session at login via client.ts::bootstrapHttpSession (originally added for Mailing Lists admin, which has the same .wssp session constraint). batchFileOps.ts now uses that SID, matching the exact pattern in mailingLists/client.ts::sessionURL().location.replace('/sys/entry.wcgp')) → fallback with warning. All three decisions logged.[batch] POST …, [batch] proxy_fetch returned N bytes, [Files] bulk-delete start/done/errors) so any future regression is traceable without guesswork.wcgp-wssp-use-http-sid-not-xmss.md — any future .wcgp/.wssp feature will see this rule.Bulk delete now works on Tauri (routes through proxy_fetch)
driftbatchfiles.wcgp POST used a direct browser fetch(..., { credentials: 'include' }) which worked in the webskin (same origin as CGP) but silently failed in Tauri: the XIMSS session cookie is scoped to the CGP origin not tauri.localhost, and CGP doesn't send Access-Control-Allow-Origin: tauri.localhost, so the response was CORS-blocked. 4.0.41 routes the POST through the Rust-side proxy_fetch invoke — same pattern used by notifyHttp, login and the async long-poll — which carries the session cookie in its own jar and bypasses the cross-origin block.confirm() globally touches every module. Deletion itself works correctly.Regression fix: Files module no longer blanks on 4.0.39 Tauri build
FilesView.vue: the new selectedPaths ref was declared below the ribbon's computed, and useRouteRibbon's watch({ immediate: true }) triggered the computed body synchronously during setup — before selectedPaths was initialised — raising a ReferenceError that aborted the whole mount. The view came up blank. 4.0.40 hoists the state refs above the ribbon declaration. Webskin wasn't affected (master ribbon doesn't reference the new refs).driftbatchfiles.wcgp server-batch endpoint with XIMSS fallback — is unchanged.Bulk file ops — one HTTP round-trip for N items, Samoware-style
driftbatchfiles.wcgp, ported from Samoware/Crystalq's copymove.wcgp and extended with context=remove. One POST per batch (application/x-www-form-urlencoded with repeating file= / folder= pairs), server loops RemoveStorageFile / RemoveStorageDirectory, returns a JSON errors array. Replaces N × XIMSS round-trips with 1 HTTP round-trip for any N._handlerAvailable=false for the session and silently falls back to the per-item XIMSS loop. Users on CGP installs that haven't deployed the drift-bar skin still get bulk delete; drift-bar / drift-offline servers get the fast path.WebSkins/drift-bar/ via build-webskin.sh's existing webskin-src loop; CGP skin cache cleared on deploy. Bulk move + bulk copy use the same handler and ship in a follow-up with their path-picker UI.Zero-lag open for every brand-new push arrival
stores/mail.ts at both folderReport mode='added' branches (direct-add + added-via-updated), fire loadEmailContent(folder, uid) as fire-and-forget right after cgpEmails.unshift. loadEmailContent already does the dual write-through — updateEmailInStore populates cgpEmails.htmlBody/textBody (tier-1), and bodies.bodyPut inside mailApi.getEmail persists to bodies.db (tier-2) — so one call hydrates both.EmailViewer watch: content already loaded — no fetch, no lag. Completes the body-hydration architecture started in 4.0.34.Ban-fix round 2: cache every XIMSS discovery call, no retry except on network errors
setSessionOption deleted from client.ts. 4.0.36 Fix A neutered the external setSkinFromPrefs() wrapper but missed two inline setSessionOption calls inside postLoginInit() (reportMailboxChanges=yes is CGP's default; skin=<x> is redundant to URL routing). Removes 2 errors per login.mailboxList + mailboxSubList session memoise with layout-change invalidation. New cached wrappers in mailboxes.ts; calendar.ts, sharing.ts, mail.ts, notes.ts, tasks.ts, stores/contacts/folders.ts, sqliteContactsIndex.ts all routed through them. 17 raw call sites eliminated. Cache invalidates on mailboxCreate/Remove/Rename/SubUpdate + on drift-ximss-session-unrecoverable event. Removes 8–15 errors per reconnect.fileDirCreate() per-user cache (same pattern as 4.0.36 Fix B). Wrapper now remembers a successful create per-user in localStorage; ContactHubPanel.vue + TasksView.vue migrated from raw client.request to the wrapper. fileDirRemove invalidates. Removes 2–2N errors per reconnect.prefsRead session cache. loadFavorites() now caches the first response for the session; saveFavorites() invalidates. Removes 1–3 errors per reconnect.signalBind unbind-first guard in stores/im.ts. Module-level _everBound flag survives reset(); on a subsequent initialize() we issue signalUnbind before signalBind to avoid CGP's "already bound" errorText. Removes 1–2 errors per reconnect.client.ts was already clean — no silent retry on 550/404/XIMSS errorText anywhere; circuit-breaker (3 strikes) working as designed. The ban was purely a caching gap, not a retry gap.Reconnect no longer trips CGP's IP auto-blocker
setSessionOption for a skin that's already resolved by URL routing, 20 × fileDirCreate for drift's own working directories which already exist (polls, feedback, planevents, photos, drafts), and 5 × fileAttrRead on virtual paths that have no attributes. CGP's ProtocolErrorsLimit=5 / Period=2m counter does not care that the errors are harmless — it adds the client's peer IP to a 15-minute temp-block. This hit IPv6 loopback ([::1]) and real LAN clients alike on every reconnect-storm.setSkinFromPrefs is now a no-op. The active skin is already picked by the SkinFiles/<account>/<skin>/ URL path CGP routes against. Trying to set it again via setSessionOption only ever produced "unknown option" errors on strict builds. Removes 2 errors per reconnect.ensureDir remembers it already created the directory. Both feedback.ts and polls.ts now cache their fileDirCreate result per-user in localStorage plus a module-level Set. Removes 20 errors per reconnect; fresh installs still pay a one-time 5 errors on first login.fetchItemAttributes skips virtual paths after one error. files.ts now holds a session-scoped attrErroredPaths set — a path that returned 500 on fileAttrRead once is treated as attribute-less for the rest of the session instead of being re-asked on every refresh. Removes 5 errors per reconnect.GETTEMPBLACKLISTEDIPS stays empty across reconnect cycles.Instant-open everywhere: in-memory body hydration + mark-read/mark-unread stability pass
bodies.db store into the in-memory view store, newest-first. First-click opens of previously-cached mails are now tier-1 fast (~0 ms) instead of paying the ~30–100 ms SQLite + decompress + IPC round-trip. Up to ~1–3 s of background work per folder switch, non-blocking.mailboxSync against CGP for every mail folder on every re-plan tick, so bodies.db catches up to the live inbox within minutes of launch.MarkAsReadTimeout: '0') caused auto-mark-read to fire with zero delay for every click. This was invisible before body hydration made clicks instant — load time masked it — and became glaring once first-click opens landed in zero RAM time. The default is now empty (no CGP opinion), so the viewer falls through to drift's own 1 s delay. Users who deliberately configured MarkAsReadTimeout keep their value.drift-offline-<ver>-prev.exe covering 4.0.29 through 4.0.34, if the new build misbehaves. One-command restore from the previous.Composer blocks • Feedback dashboard • Live feedback push
uid_mv where the server supports it, instead of one connection per message. Previously, deleting 500 mails took > 90 s; it now completes in < 5 s.Rolling cleanup series
Execute [RCPT] wiring. Per-recipient list unsubscribe footers injected on delivery via a CGP Rule action; the helper writes one .sub file per subscriber and the gateway CLI removes on unsubscribe click.-MM-1 segment + -P.txt suffix) was dropped, breaking cross-account move. Both are now applied via cgpRaw.ts.bodies.db's FTS5 table so search returns matches on body + attachment contents.Pre-rendered app shell, instant module switching, live counters, mmindex-helper Linux port
loadEmails, syncSingleFolder, exitImapMode and syncFolder each short-circuit on redundant calls — module bounces stop firing XIMSS round-trips.run.sh, annotated config template, install runbook. Verified end-to-end under CGP 6.5.4 — clean INTF handshake, no retCode=13.Session-recovery hardening, attachment content search, offline-first folder tree, faster contact management
mailboxList still runs in the background and swaps in when it arrives.datasetDelete against the CGP dataset instead of an ignored messageRemove.target=_blank stripped so recipient mailto: links stop opening blank tabs.Ribbon toolbar with fully customizable buttons and hide-able inline toolbars
prefsStore) so the same layout follows you to every device you sign in from.__imap__/{account-id}/… path no longer appears in the UI.Search fixes and cleaner viewer for mail with many recipients
Mailing list management for list owners — settings, digest & archive, subscribers
Cleaning Jobs (auto-move rules for IMAP) • folder operations & nested mailbox tree • cross-account attachment copy & paste • IMAP reply-all & Cc fixes
Entw&APw-rfe.Name <addr> <addr>Bulk-delete safety • Trash detection • Multi-folder live sync • Settings prefs rebuilt • Vacation / forwarding rule fix
\Trash attribute, with multilingual fallbacks (Trash, Papierkorb, Gelöscht, Mülleimer, Deleted Items)Tims* preferences to Drift* with automatic migration of existing dataCalendar invite attachments • Maximizable event details • Files folder fixes
Search overhaul • Reliable delete in non-INBOX folders • Optimistic search-result delete
Folder hierarchy • Contact sync • S/MIME end-to-end
Event Polls — Collaborative Scheduling
File Sharing, Viewer & WASM Engine 0.9.2
Contacts & S/MIME hardening