Self-hosted service
linagora/tmail-flutter avatar
linagora/tmail-flutter

Twake Mail is a Flutter JMAP client that treats the server choice as its main deployment decision

A multi-platform (Flutter) application for reading your emails, with your favorite devices, using the JMAP protocol!

660 stars128 forksDartAGPL-3.0

At a glance

What is it?
linagora/tmail-flutter builds a multi platform email client on Flutter that speaks JMAP instead of IMAP, ships as Android, iOS and web builds, and pairs with a Twake Mail back end for features such as labels, delegation and filters. It is AGPL licensed, released monthly, and the web target is a static bundle served by nginx.
Who is it for?
Use tmail-flutter if you run a JMAP server, you want a mail client your organisation controls from source, and you are willing to build the Flutter targets yourself. Do not expect it to be a drop in replacement for an IMAP client, since the project drops support for calendar and contacts extensions outright and pushes desktop only through contributed work.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Dart, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A mail client that speaks JMAP over HTTP and JSON

Twake Mail is a multi platform email application written in Flutter that reads your mail using the JMAP protocol. The repository description puts it plainly: read your emails with your favourite devices, using JMAP.

That protocol choice is the project's identity. The FAQ section explains the reasoning at length, and the argument is worth following because it explains why a new client would be built at all.

IMAP is described as the ubiquitous protocol, the norm for reading email, but as having been designed in another age, which produced a chatty patchwork of extensions. It lacks synchronisation primitives suited to a modern mobile fleet, consumes a lot of bandwidth, and needs many round trips, which means latency. The project also notes that large players responded with proprietary protocols of their own and that no interoperable standard was found.

JMAP is presented as the answer, built on decades of experience and using HTTP and JSON as its standards. The claimed benefits are easier application development and, in the project's view, a better experience for the end user.

The practical scope is a client for reading mail, managing mailboxes, sending email and searching. The FAQ states that the client can be used with any JMAP server. What it gains beyond that, such as labels, delegation and richer filters, comes from the Twake Mail back end rather than from JMAP itself, and that distinction is the most important thing to understand about the project.

Building it takes a prebuild step before Flutter runs

The build is a two step process, and the first step is not optional.

From the root of the project, the documented instruction is to run the prebuild script:

bash
/bin/bash scripts/prebuild.sh

The documentation explains what that script does: it downloads pinned pica and dotlottie into web/js/vendor, and it skips the download when those files are already present. So the step exists to vendor browser side dependencies at a pinned version rather than pulling whatever is current at build time.

After that, the standard Flutter build commands apply. For iOS:

bash
flutter build ios 

For Android:

bash
flutter build apk

And for the web target there is one extra configuration step, because the web build has to be told which server to talk to. The server address goes in SERVER_URL in env.file:

bash
SERVER_URL=http://your-jmap-server.domain

and then the build runs:

bash
flutter build web

That ordering matters if you are scripting a build. The web output is not a static demo that runs against a local mock; the server address is compiled in, so a different deployment target means a different build rather than a different configuration at run time.

If you would rather not build at all, prebuilt images are published on Docker Hub at linagora/tmail-web.

The web build is a static bundle served by nginx

The Dockerfile in the repository shows exactly how the web target is packaged, and it is a useful reference for anyone building a static deployment.

The build stage pins a Flutter version, 3.38.9, and the comment above the FROM line explains the choice: the digest wins over the tag, so FLUTTER_VERSION and the digest are updated together. The base image is the Instrumentisto Flutter image for the amd64 platform, taken by digest rather than by floating tag.

dockerfile
FROM --platform=amd64 ghcr.io/instrumentisto/flutter:${FLUTTER_VERSION}@sha256:7d227ac458bbb5aca38ada779dc0bf983ad24deae8d2ef3ebf5b779915d1547d AS build-env

ARG SENTRY_AUTH_TOKEN
ARG SENTRY_ORG
ARG SENTRY_PROJECT
ARG SENTRY_URL
ARG SENTRY_RELEASE
ARG VCS_REF
ARG GITHUB_SHA

The build itself runs the prebuild script, configures Sentry, and compiles the web target with release mode, source maps and the no web resources cdn flag, passing the release and the commit as dart defines.

The runtime stage is nginx on alpine, pinned by digest, with gzip installed. The built web assets are copied into the nginx html directory, the project's own nginx.conf is installed, port 80 is exposed, and the container command compresses the assets and starts nginx in the foreground.

Two things stand out. The use of source maps with release builds means source map handling is part of your deployment story rather than an afterthought. And the Sentry integration is wired through build arguments and dart defines, so error reporting is a build time configuration rather than a runtime toggle.

Any JMAP server for the protocol, Twake Mail for the features

The FAQ is unambiguous on compatibility. Yes, you can use the Twake Mail application with any JMAP server. That is the promise of the protocol layer: the client speaks JMAP, and any server that speaks JMAP can serve it.

The features beyond that are where the back end matters. The roadmap lists work on better filters with more actions and combined conditions, restoring deleted messages, delegating full access to others for example a security team, labels for sorting mail across folders, automated actions such as archiving and emptying trash and spam folders, running filters against a folder, and attachment thumbnails.

