Help us shape the future of Go! Take the 2026 Go Developer Survey

mail_cli

command module
v0.7.49 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 16 Imported by: 0

README

mail_cli

CI Go Version

A high-performance terminal and CLI email client engineered for power users. Native OAuth for Google Gmail and Microsoft 365 / Outlook, native JMAP for Fastmail, an interactive Bubbletea TUI, and Mutt-style UNIX scripting pipes — without offlineimap, mbsync, or sync-and-script hell.


Why mail_cli?

For decades, mutt and neomutt have been the gold standard for terminal email. But in 2026, running them requires an intricate, brittle stack:

  • Maintaining external sync daemons (mbsync, offlineimap) and handling UIDVALIDITY errors.
  • Managing external SMTP dispatchers (msmtp).
  • Managing external search indexers (notmuch).
  • Managing custom OAuth2 token renewal scripts that break whenever Google or Microsoft change auth flows.
  • Writing hundreds of lines of obscure .muttrc config just to view basic threads or HTML attachments.

mail_cli replaces that entire stack with a single, standalone binary.

Comparison Matrix
Feature mail_cli NeoMutt aerc Himalaya Alpine
Primary Interface TUI + Rich CLI TUI TUI CLI (basic TUI) TUI
Native Gmail OAuth Yes (Direct) No (Scripted) Partial Partial No
Native Outlook Graph Yes (Device Code) No (Scripted) No No No
Native Fastmail JMAP Yes (Direct) No No No No
External Sync Needed None mbsync/offlineimap Optional Optional None
Setup Time < 3 minutes 1–3 hours 15–30 mins 15 mins 20 mins
Local Search Fast built-in Needs notmuch Server / grep Server Built-in
Recipient Auto-Complete Yes (History+Rank) Aliases only Basic Basic Addressbook
Spam / Political Unsub Built-in External scripts No No No
Local LLM Summaries Yes (Ollama/OpenAI) No External script No No
Bidi / RTL Support Built-in Patch required Limited Terminal-dep No

Features

  • Direct API Integration: Native REST API client for Gmail with OAuth2, Microsoft Graph API for Outlook / Office 365 with Device Code auth, and JMAP API for Fastmail.
  • Modern Interactive TUI: Dual-pane split view, expandable folder/label tree, thread collapsing, inline attachment inspection, and full Hebrew/Bidi RTL text rendering.
  • Mutt-Style CLI Scripting:
    • Outbound transmission: mail_cli msg send -s "Subject" user@example.com < message.txt
    • Direct replies: mail_cli msg reply -g <message-id> (interactive in $EDITOR or headless via --headless)
    • Pre-formatted RFC822 pipeline: mail_cli msg send --raw < patch.eml (drop-in compatibility with git send-email)
  • Ranked Recipient Auto-Complete:
    • Frequency and recency ranking prioritizing contacts you actively communicate with.
    • In-TUI <Tab> completion and contact aliases.
    • Mutt alias file import (mail_cli contacts import-mutt ~/.muttrc) and Google Contacts sync.
  • Intelligent Mail Hygiene:
    • Local Bogofilter bayesian spam training (mail_cli spam sweep).
    • Automated political fundraising email audit and one-click unsubscription.
  • Optional AI Capabilities:
    • One-key message summarization and key deadline extraction via local LLMs (Ollama) or cloud APIs.

Installation

Releases are source-only — no prebuilt binaries are published — so install with go install or build from the tagged source. Either needs Go 1.26 or newer.

Go Install
go install github.com/sarielhp/mail_cli@latest

This puts mail_cli in $(go env GOPATH)/bin.

Build from Source
git clone https://github.com/sarielhp/mail_cli.git
cd mail_cli
make

Quick Start

1. Interactive Onboarding (mail_cli account setup)

Run the interactive setup wizard to configure your first email account in under 3 minutes:

mail_cli account setup

The wizard guides you through selecting your provider:

  1. Fastmail / JMAP: Fast setup using an API token (docs/setup/fastmail.md).
  2. Google Gmail: Connect through your own Google Cloud OAuth client, a free one-time setup of about 3 minutes; mail_cli ships no shared Gmail credentials (docs/setup/gmail.md).
  3. Microsoft 365 / Outlook: Connect via Azure Device Code login (docs/setup/outlook.md).
2. Launch the Interactive TUI
mail_cli tui
  • Press ? in any view to view the keybinding cheat sheet.
  • Navigate with j/k, switch folders with Tab, and toggle split preview with p.
  • Reply with r (or g for group reply), compose with c, archive with a.
  • Long URLs stay in the message text with an abbreviated display ending in .... On terminals supporting hyperlinks, clicking opens the complete URL. Other terminals display the complete URL.

