8000 feat(tuta): native Tuta accounts with encrypted Tuta-to-Tuta mail by hanthor · Pull Request #584 · hyprlab/hylki · GitHub
[go: up one dir, main page]

Skip to content

feat(tuta): native Tuta accounts with encrypted Tuta-to-Tuta mail - #584

Closed
hanthor wants to merge 4 commits into
hyprlab:mainfrom
tuna-os:feat/tuta-native
Closed

hanthor wants to merge 4 commits into
hyprlab:mainfrom
tuna-os:feat/tuta-native

Conversation

@hanthor
@hanthor hanthor commented Nov 5, 2026 •
Copy link
Copy Markdown
Contributor

Adds Tuta as a native account type. Tuta has no IMAP, SMTP or JMAP, so the account goes through hylki-tuta, a small helper built on Tuta's own Rust SDK (via tutabridge). Hylki starts it per operation, or once for push, and talks to it as versioned JSON over stdin. It opens no port and keeps no files.

What works

  • Sign-in: password, plus an authenticator code when the account has one. Only the resumable session is kept, in the keyring under session:<address>; the password is never stored.
  • Tuta-to-Tuta mail: mail to Tuta addresses is end-to-end encrypted, as in Tuta's own apps. The bucket key is encrypted to each recipient's current public key (TutaCrypt or legacy RSA) by the SDK's own key facade. A Tuta address with no key is refused before anything is written. Mail with outside recipients goes as ordinary mail, as in Tuta's apps without a password set.
  • Reading: bodies decrypted locally and rendered through the existing reader.
  • Threading: replies and forwards thread through the parent's Message-ID (Tuta's conversation entry for internal mail), and the parent is marked replied or forwarded.
  • Sync: folders with their roles; push through Tuta's event bus, falling back to polling; background index and offline download.
  • Folders: create, rename, move and delete.
  • Tags: tags are Tuta labels, created on first use in the tag's colour; labels set in Tuta's apps show as the matching tag.
  • Mail actions:
    • read state, move, spam and ham;
    • permanent delete, through Trash as the server requires, and emptying Trash or Spam;
    • undo and snooze, which work on mail that was never opened because Tuta keeps a mail's id when it moves.
  • Drafts and templates live on the server.
  • Import into a folder through Tuta's ImportMailService, on Legend and Unlimited plans (Tuta's own rule). Other plans get a clear refusal.
  • Revoking the session when the account is removed.

Limits

  • No server-side stars: Tuta has none, so they stay local, as on POP3.
  • No secure delivery to outside recipients with a password.
  • Security keys (U2F/WebAuthn) are not supported, only TOTP.
  • No manual key verification; this matches Tuta's default for contacts the user never verified. The send reply carries each recipient key's version and fingerprint as a hook for pinning later.

SDK patches

The pinned SDK keeps a few things private that a client needs, so native/tuta/sdk-patches/ carries three small patches, which native/tuta/prepare.sh applies after tutabridge's own sdk-prepare.py:

  1. Recipient key data through the SDK's own AsymmetricCryptoFacade and PublicKeyProvider. No crypto is written outside the SDK, and the patch comes with SDK unit tests.
  2. Decrypting service replies with the request's session key, as the official client does.
  3. Entity PATCH, so a reply mark changes one field instead of re-encrypting the whole mail.

The patched tree goes to native/tuta/prepared/ with its own EXPECTED digest, so tutabridge's build check still covers exactly what is compiled.

Sending safely

A send whose outcome is unknown is never retried and never queued: Hylki shows "The message may have been sent. Check Sent before trying again." The helper decides this from what actually went over the wire, so a request that never left is a plain failure.

Packaging

The helper is a separate GPL-3.0-or-later crate under native/tuta with its own Cargo.lock. Flatpak, RPM, deb and AppImage build it and install it next to hylki; Hylki looks for it there first, then on PATH, and everything except Tuta works without it. CI prepares the SDK, generates the helper's cargo sources and runs its tests. docs/BUILDING.md and docs/LICENSE.md describe both.

Testing

  • Helper: 124 unit tests, including Tuta's own importer test vectors, plus 4 SDK tests for the key-data patch.
  • Hylki: fake-helper tests for every operation and send outcome, and editor and wizard tests for the Tuta form. The full suite passes apart from five tests that fail the same way on main in the GNOME 50 SDK sandbox: three tray icon renders, the MCP stale-socket test, and the own-mailbox card face.
  • Live, against a real Tuta account (#[ignore], gated on TUTA_LIVE*), every step through the worker's own handlers:
    • sign-in with TOTP, sync, and a decrypted body;
    • push ready and mail_changed;
    • an encrypted send to self, with the reply carrying confidential: true and the TutaCrypt key, and the mail decrypting in Inbox and Sent;
    • folder, label and draft round trips;
    • a reply threaded and marking its parent;
    • permanent delete;
    • a cleanup sweep that leaves nothing behind.
      Import was checked only up to the plan refusal, because the test account is on Essential.
  • Flatpak: built locally from the working tree; hylki-tuta runs inside it.

This came out of the Postcard mail client's Tuta work and was written with AI assistance. I'm happy to adapt it to how you want the code laid out.

Tuta has no IMAP, so a small Rust helper built on Tuta's own SDK speaks to it and talks to Hylki as JSON over stdin. The Flatpak, RPM, deb and AppImage builds compile it and install it next to hylki, and CI tests it.
A Tuta account signs in with its password and authenticator code through the bundled helper, which keeps only a session in the keyring. Mail syncs by polling, bodies decrypt locally, and sending goes to outside addresses. A send whose outcome is unknown is never retried.
native/tuta/prepare.sh prepares the Tuta SDK, then applies three small patches carried here: recipient key data for encrypted sends through the SDK's own key facade, decrypting service replies with the request's key, and entity PATCH. Every build path runs it.
Mail to Tuta addresses now goes end-to-end encrypted, as in Tuta's own apps. Folders can be created, renamed and deleted, tags map to Tuta labels, drafts and templates live on the server, mail can be deleted for good, imported, snoozed and undone, replies thread, and new mail is pushed instead of polled.
@hanthor hanthor changed the title feat(tuta): sign in to Tuta accounts natively feat(tuta): native Tuta accounts with encrypted Tuta-to-Tuta mail Nov 5, 2026
@hyprlab
hyprlab commented Nov 5, 2026
Copy link
Copy Markdown
Owner

Thanks for the PR but I am declining the merge. Tuta doesn't support third-party clients in this way and I do not wish to create something that might go against their EULA.

@hyprlab hyprlab closed this Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0