The CLI (`src/main.rs`) only spawned the syncer + IMAP + SMTP servers
and never started an `EventBusClient` — so the realtime push the
GUI's `BridgeHandle` ships had no effect when running `cargo run` or
the headless binary. Mails that arrived after a bootstrap sync were
silently missed until the next restart with a forced full re-sync;
that's the irritant that triggered today's WS heartbeat/timeout audit.
Replicate the bridge.rs initialisation directly: build an
`EventBusClient`, hydrate `last_batch_ids` from
`event_bus_state` (with the same 44-day expiration guard), spawn
`bus_client.run` alongside the syncer and an
`event_handler::run_event_handler` to consume the mpsc, and log
WsState transitions at INFO so reconnect storms are visible without
`RUST_LOG=debug`. Shutdown aborts the bus + handler handles in the
same Ctrl-C arm as the syncer.
To avoid duplicating the model-version + client-name plumbing, the
helpers `bridge::sys_model_version`, `bridge::tutanota_model_version`
and `bridge::CLIENT_NAME` are now public, and the root crate gains a
direct `tuta-sdk` dependency (already present transitively through
`tutabridge-core`).
SDK (sdk-event-bus amended on the fork): a new `WsState` enum
(`Stopped`/`Connecting`/`Connected`/`Reconnecting`) is broadcast through a
`watch::Sender` inside `EventBusClient`, exposed via `state()` for
observers. Transitions are emitted at every step of the reconnect loop,
plus a `Drop` guard guarantees a final `Stopped` even on a panic in the
caller's task tree. Two new SDK tests cover the initial value and
multi-subscriber broadcast.
Bridge: capture `bus_client.state()` at start, mirror it into a serde
`WsStatus` field on `BridgeStats`, and clear on stop.
UI: add a third stat card "Realtime" with a colored dot (green Connected,
orange pulsing Connecting/Reconnecting, gray Off) reading
`stats.ws_status`. Stats grid switches from 2 to 3 columns.
Submodule pointer bumped to the rebuilt `tutabridge-integration` which
cherry-picks all six SDK branches on `upstream/master`; the move-mails
fixup (use `make_test_facade` so its test compiles alongside the blob
branch) is re-applied. 341/341 SDK lib tests pass, 154/154 bridge tests
pass.
The 60s list-sync loop is replaced by the WebSocket event bus from the
SDK (sdk-event-bus). On startup the syncer still does Phase 0 (load the
local store into memory), then a one-shot bootstrap sync only if no
event-bus catch-up state is cached. From there on:
- `EventBusClient` runs in its own task, streams `EventBusMessage`s into
an mpsc channel and reconnects with backoff.
- `event_handler` consumes the channel: MailSetEntry CREATE/DELETE
triggers a targeted `sync_folder` for the affected folder; Mail UPDATE
refreshes metadata in place; Mail DELETE drops the cache + .eml.
- After each batch the `(group_id, batch_id)` is persisted in the new
`event_bus_state` SQLite table (schema bumped to v4) and mirrored in
the bus's in-memory map, so the next reconnect resumes catch-up via
`groupsToLastEventBatchIds`.
`stop()` aborts and awaits the new bus + handler tasks alongside the
existing syncer/IMAP/SMTP teardown, so ports release before the next
start rebinds them.
138/138 bridge unit tests pass (incl. 2 new ones for the event-bus state
table). End-to-end behaviour to be verified against the live server.
Split the bridge into a tutabridge-core crate, a Tauri v2 desktop app
(src-tauri) and a React/TS UI (ui), keeping the CLI entrypoint at the
workspace root.
Add encrypted local storage (SQLCipher metadata index + encrypted .eml
files) so mail persists across launches and only the delta is fetched.
Wire the bridge to the Tuta Rust SDK via the tuta-repo submodule
(batch loading, MailDetailsBlob reading, interactive 2FA login).
Implement SMTP sending: build the draft and send it through Tuta's
DraftService/SendDraftService, mirroring the web client (body in
compressedBodyText, non-empty sender/recipient names, populated
SendDraftParameters). Add unit tests for the draft/send payload building.
Local bridge that exposes Tuta encrypted email via standard
IMAP/SMTP protocols for use with Thunderbird and other clients.
Features:
- IMAP server with TLS (STARTTLS self-signed cert)
- SMTP server for sending mail via Tuta
- Session persistence via macOS Keychain
- Mail body decryption including LZ4-compressed blobs
- Blob storage access (BlobAccessTokenService + blob server)
- RFC 2822 message formatting
- Interactive first-run configuration