There is also work planned around the encrypted mailbox with GPG, sending and transferring attachments through the TDrive file sharing platform, and discussing received emails in Twake chat.

These are server side capabilities. If you point the client at a plain JMAP server, the protocol level features work and the rest do not.

Two features are ruled out on purpose. The project does not plan to support JMAP extensions for calendar and contacts, because those extensions are not standardised as RFCs and are not implemented on the Twake Mail back end. That is a decision about the protocol's maturity, and it is worth knowing before you evaluate a JMAP client as a groupware front end.

The FAQ also says a desktop application is not currently planned, and that work on websockets for push on top of the web mail is not planned either, though contributions towards either would be welcomed.

Portability to other mail servers is welcomed but not delivered

The project describes itself as aiming to provide a multi platform mobile email application running the JMAP protocol, and it also delivers additional features to the Twake Mail back end. That second half is the caveat in the positioning statement, and the FAQ states it directly.

The maintainers say they welcome feedback and pull requests regarding Team Mail portability, which is running Team Mail on top of third party mail servers. So the intent to support other back ends is stated, and the route to get there is contributions rather than a shipped configuration.

What that means for an evaluator is that the client is easiest to run against the back end the same organisation develops. Pointing it at another JMAP server gives you the protocol features and the client experience, but the server dependent extras, from labels to delegation to GPG mailboxes, are tied to the Twake Mail back end.

The repository layout mirrors that split in a visible way. Alongside the Flutter application directories there are contact, labels, rule_filter, forward, workplace, email_recovery and server_settings modules, plus a cozy directory and a tmail-mcp directory, and a backend-docker directory. The presence of a Docker directory for the back end in the same repository is a reminder that this project covers a deployment stack, not only an app. The overview does not describe what each of those modules does, so treat the directory names as a map of the surface area rather than as a specification.

For a team weighing this against an IMAP client, that is the comparison that matters: protocol reach versus feature depth.

AGPL terms, monthly tags and a Docker published image

The licence is AGPL-3.0, and for a networked application that is the term to think about carefully rather than later.

An AGPL covered application that you modify and then offer to users over a network triggers the source sharing obligation. This is different from the ordinary case of running an unmodified AGPL application internally, and different again from permissively licensed mail clients. This review cannot give legal advice, and the point is not that the licence is hostile. It is that a self hosted mail client that organisations intend to modify is exactly the case the AGPL was written to address, and the person responsible for your licensing needs to read the terms in that context rather than assume they behave like MIT.

The release history is regular. The tags are v0.37.1 from 2026-09-22, v0.35.1 from 2026-09-08 and v0.34.0 from 2026-08-17, so the project ships roughly monthly and the version numbers are still below 1.0. The repository is not archived and the last push was on 2026-10-20.

The deployment artefacts are consistent with that cadence. The web client is published as linagora/tmail-web on Docker Hub, the Dockerfile builds from a pinned Flutter image and a pinned nginx image, and the mobile builds are distributed through the Play Store and the App Store listings linked in the overview.

The repository also carries the files a serious deployment needs: a privacy.md, a security.md, a CHANGELOG.md, AGENTS.md, a Jenkinsfile alongside a JenkinsfileMobile for continuous integration, and an analysis_options.yaml for Dart linting.

Editorial conclusion

Use tmail-flutter if you run a JMAP server, you want a mail client your organisation controls from source, and you are willing to build the Flutter targets yourself. Do not expect it to be a drop in replacement for an IMAP client, since the project drops support for calendar and contacts extensions outright and pushes desktop only through contributed work. Before committing, point env.file SERVER_URL at your own JMAP server, run /bin/bash scripts/prebuild.sh, build the web target with flutter build web, and check the AGPL-3.0 terms with whoever owns licensing in your organisation, since a modified client served over the network carries obligations the unmodified build does not.

Frequently asked questions

What is tmail-flutter?

It is the Flutter source of Twake Mail, a multi platform email application that reads mail using the JMAP protocol. It targets Android, iOS and web, and it is developed by Linagora.

How do I build tmail-flutter?

Run /bin/bash scripts/prebuild.sh from the project root first, which downloads the pinned pica and dotlottie assets into web/js/vendor, then use the normal Flutter commands such as flutter build apk, flutter build ios or flutter build web.

How do I point the web build at my own JMAP server?

Set SERVER_URL in env.file to the address of your JMAP server, for example SERVER_URL=http://your-jmap-server.domain, and then run flutter build web. The address is compiled into the build.

Can Twake Mail work with any JMAP server?

Yes, the FAQ states you can use the application with any JMAP server. Features such as labels, delegation and richer filters come from the Twake Mail back end rather than from the protocol.

Does Twake Mail support calendar or contacts?

No. The project states it does not plan to support those JMAP extensions because they are not standardised as RFCs and are not implemented on the Twake Mail back end.

Is there a prebuilt image of the web client?

Yes, prebuilt images are published on Docker Hub at linagora/tmail-web, and the repository's own Dockerfile shows how the web target is compiled with Flutter and served by nginx on alpine.

Official sources

  1. Issues
  2. License: AGPL-3.0
  3. linagora/tmail-flutter on GitHub
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/linagora-tmail-flutter.svg)](https://hysenlabs.com/projects/linagora-tmail-flutter)

Was this useful?