Files
tutabridge/README.md
T

149 lines
5.0 KiB
Markdown

# TutaBridge
A local IMAP/SMTP bridge for [Tuta](https://tuta.com) encrypted email. It runs a
local IMAP+SMTP server that ordinary mail clients (Thunderbird, Apple Mail, mutt,
…) connect to, while talking to Tuta's API and handling the end-to-end
encryption transparently.
Available as a **CLI** and a **desktop GUI** (Tauri).
## Features
- **IMAP + SMTP** servers on localhost (TLS), so any standard mail client works.
- **Realtime sync** over Tuta's WebSocket event bus — new mail, reads, moves and
deletes show up without polling. A heartbeat + idle-timeout detect dead
sockets and reconnect automatically.
- **Attachments** both ways — incoming mail is served as `multipart/mixed`;
attachments composed in your client are uploaded to Tuta on send.
- **Drafts**, **custom / nested folders**, **move**, **trash**, and read/unread
flags.
- **2FA (TOTP)** login.
- **Encrypted local cache** — metadata in SQLCipher, bodies as individually
encrypted `.eml.enc` files. Subsequent launches load from cache and only fetch
the delta, so the client is usable immediately.
- **Complete mailbox backup** to portable `.eml` files (see below).
## Architecture
Syncer-driven, store-backed:
```
Tuta API ←── Syncer (background) ──→ MailStore (in-memory) ←── IMAP server ──→ mail client
←── GUI (stats)
```
- The **syncer** pulls from the Tuta API and populates an in-memory `MailStore`,
backed by the on-disk encrypted cache.
- The **IMAP server** only ever *reads* from the store — it never makes API
calls for reads.
- The only IMAP→network calls are mutations: mark read/unread (`STORE \Seen`)
and trash (`EXPUNGE`). Sending goes through SMTP → Tuta's `DraftService` +
`SendDraftService`.
The storage encryption key is derived from your Tuta session, so there's no extra
password to manage; the cache is encrypted at rest.
## Build
```bash
cargo build # CLI + core
cargo build -p tutabridge-core # core library only
```
GUI (Tauri + React) in dev mode:
```bash
./dev.sh # cargo tauri dev — opens the desktop app
```
## Running the bridge
CLI:
```bash
cargo run # or: ./target/debug/tutabridge
```
On first run it prompts for your Tuta email; the session is then stored in the OS
keychain so later launches resume without a password (TOTP is prompted when
required). The bridge prints the local connection details:
```
IMAP server: 127.0.0.1:1143 (SSL/TLS)
SMTP server: 127.0.0.1:1025 (SSL/TLS)
Username: <your tuta email>
Password: <bridge password — shown in the logs / GUI>
```
Point your mail client at those, accept the self-signed certificate, and use the
**bridge password** (not your Tuta password) for IMAP/SMTP auth.
Config and cache live under
`~/Library/Application Support/tutabridge/` (macOS):
```
config.toml account + ports + bridge_password + sync_limit
store.db SQLCipher metadata index
mails/<id>.eml.enc per-mail encrypted bodies
```
## Backup
Export **every** email to a folder of plain `.eml` files — one file per message,
in a directory tree mirroring your IMAP folders. This is a *complete* backup: it
enumerates all mail from the server, not just the messages currently synced, so
nothing is silently left out.
```
<output>/
├── INBOX/
│ ├── 20260528-144935_OtjDuDU--3-9.eml
│ └── …
├── Sent/
├── Trash/
└── Café/Projets/…
```
CLI:
```bash
tutabridge backup ~/TutaBackup
```
GUI: the **Backup** tab — pick a folder, watch the per-folder progress, done.
(The bridge must be running; the backup reuses its signed-in session.)
Notes:
- **Format**: `.eml` (RFC 2822). Opens natively in Thunderbird / Apple Mail /
Outlook, survives Windows filesystems, and one corrupt file never takes down
the whole archive. Filenames are date-prefixed so a listing sorts
chronologically.
- **Resumable / incremental**: re-running into the same folder skips messages
already on disk, so an interrupted backup resumes and a periodic re-backup only
fetches new mail.
- **Speed**: messages already in the local cache export instantly; the rest are
fetched from the server with a small politeness delay, so a first full backup of
a large mailbox can take several minutes. Subsequent runs are fast.
- **Scope**: every folder, including Trash and Spam. Labels aren't separate
folders, so a labelled mail is backed up once, in its real folder.
## Testing
```bash
cargo test --workspace # unit + integration tests
python3 scripts/test_imap.py # integration test against a running bridge
```
The IMAP integration test connects to the local server and verifies TLS, auth,
folder list, mail count, body fetch and search. It reads the bridge password from
`config.toml` automatically.
## SDK
TutaBridge depends on a few additions to Tuta's Rust SDK, vendored as the
`tuta-repo` submodule. Each change is kept as its own single-commit branch off
upstream for easy review / upstreaming — see [`SDK_PRS.md`](SDK_PRS.md) for the
status of each.