build-packages prints a retirement notice, and cargo build does nothing
Tuta is an email service with a strong focus on security and privacy that lets you encrypt emails, contacts and calendar entries on all your devices.
At a glance
- What is it?
- This is the client source for Tuta, a mail service with built-in end-to-end encryption, and it is one repository containing TypeScript for the web app, a Rust SDK for the shared crypto and protocol code, an Android tree, an iOS tree and a desktop target. Releases are cut as separate per-app, per-platform artefacts, package.json carries a date-coded version ahead of the newest tags, and the contribution policy closes issues it suspects were written by a language model.
- Who is it for?
- Take this repository when you want to read or build a client for an end-to-end encrypted mail service, and you are prepared for TypeScript, Rust and two native toolchains in one tree. If you need a Linux desktop client, check the desktop download page first, since the README lists web, Android, iOS and a desktop client without naming its platforms.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- tutao/tutanota8,157 ★ · +218
| Repository | 2026-09-22 | 2026-11-14 |
|---|---|---|
| tutao/tutanota | 7.9k | 8.2k |
218 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Three artefacts per version, and the version encodes a date
The three newest releases are split by app and platform.
There is tutanota-desktop-release-362.261023.2, published on 2026-10-23, and tuta-drive-ios-release-362.261020.0 and tuta-drive-android-release-362.261020.0, both published on 2026-10-21. Each platform gets its own release, and there is no single combined release.
That matters for automation, because a release asset name is now platform and version in one string. And the version itself is a date with a counter in front of it: 362 is the sequence, 261020 is 2026-10-20.
Which brings up the mismatch worth knowing. package.json declares version 365.261030.0 and Cargo.toml declares the same, which is ahead of the 362 versions in the newest tags. Either the version is bumped on a build day rather than a release day, or the branch was already bumped after the last cut. The README does not explain it, so treat the release tags as the record of what shipped and the manifest as the record of what the branch thinks it is.
The last push to the default branch, master, was on 2026-11-02.
One repository, four toolchains, and two signing keys at the root
The top level entries describe the shape of this codebase better than the README does.
There is src/ and app-android/ and app-ios/, which are the three application trees. There is tuta-sdk/, which holds the shared code, and inside it a rust/ directory holding the crates of the root Cargo workspace. There are buildSrc/ and ci/ for the build itself, and libs/ for vendored code with third-party.txt alongside it.
Then the details that explain themselves only once you see them. android.js, webapp.js and desktop.js are per-target build entry scripts, and start-desktop.sh is what npm start runs. xcodegen_common.yml plus an ios:generate-project script means the iOS project file is generated rather than committed, from mail-project.yml, calendar-project.yml and drive-project.yml. fdroid-metadata-workaround is a directory whose name says what it is, and it exists because the F-Droid listing is one of the distribution channels.
Two files at the root are easy to misread. tutao-pub.pem and tutao-pub-test.pem are public keys, so committing them is correct.
And .nvmrc, .npmrc, .cargo/ and rustfmt.toml sit together, so Node, npm, cargo and rustfmt are each configured by the repository.
build-packages is a script that only prints a retirement notice
Two entries in the scripts block are worth reading as documentation rather than as commands.
One is start, which is:
./start-desktop.shso starting the whole application for development is a shell script, not a JavaScript entry point.
The other is build-packages, whose entire body is:
"build-packages": "echo '>>>> You no longer need to execute this <<<<<'",A retired script kept in place so that anyone following an old instruction gets told, in the terminal, that they no longer need to run it. That is a small courtesy and a real one: the usual outcome of removing a script is a not found error and a search through git history.
The rest of the block is a TypeScript project with three application targets. There are separate type-check scripts for mail, calendar and drive, each building its own tsconfig: tsconfig.json, tsconfig-calendar-app.json and tsconfig-drive-app.json. So the three apps are not one compilation unit, and a type error in the calendar app does not necessarily block the mail one.
There is also an import review pair, trace-imports and review-import-trace, which run node with a custom import hook and read an import-trace.json, which is dependency linting by a different route than the import rules you would expect.
cargo build does nothing, because default-members is empty
The Rust workspace in Cargo.toml has an unusual default, and the comment above it explains why.
default-members = []Above it: in most cases, we don't want to build everything, and this requires passing --all or --package to cargo for almost anything.
So a bare cargo build in the root of this repository compiles nothing at all. That is a deliberate guard against pulling the whole SDK into every incremental build, and anyone arriving from a normal Rust project will hit it immediately.
The workspace members list is five entries:
"tuta-sdk/rust/sdk",
"src/app-kit/mimimi",
"tuta-sdk/rust/uniffi-bindgen",
"tuta-sdk/rust/crypto-primitives",
"tuta-sdk/rust/util",Two things stand out. src/app-kit/mimimi is a single crate inside the TypeScript tree, so the boundary is not by language. And uniffi-bindgen is separate because, as the comment puts it, uniffi-bindgen does not have a CLI yet, with a second comment warning not to confuse it with the unrelated bindgen binary.
The package metadata is also unusual in a good way: publish = false, so the SDK is never accidentally pushed to a registry.
uniffi is pinned to a commit hash, and it binds Rust to Kotlin and Swift
The workspace dependency list explains what the Rust side is for.
It has tuta-sdk, crypto-primitives and util as path dependencies, all declared with default-features = false, so a consumer opts into what it needs. Then the external crates: base64, log, serde with derive and rc, serde_json, tokio with default-features off, and rand.
The entry that carries the design is uniffi:
uniffi = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "13a1c559cb3708eeca40dcf95dc8b3ccccf3b88c", default-features = false }Pinned to a commit hash of Mozilla's uniffi-rs repository, not to a version and not to its default branch. uniffi is the framework for generating foreign function interface bindings from Rust, which is how one crypto implementation reaches a Kotlin Android client and a Swift iOS client without being written three times. A commit pin is a deliberate choice: reproducible, and immune to somebody moving a tag.
The toolchain is stated alongside:
rust-version = "1.84.0"
edition = "2021"and the resolver is version 2 with a comment saying it can move to 3 once 1.84.0 is available, which is a small sign of a workspace that tracks its own floor closely. The lints section has the cargo lints block commented out with a note that lints.cargo is not supported on stable yet.
IPC bindings are generated by licc from a schema directory
Three application targets in one product need one protocol, and the repository generates the bindings rather than maintaining them.
There is an ipc-schema/ directory at the root, and a generate-ipc script that compiles a generator and then runs it against that directory:
node build/licc/cli.js ipc-schemaThe whole script is a chain: build the licc compiler with tsc from buildSrc/licc/tsconfig.licc.json, run its CLI against the ipc-schema directory, then run the formatter over the result. So generated code is formatted before it lands, which means it does not immediately show up as a diff against the style rules.
licc is the project's own name for the generator, and it lives in buildSrc/ rather than in a dependency, so the schema and the generator are versioned together. That keeps the schema and the generator in one place.
LLM-written issues are closed, machine-translated ones are not
The contribution policy is the last section of the README and it is the most unusual.
The project states that it does not accept contributions or bug reports produced, in part or in full, with the assistance of large language models or generative AI. Maintainers will close issues or delete comments without further explanation if they suspect that any part of the issue is generated.
And then the sentence that makes the policy precise: incomplete or automatically translated issue reports are still welcomed and encouraged over LLM-assisted ones.
So the line is not about machines at all. A human writing in another language and using a translator is fine. A human submitting text a language model produced, even partially, is not. The test is provenance of the words rather than the reporter.
The other half of that section is where to file things. Reddit is the forum for bug reports and feature requests, there is a roadmap on the website, and the GitHub issue tracker exists but the README asks you to submit feature requests via Reddit or support mail instead.
Editorial conclusion
Take this repository when you want to read or build a client for an end-to-end encrypted mail service, and you are prepared for TypeScript, Rust and two native toolchains in one tree. If you need a Linux desktop client, check the desktop download page first, since the README lists web, Android, iOS and a desktop client without naming its platforms. Verify three things. Read the contribution policy before you file anything, because the project states it does not accept contributions or bug reports produced with assistance from large language models, and that maintainers will close such issues without further explanation. Expect bugs through Reddit rather than the tracker, since the README names Reddit as the forum for bug reports and asks for feature requests there or by support mail. And read the version numbers carefully, because the newest releases are 362.261023.2 for desktop and 362.261020.0 for Drive on iOS and Android, while package.json and Cargo.toml already read 365.261030.0.
Frequently asked questions
what is tutanota
Tuta Mail is a secure email service with built-in end-to-end encryption that lets you communicate securely with anyone on all your devices. The description says it encrypts emails, contacts and calendar entries, and it offers a web client at app.tuta.com, an Android app on Google Play and F-Droid, an iOS App Store app and a desktop client.
what is tutanota used for
Encrypted email, contacts and calendar entries across all your devices. The clients are a web client, an Android app on Google Play and on F-Droid, an iOS App Store app and a desktop client. The service publishes a roadmap at tuta.com/roadmap, and this repository holds the client source under GPL-3.0.
is tutanota safe
The README describes Tuta Mail as a secure email service with built-in end-to-end encryption and a strong focus on security and privacy, and this repository is the client source, released under GPL-3.0 with a SECURITY.md at the root. The README makes no audit or independent verification claim, and says nothing about the server beyond that encryption claim.
is tutanota free
The README does not discuss pricing for the service. What it states is that this repository, the client source, is released under the GPL-3.0 licence, and that the clients are distributed through Google Play, F-Droid, the iOS App Store and a desktop download.
how to install tutanota on ubuntu
The README does not say which operating systems the desktop client supports. It points at a web client at app.tuta.com, an Android app on Google Play and on F-Droid, an iOS App Store app and a desktop client. Building from source is covered in doc/BUILDING.md, and the repository root carries an fdroid-metadata-workaround directory.
is tutanota good
The project's own claim is that Tuta Mail makes encryption easy and provides secure email with built-in end-to-end encryption across all your devices, covering email, contacts and calendar entries. It publishes a roadmap, takes bug reports on Reddit, and asks for feature requests through Reddit or support mail rather than the GitHub tracker.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tutao-tutanota)Star history chart for your README
[](https://hysenlabs.com/projects/tutao-tutanota)Was this useful?