8000 feat(proton): sign in to Proton Mail accounts natively by hanthor · Pull Request #586 · hyprlab/hylki · GitHub
[go: up one dir, main page]

Skip to content

feat(proton): sign in to Proton Mail accounts natively - #586

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

hanthor wants to merge 9 commits into
hyprlab:mainfrom
tuna-os:feat/proton-native

Conversation

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

Adds Proton Mail as a native account type, next to the existing "Proton Mail (Bridge)" preset, which is unchanged.

This builds on #584 (Tuta). It reuses that PR's helper client, sign-in flow and uncertain-send handling, so the first two commits here are #584's. Only the five proton commits are new. I'll rebase once #584 is settled.

Why offer this after #335

#335 asked for native Proton, and was closed with "Bridge is the correct way of doing this that maintains Proton's security infrastructure", alongside a fair worry about unaudited crypto. This PR tries to answer both points rather than argue with them.

  • No crypto of our own. The helper is a small Go program, hylki-proton, built on Proton's own libraries: go-proton-api for the API and SRP sign-in, and gopenpgp for keys and messages. The revision is the one Proton Bridge pins today. The per-recipient send rules are a port of Bridge's own table. Keys are unlocked in the helper and nowhere else.
  • Same infrastructure Bridge uses. Bridge is these same libraries plus a local IMAP/SMTP server. The helper is these libraries without the server: no open port, no daemon, no local IMAP password, and nothing kept on disk by the helper. Hylki starts it per operation and talks to it over a private pipe.
  • It reaches more people. Bridge needs a paid plan and a separate app running. Native sign-in works for any Proton account Hylki can sign in to.
Bridge preset Native (this PR)
Needs Bridge running, paid plan nothing extra
Crypto Proton's libraries the same libraries
Local surface IMAP/SMTP on 127.0.0.1, a Bridge password a pipe to a short-lived process
Push IMAP IDLE via Bridge Proton's event stream, polled
Maturity Proton's product new

If you'd still rather not carry it, that's understood; we'll keep it in our fork.

What works

  • Sign-in: password, authenticator code, mailbox password for two-password accounts, and Proton's human verification. The CAPTCHA is shown in a WebKit dialog limited to https://*.proton.me, with its own ephemeral session and settings, separate from the mail reader.
  • Session: only a rotating session is kept, in the keyring. Every helper reply hands back the refreshed tokens, and the worker saves them under a per-account lock before acting on the result.
  • Sync: folders and labels with their roles, incremental sync through Proton's event stream, and the background index.
  • Reading and organising: bodies decrypted locally, read state, stars (Proton's Starred label), and moves including spam, ham and Trash.
  • Sending: Proton recipients are end-to-end encrypted. Outside recipients get PGP/MIME when Proton or a contact has their key, and cleartext otherwise. Replies and forwards link to their parent so Proton threads them. A send whose outcome is unknown is never retried (same rule as feat(tuta): native Tuta accounts with encrypted Tuta-to-Tuta mail #584).
  • Removal: revoking the session when the account is removed.

Limits

  • No server search, folder create/rename/delete, server-side drafts, or permanent delete.
  • Mail can't be moved in from other accounts.
  • User labels can be browsed but not applied.
  • Reply-all is inferred from a reply having more than one recipient, because the composer doesn't record it.

Testing

  • Helper: go test against go-proton-api's in-process server covers:
    • sign-in, including TOTP, mailbox password, human verification and token rotation;
    • sync and event changes;
    • decrypting to MIME;
    • read, star and move;
    • sending to Proton recipients (each recipient decrypts their own copy, Bcc included), to outside recipients in cleartext and with a key;
    • reply threading;
    • every failure mode of the submit, including the uncertain ones.
  • Hylki: a fake helper drives every operation, session rotation on success and on error, the per-account lock, and the error mapping. The editor and wizard tests cover each revealed row. Unit tests cover the verify-message parser and URL building. The full suite passes apart from the five tests that fail on main in the SDK sandbox.
  • Flatpak: built locally from the working tree; both helpers run inside it.
  • Live: not yet. Against a real account, Proton now asks this network for a CAPTCHA before sign-in, and that needs a person. The live test (PROTON_LIVE*, with a pre-solved challenge) is ready and will be run before this leaves draft.

Written with AI assistance, like #584.

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.
A bundled Go helper speaking JSON over stdin signs in with SRP and TOTP, syncs folders and pages, decrypts messages to MIME, marks read, moves, sends with Proton's per-recipient packages, and revokes the session. It never reports a send it cannot confirm as sent.
The Go helper is built offline from its vendored modules in the Flatpak, RPM, deb and AppImage builds and installed next to hylki, and CI tests it on both architectures.
Proton Mail works without Bridge: the bundled helper signs in with SRP, an authenticator code, a mailbox password and Proton's human verification when asked, keeps only a rotating session in the keyring, syncs through Proton's event stream and sends with Proton's own encryption. The Bridge preset is unchanged.
@hanthor
hanthor force-pushed the feat/proton-native branch from a809e8f to e69a137 Compare November 5, 2026 16:08
@hyprlab
hyprlab commented Nov 5, 2026
Copy link
Copy Markdown
Owner

Appreciate the PR but I am going to decline the merge. Proton Bridge is the proper and safest way of interacting with Proton Mail how the devs intended. Hylki fully supports Bridge.

@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