Command Line Cheat Sheet

The CLI has 14 top level commands. Browsing and composing stay direct; other actions are grouped by the thing you want to manage. Use <command> -h for a short list, <command> -H for details, and -E <command> for examples.

Commands Purpose
scan, search, write, tui Find, classify, browse mail, and write new messages
msg Show, send, reply, drafts, recent mail, export, archive, block
label, mbox Manage server folders and local mail archives
spam, rule Train spam filters and manage routing rules
calendar, contacts Manage events and recipient information
account Guided setup, accounts, login, migration
config Preferences, validation, LLM checks
utils Cache, terminal colors, diagnostics, completion, manual pages

Earlier root spellings such as send, show, drafts, last, setup, cache, and completion still work as hidden compatibility commands. Their flags and behavior are preserved; help and completion teach the grouped paths. The previous compose, msg compose, and tools spellings also remain available as hidden shortcuts for write and utils. tui write is equivalent to write, including recipients, flags, and draft resumption, for wrappers that already invoke mail_cli tui.

# Browse & Read
mail_cli %                          # Scan the inbox (% alone denotes INBOX)
mail_cli %work:receipts             # Scan a specific folder on a specific account
mail_cli msg show <message-id>          # Display email body and attachments
mail_cli search "invoice 2026"      # Fast indexed search across downloaded messages
mail_cli msg last 20                # Recent mail across all folders

# Compose & Send
mail_cli write                    # Compose interactively with $EDITOR and TUI review
mail_cli msg send -s "Update" boss@co.com < notes.txt    # Send from stdin
mail_cli msg send -s "Report" -a report.pdf user@co.com  # Send with attachment
mail_cli msg send --raw < patch.eml                      # Send pre-formatted RFC822 (git send-email)

# Reply
mail_cli msg reply 18fb1234abcd         # Open interactive reply in $EDITOR with quoted text
mail_cli msg reply -g 18fb1234abcd      # Group reply (reply-all) to all recipients
mail_cli msg reply --headless --body "Ack" 18fb1234abcd  # Headless instant reply

# Contacts & Hygiene
mail_cli contacts suggest "ali"     # Search auto-complete recipient candidates
mail_cli contacts import-mutt ~/.muttrc  # Import existing Mutt aliases
mail_cli spam sweep                 # Move spam out of inbox and train filter

# Setup & Maintenance
mail_cli account setup              # Guided account setup
mail_cli config llm test            # Check the configured LLM endpoint
mail_cli utils cache prune 30       # Prune old local cached messages
mail_cli utils completion install   # Install shell completion

Documentation


License

This project is licensed under the MIT License.

Documentation

Overview

Command mail_cli is a command-line mail client.

This file is the composition root: it parses just enough of the command line to choose a config, builds the backend factory and the services in wiring.go, binds them to the interfaces the cli and tui packages declare, and gets out of the way. Nothing here does mail work, and nothing below imports it.

Directories

