Skip to content
erictran308Public

About

Email in your terminal: a TUI email client for IMAP, POP3 and SMTP with vim or arrow keys, several accounts, Gmail and Outlook ready, HTML read as text with no tracking pixels, and passwords in your keychain. Built in Rust with ratatui.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

7 Commits

Folders and files

Repository files navigation

tuimail

Your mail, at the speed of your keyboard.

A terminal email client (TUI): IMAP and POP3 to read, SMTP to send, several accounts side by side.
Arrow keys or vim keys. Passwords in your system's keychain. Nothing loaded from the internet when you read.

Release crates.io License: MIT Rust

Get started · Keys · Accounts · Settings · Privacy

tuimail: a sidebar with All inboxes and two accounts' folders, beside the work inbox's messages with stars, replies and attachments marked, and Alice's message 'Lunch tomorrow?' open in the reader: its sender, the attached menu, an underlined link and quotes colored by depth

The demo's made-up mail: tuimail --demo


Why tuimail

  • IMAP, POP3 and SMTP. IMAP accounts keep mail on the server, in its folders; POP3 accounts download the inbox and keep Sent, Drafts, Archive and Trash on your computer. Both send through SMTP, with TLS or STARTTLS.
  • New mail at once. Where the server can (IMAP IDLE), new mail shows the moment it arrives, with a notification through your terminal. Elsewhere tuimail checks every few minutes, and R checks now.
  • Several accounts. Each in the sidebar with its folders, and All inboxes together at the top. Write from any of them (← → on From).
  • Arrows or vim, your choice. ←↓↑→ and h j k l both move, Enter opens, gg / G, Ctrl-d / Ctrl-u. ? lists every key, and O opens the settings.
  • Reading made calm. HTML mail is shown as text (bold, italics, links numbered), with nothing it points to fetched: no tracking pixels, no "read" receipts by image. Quotes are colored by depth. H shows the plain-text part instead, o lists the links, A the attachments.
  • Writing in place, or in your editor. To, Cc, Bcc and Subject with addresses completed from people you've written to or heard from; the text in place, or Ctrl-e for $EDITOR. Drop a file on the window to attach it. Replies quote, forwards carry the attachments, drafts go to Drafts and open again where you left them.
  • Quick to tidy. d deletes (to Trash), e archives, ! marks junk, m moves anywhere, s stars, u marks read or unread. Space marks several messages for any of these at once. U unsubscribes from a mailing list.
  • Search. / finds mail by sender, recipients, subject or text: at once in what's on your computer, then on the server, which searches whole messages.
  • Works offline. Headers and the messages you've opened are kept in a local cache, so the list and what you've read are there without a connection.
  • Set up in a minute. Type your address and password: the servers fill in for Gmail, iCloud, Outlook, Yahoo, Fastmail, Proton (through its Bridge), Zoho, GMX, WEB.DE, Yandex, Mail.ru, Posteo, mailbox.org and more, or are guessed for others. tuimail logs in to check before saving.
  • Make it yours. Catppuccin, Tokyo Night, Dracula, Gruvbox, Nord and Rosé Pine themes (picked in the settings, O), and Nerd Font icons where your terminal has them.
  • Private by design. No account with anyone but your mail provider, no telemetry, no servers in between. Your mail, accounts and settings stay in one folder on your computer, readable only by you.

Get started

1. Install tuimail. If you have Rust and cargo-binstall, that's one command, on any system:

cargo binstall tuimail

Otherwise, on macOS or Linux, paste this into a terminal. It puts tuimail in ~/.local/bin:

mkdir -p ~/.local/bin
curl -fsSL https://github.com/erictran308/tuimail/releases/latest/download/tuimail-aarch64-apple-darwin.tar.gz | tar xz -C ~/.local/bin tuimail

Swap the file name for your computer's:

Computer File
Mac with Apple silicon (M1 or later) tuimail-aarch64-apple-darwin.tar.gz
Mac with Intel tuimail-x86_64-apple-darwin.tar.gz
Linux, x86_64 tuimail-x86_64-unknown-linux-gnu.tar.gz
Linux, ARM64 tuimail-aarch64-unknown-linux-gnu.tar.gz
Windows, x86_64 tuimail-x86_64-pc-windows-msvc.zip
Windows, ARM64 tuimail-aarch64-pc-windows-msvc.zip
  • Windows: download the .zip, unzip it, and run tuimail.exe from Windows Terminal.
  • Linux: needs glibc 2.35 or newer: Ubuntu 22.04, Debian 12, Fedora 36, RHEL 9 or later.
  • macOS: if you downloaded the file in a browser instead, macOS blocks the app. Run xattr -d com.apple.quarantine tuimail once to allow it.

If tuimail isn't found afterwards, add ~/.local/bin to your PATH. Each file comes with a signed record of the commit it was built from; to check one, run gh attestation verify <file> --repo erictran308/tuimail --signer-workflow erictran308/tuimail/.github/workflows/release.yml.

Or build it from source (Rust 1.90 or newer, and a C compiler for SQLite):

cargo install tuimail --locked

2. Run it.

tuimail

The first start asks for an account: your address and password (for Gmail, iCloud, Yahoo and others, an app password: see App passwords). The servers fill in; Ctrl-s logs in to check them and saves the account, with the password in your system's keychain.

To look around first, tuimail --demo shows made-up accounts and mail, connecting nowhere and sending nothing.

Check your setup

tuimail --check

It says where your data folder is, whether a keychain is there for passwords, and each account it found: its servers, security and where its password comes from. An account it can't use, or a line in accounts.toml it doesn't understand, shows up as a warning.

Keys

The status bar shows the keys for where you are, and ? lists them all. Tab there goes to the settings.

Key Action
←↓↑→ / h j k l Move; Enter, → or l opens
Tab Folders → messages → the message
gg / G, Ctrl-u / Ctrl-d First / last, half a page
c Write a message
r / a / f Reply / reply to all / forward
d Delete: to Trash; from Trash, for good (asking first)
e / ! / m Archive / junk / move to a folder
s / u Star / read or unread
Space / * Mark a message / all of them; the keys above act on the marked
/ Search; Esc ends it
J / K Reading: the next / previous message
Space / b Reading: a page down / up
o / A Reading: the links (Enter open, y copy) / attachments (Enter open, s save)
H Reading: HTML or plain text
U Unsubscribe from a mailing list
R Check for mail now
+ / x / P Add an account / remove it (on its row) / type its password
? / O Every key / the settings and themes
q Quit

Writing:

Key Action
Tab / Shift-Tab, Enter The next / previous field; Tab takes a suggested address
Ctrl-s Send (asking first, unless turned off)
Ctrl-d Save in Drafts and close
Ctrl-o Attach a file (or drop it on the window)
Ctrl-e Write the text in your editor ($VISUAL, $EDITOR, or editor in the settings)
← → on From Send from another account
x on Files Take a file off
Esc Close: y keeps it in Drafts, n throws it away

Accounts

Accounts are kept in accounts.toml in your data folder. The setup screen (+) writes it; you can also edit it while tuimail isn't running:

[[account]]
name = "work"                      # what the sidebar calls it
email = "me@example.org"
display_name = "Sam Taylor"        # your name, as recipients see it
protocol = "imap"                  # or "pop3"
host = "imap.example.org"
port = 993                         # if not the usual one
security = "tls"                   # "tls", "starttls", or "none" (this computer only, unencrypted)
smtp_host = "smtp.example.org"
smtp_port = 465
smtp_security = "tls"
password = "keychain"              # "keychain", "ask" (each start) or "command"
signature = "Sam"

More keys: username and smtp_username (if not the address), password_command (below), save_sent (copy sent mail to Sent; off by default for Gmail and Outlook, which do it themselves), certificate (a server certificate to trust, for Proton Mail Bridge or your own server), leave_on_server (POP3, on by default), and sent_folder, drafts_folder, trash_folder, archive_folder, junk_folder when the server doesn't say which folder is which.

x on an account's row in the sidebar removes it, its cached mail, and its password from the keychain.

App passwords

Gmail, iCloud, Yahoo, AOL, Fastmail and others don't take your normal password from mail programs: make an app password in your account's security settings and use that. For Gmail: myaccount.google.com/apppasswords (it needs 2-Step Verification on).

Passwords from a command

To keep the password in a password manager instead of the keychain:

password = "command"
password_command = ["/opt/homebrew/bin/pass", "show", "mail/work"]

The program is given by its full path and run without a shell; tuimail uses the first line it prints. It runs once at start with your terminal, so it can ask you to unlock something.

OAuth2 (Outlook.com, Microsoft 365, Gmail without app passwords)

Outlook.com takes only OAuth2. tuimail logs in with XOAUTH2 using an access token printed by a command, run again for each connection so a short-lived token stays fresh. oama and the mutt_oauth2.py script both do this:

auth = "oauth2"
password_command = ["/opt/homebrew/bin/oama", "access", "me@outlook.com"]
host = "outlook.office365.com"
smtp_host = "smtp-mail.outlook.com"
smtp_port = 587
smtp_security = "starttls"

Proton Mail

Run Proton Mail Bridge, use the password it shows for the account, and export its certificate (Bridge → Settings → Export TLS certificates), then point tuimail at it:

host = "127.0.0.1"
port = 1143
security = "starttls"
smtp_host = "127.0.0.1"
smtp_port = 1025
smtp_security = "starttls"
certificate = "/Users/you/Documents/bridge/cert.pem"

Settings

O (or ? then Tab) opens the settings: the message beside the list, plain text or HTML, marking read, asking before deleting and before sending, notifications, and the theme. j / k move, Enter or Space turns one on or off (or picks the theme), and it's saved at once, changing only its own line in settings.toml and keeping the rest of the file (but not its comments).

Everything else is in settings.toml in your data folder. Every line is optional; changes made by hand take effect the next time tuimail starts:

theme = "mocha"          # latte, frappe, macchiato, mocha, tokyonight, dracula, gruvbox, nord, rose-pine
icons = "auto"           # auto (Nerd Font icons in Ghostty, kitty and WezTerm), nerd or plain
notifications = "auto"   # auto (what your terminal understands), off, bell, osc9, osc777 or osc99
preview = true           # the open message beside the list, when the window is wide enough
prefer_plain = false     # a message's plain-text part rather than its HTML, when it has both
mark_read = true         # mark a message read once it's shown
confirm_delete = false   # ask before moving mail to Trash
confirm_send = true      # ask before sending (a message without a subject always asks)
check_minutes = 5        # how often to check where the server can't say at once, and folders other than the inbox (1 to 1440)
fetch_count = 300        # how many of a folder's newest messages to fetch at first (20 to 5000); older ones as you scroll
sidebar_width = 28       # in columns (16 to 50)

# Where `s` saves attachments, if not your Downloads folder:
# downloads = "/Users/you/Mail attachments"
# The editor for Ctrl-e, as a full path with its arguments, if not $VISUAL or $EDITOR:
# editor = ["/usr/bin/vim"]

Privacy and security

  • Nothing fetched to read. HTML is turned into text on your computer; pictures are shown by their description, never downloaded, so senders can't tell when you read their mail.
  • Passwords stay out of files. They're in your system's keychain (macOS Keychain, Windows Credential Manager, the Secret Service on Linux), asked for at each start, or printed by your own command. Never in accounts.toml, never on a command line.
  • TLS, checked. Connections use TLS (or STARTTLS, which must succeed before anything is sent) and your system's trusted certificates. An unencrypted connection is allowed only to a server on your own computer, at its loopback address; on Linux, only if that server runs as you or the system. On a computer shared with other accounts, prefer STARTTLS with certificate (as for Proton Mail Bridge): there, any account could answer on a free port.
  • Nothing about your computer in what you send. Messages go out with a random Message-ID and a UTC date, and tuimail greets SMTP servers as [127.0.0.1], so your computer's name never ends up in mail headers.
  • Text from senders can't take over your terminal. Control characters, escape sequences and direction-changing characters are taken out of everything shown, copied or notified.
  • Attachments are handled with care. File names are cleaned (no folders, no hidden extensions), files never overwrite one another, they're marked as downloaded from the internet, and only pictures, sound, video, PDF and plain text open without asking (Office files, archives, CSV and the rest ask first). Web links open only through your browser, and only http and https; the link list shows where each one really goes, with look-alike letters spelled out (xn--). mailto links and U's addresses open here, as a message to write; U's web page is shown before it opens.
  • Pastes stay text. A paste that arrives as keystrokes (as it always does on Windows) is never taken for commands, and a question that waits for y ignores one typed too soon.
  • Local data is yours alone. The data folder is made readable only by you; the cache (tuimail.db) overwrites what's deleted.

To report a problem, see SECURITY.md.

Your data

Everything is in one folder on your machine (tuimail --help prints its path):

OS Location
macOS ~/Library/Application Support/tuimail
Linux ~/.local/share/tuimail
Windows %LOCALAPPDATA%\tuimail

It holds accounts.toml, settings.toml, and tuimail.db: the cache of your folders, headers and the messages you've opened, POP3 accounts' mail, and the addresses used for completing To, Cc and Bcc. Attachments you open go to its opened/ folder. Passwords aren't in it: they're in your system's keychain. Deleting the folder starts tuimail afresh; remove the accounts with x first to take their passwords out of the keychain too.

Variable Use
TM_DATA_DIR Keep the data folder somewhere else (a full path)
TM_ICONS Which icons: auto, nerd or plain

Development

cargo test                       # offline tests
cargo clippy --all-targets
TM_DATA_DIR=$HOME/tm-test cargo run   # a separate data folder (a full path) for trying things
cargo run -- --demo              # made-up accounts and mail, nothing connects or is sent

The tests against a real server run against GreenMail in Docker (IMAP, POP3 and SMTP over TLS); the commands are at the top of src/live.rs.

Only development builds read a .env, and only from the source folder, never the folder they're started from, and only its TM_* lines: an installed tuimail ignores it, so a .env in a folder you cloned can't change where your mail is kept.

Built with

License

MIT

About

Email in your terminal: a TUI email client for IMAP, POP3 and SMTP with vim or arrow keys, several accounts, Gmail and Outlook ready, HTML read as text with no tracking pixels, and passwords in your keychain. Built in Rust with ratatui.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages