Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Clients — Overview

The ecosystem has three native clients. Each talks only to the relay. No client uses IMAP or SMTP. One device pairing with a QR code or deep link creates the relay credential. After that, the relay handles mail, keyword tabs, push, and contact sync.

Which client for which platform

  • Androidkypost-android, package org.kysecurity.mail, FCM or UnifiedPush + pull fallback. The package rename is breaking for existing installs.
  • macOS & iOSkypost-for-Mac, bundle com.urlxl.mail, SwiftUI shared codebase, APNs + polling.
  • Linuxkypost-Linux, app id com.kysecurity.mail, KDE Plasma and Plasma Mobile, Qt6/Kirigami Flatpak, UnifiedPush + polling.

Common traits

All clients share:

  • Relay-only access. No mail credentials on the device.
  • A per-device credential minted at registration (deviceId + deviceSecret), revocable one device at a time, that cannot sign in to webmail.
  • Keyword-based inbox tabs that come from server fields. The user tunes them on each client.
  • Compose with contact autocomplete and an address-book picker.
  • Two-way contact sync against the relay.
  • PGP public-key exchange through QR codes with fingerprint confirmation out of band.
  • Optional device enrollment, after which the client reads end-to-end encrypted mail without the server. Until then, encrypted mail hands off to webmail rather than showing ciphertext. See PGP & Encryption.
  • Signature verdicts decided locally from keys the device holds, in six states. The relay’s own verified flag is not read.
  • Certificate pinning at first pairing. Android can additionally receive the pin in the pairing QR, closing the trust-on-first-use window.
  • Hostile Location Protection or equivalent keep-no-data-on-device option.
  • The same theme system. 15 themes that match byte for byte. Default is Patina Ky.
  • Deep-link scheme kypost://

Differences the READMEs highlight

AreaAndroidmacOS/iOSLinux
UINative Android screensiOS tab layout (MainTabView), macOS NavigationSplitView + pop-out WindowGroupPlasma desktop 3-column, Plasma Mobile bottom-tab, QML MobileRoot / DesktopRoot
Mail renderingNot detailedWebKit with JS off, remote content blockedWebEngineView with JS and remote images disabled
PushFCM native + pull GET polling, per-user push/pull mode on webAPNs + 90s foreground polling + iOS background refreshUnifiedPush distributor + 90s polling
LockPIN or biometric, escalating delays, wipe-on-repeat, common PINs rejectedRequire Unlock (Face ID/Touch ID/passcode), Hostile Location erases cachePIN lock with configurable lockout, grace period and erase threshold; credential seal with AES-256-GCM + Argon2
On-device PGPReads and writes once enrolledReads once enrolled; sending still goes through the relayReads and writes through the user’s own gpg-agent
Cached mail at restSQLCipher, key in the KeystoreSwiftData store with backup exclusionSQLCipher, converted in place on upgrade
LayoutPhone, plus a navigation rail and wide layouts at 600dp and master-detail via activity embedding at 800dpiOS tab layout, macOS three-pane + pop-out readersPlasma desktop 3-column, Plasma Mobile bottom-tab
QR cameraScan or show QR on one screen (Play Services code scanner)iOS scans with camera + pasted link fallback; macOS pasted link onlyCamera scan and show
LanguageKotlin (org.kysecurity.mail)Swift, SwiftUI, SwiftData, URLSession, WebKit; GopenPGP as its one external dependencyC++/QML, Qt6/Kirigami, SQLite/SQLCipher, GPGME

Bundle and naming

  • The Mac README says the app name is KyPost everywhere (Dock, Home Screen, About, permission prompts, project and scheme, deep link). Bundle IDs and Keychain group stay com.urlxl.mail on purpose. Renaming them is a separate high-risk step. See Brand_Refresh_KyPost.md.
  • Android app ID is org.kysecurity.mail. Existing installs of com.urlxl.mail must reinstall, pair again, and re-enrol any device-held PGP identity.
  • Linux app ID is com.kysecurity.mail, renamed from com.urlxl.mail. See docs/RENAME_NOTES.md in that repo.

Pairing

All clients pair from the web app. See Pairing for the deep-link format and validation.