Path Synopsis
Package app holds the small utilities every layer may use: colour styles and the [+]/[!] prefixes, the loggers, temporary directories, the version string, and ErrUsage.
Package app holds the small utilities every layer may use: colour styles and the [+]/[!] prefixes, the loggers, temporary directories, the version string, and ErrUsage.
backend
backendtest
Package backendtest holds the test helpers the concrete mail backends share.
Package backendtest holds the test helpers the concrete mail backends share.
gmail
Package gmail implements the mail client interfaces against the Gmail REST API, including its OAuth flow.
Package gmail implements the mail client interfaces against the Gmail REST API, including its OAuth flow.
jmap
Package jmap implements the mail client interfaces against a JMAP server.
Package jmap implements the mail client interfaces against a JMAP server.
mbox
Package mbox implements the mail client interfaces against a local mbox file, which makes it the backend that needs no account and no network.
Package mbox implements the mail client interfaces against a local mbox file, which makes it the backend that needs no account and no network.
outlook
Package outlook implements the mail client interfaces against the Microsoft Graph API.
Package outlook implements the mail client interfaces against the Microsoft Graph API.
paging
Package paging converges a batched walk over a result set that the batch function itself is shrinking.
Package paging converges a batched walk over a result set that the batch function itself is shrinking.
political
Package political classifies cached messages as political donation mail.
Package political classifies cached messages as political donation mail.
spamlearn
Package spamlearn records which messages a backend has trained the spam filter on.
Package spamlearn records which messages a backend has trained the spam filter on.
Package bogofiltertest installs a stand-in bogofilter executable for tests.
Package bogofiltertest installs a stand-in bogofilter executable for tests.
Package browser launches a web browser on a URL or local file.
Package browser launches a web browser on a URL or local file.
Package cache is the on-disk store for everything the server told us: which messages a folder holds, which have been read or replied to, and the cached label listing.
Package cache is the on-disk store for everything the server told us: which messages a folder holds, which have been read or replied to, and the cached label listing.
cachedir
Package cachedir names an account's cache directory.
Package cachedir names an account's cache directory.
dirlock
Package dirlock serializes read-modify-write access to a cache directory.
Package dirlock serializes read-modify-write access to a cache directory.
folderindex
Package folderindex maintains the local record of which message IDs are in which folder, so a listing can be drawn without asking the server.
Package folderindex maintains the local record of which message IDs are in which folder, so a listing can be drawn without asking the server.
msg
Package msg stores raw message bodies on disk and the classification derived from them.
Package msg stores raw message bodies on disk and the classification derived from them.
msgstore
Package msgstore serves raw messages by ID, reading whatever the local cache already holds and downloading only what is missing.
Package msgstore serves raw messages by ID, reading whatever the local cache already holds and downloading only what is missing.
virtual
Package virtual stores named result sets: a list of message IDs plus the folder each came from, saved under the cache directory.
Package virtual stores named result sets: a list of message IDs plus the folder each came from, saved under the cache directory.
Package calendar reads the .ics attachments that arrive as meeting invitations, turning them into an ICSEvent the rest of the program can show or file.
Package calendar reads the .ics attachments that arrive as meeting invitations, turning them into an ICSEvent the rest of the program can show or file.
google
Package google integrates with the Google Calendar API: adding events parsed from .ics mail attachments, checking whether they are already present, and printing a week's schedule.
Package google integrates with the Google Calendar API: adding events parsed from .ics mail attachments, checking whether they are already present, and printing a week's schedule.
Package cfg_acc holds the per-account configuration types: the account itself, its routing rules, and its whitelist and blacklist.
Package cfg_acc holds the per-account configuration types: the account itself, its routing rules, and its whitelist and blacklist.
Package cfg_g is the global configuration: loading and saving the file, resolving which account a command acts on, and parsing the %label references the command line takes.
Package cfg_g is the global configuration: loading and saving the file, resolving which account a command acts on, and parsing the %label references the command line takes.
Package cfghandler implements the config subcommands: show, set, unset and check.
Package cfghandler implements the config subcommands: show, set, unset and check.
Package cli is the command-line front end: the command tree, the flags, and the translation from what the user typed into a call on an operation.
Package cli is the command-line front end: the command tree, the flags, and the translation from what the user typed into a call on an operation.
Package contacts holds the local address book: the contacts file and its history, importers for mutt aliases and Google Contacts, recipient harvesting from mail, and the ranked suggestions offered while composing.
Package contacts holds the local address book: the contacts file and its history, importers for mutt aliases and Google Contacts, recipient harvesting from mail, and the ranked suggestions offered while composing.
Package draft is the local copy of every message being composed: one draft.eml per compose session under <root>/YYYY/MM/DD/N. It knows nothing about servers.
Package draft is the local copy of every message being composed: one draft.eml per compose session under <root>/YYYY/MM/DD/N. It knows nothing about servers.
Package email parses messages: headers and their encoded words, MIME parts and attachments, HTML reduced to the words it displays, and the threading of a folder into conversations.
Package email parses messages: headers and their encoded words, MIME parts and attachments, HTML reduced to the words it displays, and the threading of a folder into conversations.
Package filebrowser is the interactive directory picker used when saving an attachment, built on bubbletea like the rest of the interface.
Package filebrowser is the interactive directory picker used when saving an attachment, built on bubbletea like the rest of the interface.
zonetest
Package zonetest waits for bubblezone to record a zone a view has drawn.
Package zonetest waits for bubblezone to record a zone a view has drawn.
Package integration holds the tests that talk to a real account.
Package integration holds the tests that talk to a real account.
Package interactive holds the tests that drive mail_cli in a real terminal.
Package interactive holds the tests that drive mail_cli in a real terminal.
Package label is about folder names: matching one the user typed against the ones the server has, ordering a listing, and nesting it into a tree.
Package label is about folder names: matching one the user typed against the ones the server has, ordering a listing, and nesting it into a tree.
Package last implements the listing of the most recent messages across every folder of an account.
Package last implements the listing of the most recent messages across every folder of an account.
Package llm summarises a message through an OpenAI-compatible chat endpoint.
Package llm summarises a message through an OpenAI-compatible chat endpoint.
Package localdir resolves the on-disk directory a subsystem keeps its own files in: <downloadDir>/<name> when a download directory is configured, and ~/.cache/mail_cli/<name> otherwise, so a subsystem still has somewhere to write when no account -- and therefore no download directory -- is selected.
Package localdir resolves the on-disk directory a subsystem keeps its own files in: <downloadDir>/<name> when a download directory is configured, and ~/.cache/mail_cli/<name> otherwise, so a subsystem still has somewhere to write when no account -- and therefore no download directory -- is selected.
Package mailclient defines what a mail backend must be able to do, and the decorators that wrap one.
Package mailclient defines what a mail backend must be able to do, and the decorators that wrap one.
Package mailops builds backend clients: it resolves an account to its per-account config, instantiates the right backend for its type, and wraps it in the read-only and caching decorators.
Package mailops builds backend clients: it resolves an account to its per-account config, instantiates the right backend for its type, and wraps it in the read-only and caching decorators.
Package message_info stores the cache's per-message index: where a message sits on disk, and what classification it has been given.
Package message_info stores the cache's per-message index: where a message sits on disk, and what classification it has been given.
Package organize archives mail: moving everything under a label prefix into the account's archive folder.
Package organize archives mail: moving everything under a label prefix into the account's archive folder.
Package outbox provides an offline send queue: RFC822 messages spooled to disk when offline or when asynchronous queuing is requested.
Package outbox provides an offline send queue: RFC822 messages spooled to disk when offline or when asynchronous queuing is requested.
Package pgp is the mail program's OpenPGP layer: it shells out to the system gpg and knows how a PGP/MIME message is shaped.
Package pgp is the mail program's OpenPGP layer: it shells out to the system gpg and knows how a PGP/MIME message is shaped.
Package report is how the layers below the user interface say what they are doing, without deciding where it goes or what it looks like.
Package report is how the layers below the user interface say what they are doing, without deciding where it goes or what it looks like.
Package runner orchestrates whole commands: the account-spanning scan, show and last, rule import and export, and the service types that implement the interfaces cli and tui declare.
Package runner orchestrates whole commands: the account-spanning scan, show and last, rule import and export, and the service types that implement the interfaces cli and tui declare.
Package scan is the spam pass over a folder: download what is there, apply the account's routing rules, classify the remainder with bogofilter, and move what the rules and the classifier agree on.
Package scan is the spam pass over a folder: download what is there, apply the account's routing rules, classify the remainder with bogofilter, and move what the rules and the classifier agree on.
Package show renders one message for reading: headers, the decoded body, attachments, and any calendar invitation it carries.
Package show renders one message for reading: headers, the decoded body, attachments, and any calendar invitation it carries.
Package sieve exports an account's routing rules as a Sieve script, for a server that can filter mail without this program running.
Package sieve exports an account's routing rules as a Sieve script, for a server that can filter mail without this program running.
Package spam is the manual side of spam handling: marking a message, taking the mark back, and training bogofilter from either.
Package spam is the manual side of spam handling: marking a message, taking the mark back, and training bogofilter from either.
Package terminal holds the low-level terminal queries that several packages need and none of them owns.
Package terminal holds the low-level terminal queries that several packages need and none of them owns.
Package train records which messages the spam filter has already been trained on.
Package train records which messages the spam filter has already been trained on.
tui
Package tui is the interactive front end, built on bubbletea.
Package tui is the interactive front end, built on bubbletea.
render
Package render turns the TUI's model state into styled terminal output: themes, coloured segments, and the individual lines of the folder tree and message list.
Package render turns the TUI's model state into styled terminal output: themes, coloured segments, and the individual lines of the folder tree and message list.
Package ui formats the listings the command line prints: folder trees, label listings, message summaries, filter listings.
Package ui formats the listings the command line prints: folder trees, label listings, message summaries, filter listings.
Package usage owns the generated documentation: the per-command Markdown tree under docs/clihelp, and the package inventory inside docs/ARCHITECTURE.md.
Package usage owns the generated documentation: the per-command Markdown tree under docs/clihelp, and the package inventory inside docs/ARCHITECTURE.md.
Package watcher polls mail accounts in the background and announces what is new: a desktop notification, a user script, and a flush of the offline outbox.
Package watcher polls mail accounts in the background and announces what is new: a desktop notification, a user script, and a flush of the offline outbox.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL