README.md
himalaya envelope list --account posteo --folder Archives.FOSS --page 2
wizard feature)./config.sample.toml)$EDITORimap feature)maildir feature)notmuch feature)smtp feature)sendmail feature)keyring feature)oauth2 feature)--output jsonpgp-commands feature)pgp-gpg feature)pgp-native feature)Himalaya CLI is written in Rust, and relies on cargo features to enable or disable functionalities. Default features can be found in the features section of the Cargo.toml, or on docs.rs.
Himalaya CLI can be installed with the install.sh installer:
As root:
curl -sSL https://raw.githubusercontent.com/pimalaya/himalaya/master/install.sh | sudo sh
As a regular user:
curl -sSL https://raw.githubusercontent.com/pimalaya/himalaya/master/install.sh | PREFIX=~/.local sh
These commands install the latest binary from the GitHub releases section.
If you want a more up-to-date version than the latest release, check out the releases GitHub workflow and look for the Artifacts section. You will find a pre-built binary matching your OS. These pre-built binaries are built from the master branch.
Such binaries are built with the default cargo features. If you need more features, please use another installation method.
Himalaya CLI can be installed with cargo:
cargo install himalaya --locked
With only IMAP support:
cargo install himalaya --locked --no-default-features --features imap
You can also use the git repository for a more up-to-date (but less stable) version:
cargo install --locked --git https://github.com/pimalaya/himalaya.git
Himalaya CLI can be installed on Arch Linux with either the community repository:
pacman -S himalaya
or the user repository:
git clone https://aur.archlinux.org/himalaya-git.git
cd himalaya-git
makepkg -isc
If you use yay, it is even simplier:
yay -S himalaya-git
Himalaya CLI can be installed with Homebrew:
brew install himalaya
Note: cargo features are not compatible with brew. If you need features like OAuth 2.0, please use a different installation method.
Himalaya CLI can be installed with Scoop:
scoop install himalaya
Himalaya CLI can be installed on Fedora Linux/CentOS/RHEL via COPR repo:
dnf copr enable atim/himalaya
dnf install himalaya
Himalaya CLI can be installed with Nix:
nix-env -i himalaya
You can also use the git repository for a more up-to-date (but less stable) version:
nix-env -if https://github.com/pimalaya/himalaya/archive/master.tar.gz
Or, from within the source tree checkout:
nix-env -if .
If you have the Flakes feature enabled:
nix profile install himalaya
Or, from within the source tree checkout:
nix profile install
You can also run Himalaya directly without installing it:
nix run himalaya
Himalaya CLI can be installed from sources.
First you need to install the Rust development environment (see the rust installation documentation):
curl https://sh.rustup.rs -sSf | sh
Then, you need to clone the repository and install dependencies:
git clone https://github.com/pimalaya/himalaya.git
cd himalaya
cargo check
Now, you can build Himalaya:
cargo build --release
Binaries are available under the target/release folder.
Just run himalaya, the wizard will help you to configure your default account.
Accounts can be (re)configured via the wizard using the command himalaya account configure <name>.
You can also manually edit your own configuration, from scratch:
./config.sample.toml~/.config/himalaya/config.tomlWhen using Proton Bridge, emails are synchronized locally and exposed via a local IMAP/SMTP server. This implies 2 things:
[accounts.proton]
email = "[email protected]"
backend.type = "imap"
backend.host = "127.0.0.1"
backend.port = 1143
backend.encryption.type = "none"
backend.login = "[email protected]"
backend.auth.type = "password"
backend.auth.raw = "*****"
message.send.backend.type = "smtp"
message.send.backend.host = "127.0.0.1"
message.send.backend.port = 1025
message.send.backend.encryption.type = "none"
message.send.backend.login = "[email protected]"
message.send.backend.auth.type = "password"
message.send.backend.auth.raw = "*****"
If you still want to use TLS, you need to export the certificate generated by Proton Bridge, then give it to Himalaya:
backend.encryption.type = "start-tls"
backend.encryption.cert = "/path/to/exported/cert.pem"
message.send.backend.encryption.type = "start-tls"
message.send.backend.encryption.cert = "/path/to/exported/cert.pem"
Keeping your password inside the configuration file is good for testing purpose, but it is not safe. You have 2 better alternatives:
Save your password in any password manager that can be queried via the CLI:
backend.auth.cmd = "pass show proton"
Use the global keyring of your system (requires the keyring cargo feature):
backend.auth.keyring = "proton-example"
Running himalaya account configure proton will ask for your IMAP password, just paste the one generated previously.
Google passwords cannot be used directly. There is two ways to authenticate yourself:
This option is the simplest and the fastest. First, be sure that:
First create a dedicated password for Himalaya.
[accounts.gmail]
email = "[email protected]"
folder.aliases.inbox = "INBOX"
folder.aliases.sent = "[Gmail]/Sent Mail"
folder.aliases.drafts = "[Gmail]/Drafts"
folder.aliases.trash = "[Gmail]/Trash"
backend.type = "imap"
backend.host = "imap.gmail.com"
backend.port = 993
backend.login = "[email protected]"
backend.auth.type = "password"
backend.auth.raw = "*****"
message.send.backend.type = "smtp"
message.send.backend.host = "smtp.gmail.com"
message.send.backend.port = 465
message.send.backend.login = "[email protected]"
message.send.backend.auth.type = "password"
message.send.backend.auth.cmd = "*****"
Keeping your password inside the configuration file is good for testing purpose, but it is not safe. You have 2 better alternatives:
Save your password in any password manager that can be queried via the CLI:
backend.auth.cmd = "pass show gmail"
Use the global keyring of your system (requires the keyring cargo feature):
backend.auth.keyring = "gmail-example"
Running himalaya configure -a gmail will ask for your IMAP password, just paste the one generated previously.
This option is the most secure but the hardest to configure. It requires the oauth2 and keyring cargo features.
First, you need to get your OAuth 2.0 credentials by following this guide. Once you get your client id and your client secret, you can configure your Himalaya account this way:
[accounts.gmail]
email = "[email protected]"
folder.aliases.inbox = "INBOX"
folder.aliases.sent = "[Gmail]/Sent Mail"
folder.aliases.drafts = "[Gmail]/Drafts"
folder.aliases.trash = "[Gmail]/Trash"
backend.type = "imap"
backend.host = "imap.gmail.com"
backend.port = 993
backend.login = "[email protected]"
backend.auth.type = "oauth2"
backend.auth.method = "xoauth2"
backend.auth.client-id = "*****"
backend.auth.client-secret.keyring = "gmail-oauth2-client-secret"
backend.auth.access-token.keyring = "gmail-oauth2-access-token"
backend.auth.refresh-token.keyring = "gmail-oauth2-refresh-token"
backend.auth.auth-url = "https://accounts.google.com/o/oauth2/v2/auth"
backend.auth.token-url = "https://www.googleapis.com/oauth2/v3/token"
backend.auth.pkce = true
backend.auth.scope = "https://mail.google.com/"
message.send.backend.type = "smtp"
message.send.backend.host = "smtp.gmail.com"
message.send.backend.port = 465
message.send.backend.login = "[email protected]"
message.send.backend.auth.type = "oauth2"
message.send.backend.auth.method = "xoauth2"
message.send.backend.auth.client-id = "*****"
message.send.backend.auth.client-secret.keyring = "gmail-oauth2-client-secret"
message.send.backend.auth.access-token.keyring = "gmail-oauth2-access-token"
message.send.backend.auth.refresh-token.keyring = "gmail-oauth2-refresh-token"
message.send.backend.auth.auth-url = "https://accounts.google.com/o/oauth2/v2/auth"
message.send.backend.auth.token-url = "https://www.googleapis.com/oauth2/v3/token"
message.send.backend.auth.pkce = true
message.send.backend.auth.scope = "https://mail.google.com/"
Running himalaya account configure gmail will complete your OAuth 2.0 setup and ask for your client secret.
[accounts.outlook]
email = "[email protected]"
backend.type = "imap"
backend.host = "outlook.office365.com"
backend.port = 993
backend.login = "[email protected]"
backend.auth.type = "password"
backend.auth.raw = "*****"
message.send.backend.type = "smtp"
message.send.backend.host = "smtp-mail.outlook.com"
message.send.backend.port = 587
message.send.backend.encryption.type = "start-tls"
message.send.backend.login = "[email protected]"
message.send.backend.auth.type = "password"
message.send.backend.auth.raw = "*****"
Keeping your password inside the configuration file is good for testing purpose, but it is not safe. You have 2 better alternatives:
Save your password in any password manager that can be queried via the CLI:
backend.auth.cmd = "pass show outlook"
Use the global keyring of your system (requires the keyring cargo feature):
backend.auth.keyring = "outlook-example"
Running himalaya account configure outlook will ask for your IMAP password, just paste the one generated previously.
This option is the most secure but the hardest to configure. First, you need to get your OAuth 2.0 credentials by following this guide. Once you get your client id and your client secret, you can configure your Himalaya account this way:
[accounts.outlook]
email = "[email protected]"
backend.type = "imap"
backend.host = "outlook.office365.com"
backend.port = 993
backend.login = "[email protected]"
backend.auth.type = "oauth2"
backend.auth.client-id = "*****"
backend.auth.client-secret.keyring = "outlook-oauth2-client-secret"
backend.auth.access-token.keyring = "outlook-oauth2-access-token"
backend.auth.refresh-token.keyring = "outlook-oauth2-refresh-token"
backend.auth.auth-url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
backend.auth.token-url = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
backend.auth.pkce = true
backend.auth.scopes = ["https://outlook.office.com/IMAP.AccessAsUser.All", "https://outlook.office.com/SMTP.Send"]
message.send.backend.type = "smtp"
message.send.backend.host = "smtp.mail.outlook.com"
message.send.backend.port = 587
message.send.backend.starttls = true
message.send.backend.login = "[email protected]"
message.send.backend.auth.type = "oauth2"
message.send.backend.auth.client-id = "*****"
message.send.backend.auth.client-secret.keyring = "outlook-oauth2-client-secret"
message.send.backend.auth.access-token.keyring = "outlook-oauth2-access-token"
message.send.backend.auth.refresh-token.keyring = "outlook-oauth2-refresh-token"
message.send.backend.auth.auth-url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
message.send.backend.auth.token-url = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
message.send.backend.auth.pkce = true
message.send.backend.auth.scopes = ["https://outlook.office.com/IMAP.AccessAsUser.All", "https://outlook.office.com/SMTP.Send"]
Running himalaya account configure outlook will complete your OAuth 2.0 setup and ask for your client secret.
From the iCloud Mail support page:
993.johnappleseed, not [email protected])587 with STARTTLS[email protected], not johnappleseed)[accounts.icloud]
email = "[email protected]"
backend.type = "imap"
backend.host = "imap.mail.me.com"
backend.port = 993
backend.login = "johnappleseed"
backend.auth.type = "password"
backend.auth.raw = "*****"
message.send.backend.type = "smtp"
message.send.backend.host = "smtp.mail.me.com"
message.send.backend.port = 587
message.send.backend.encryption.type = "start-tls"
message.send.backend.login = "[email protected]"
message.send.backend.auth.type = "password"
message.send.backend.auth.raw = "*****"
folder.aliases.sent = "Sent Messages"
Keeping your password inside the configuration file is good for testing purpose, but it is not safe. You have 2 better alternatives:
Save your password in any password manager that can be queried via the CLI:
backend.auth.cmd = "pass show icloud"
Use the global keyring of your system (requires the keyring cargo feature):
backend.auth.keyring = "icloud-example"
Running himalaya account configure icloud will ask for your IMAP password, just paste the one generated previously.
These interfaces are built at the top of Himalaya CLI to improve the User Experience:
Aerc, mutt and alpine can be categorized as Terminal User Interfaces (TUI). When the program is executed, your terminal is locked into an event loop and you interact with your emails using keybinds.
Himalaya is also a TUI, but more specifically a Command-Line Interface (CLI). There is no event loop: you interact with your emails using shell commands, in a stateless way.
Additionaly, Himalaya CLI is based on email-lib, which is also part of the Pimalaya project. The aim is not just to propose a new terminal interface, but also to expose Rust tools to deal with emails. Anyone who knows Rust language can build his own email interface, without re-inventing the wheel.
An email message is a list of headers (key: val) followed by a body. They form together a template:
Header: value
Header: value
Header: value
Body
Headers and body must be separated by an empty line.
Here a non-exhaustive list of valid email message template headers:
Message-ID: represents the message identifier (you usually do not need to set up it manually)In-Reply-To: represents the identifier of the replied messageDate: represents the date of the messageSubject: represents the subject of the messageFrom: represents the address of the senderTo: represents the addresses of the receiversReply-To: represents the address the receiver should reply to instead of the From headerCc: represents the addresses of the other receivers (carbon copy)Bcc: represents the addresses of the other hidden receivers (blind carbon copy)An address can be:
user@domainName <user@domain>"Name" <user@domain>Multiple address are separated by a comma ,: user@domain, Name <user@domain>, "Name" <user@domain>.
Email message template body can be written in plain text. The result will be compiled into a single text/plain MIME part:
From: alice@localhost
To: Bob <bob@localhost>
Subject: Hello from Himalaya
Hello, world!
Email message template body can also be written in MML. The MIME Meta Language was introduced by the Emacs mml ELisp module. Pimalaya ported it in Rust.
A raw email message is structured according to the MIME standard. This standard produces verbose, non-friendly messages. Here comes MML: it simplifies the way email message body are structured. Thanks to its simple XML-based syntax, it allows you to easily add multiple parts, attach a binary file, or attach inline image to your body without dealing with the MIME standard.
For instance, this MML template:
From: alice@localhost
To: bob@localhost
Subject: MML simple
<#multipart type=alternative>
This is a plain text part.
<#part type=text/enriched>
<center>This is a centered enriched part</center>
<#/multipart>
compiles into the following MIME Message:
Subject: MML simple
To: bob@localhost
From: alice@localhost
MIME-Version: 1.0
Date: Tue, 29 Nov 2022 13:07:01 +0000
Content-Type: multipart/alternative;
boundary="4CV1Cnp7mXkDyvb55i77DcNSkKzB8HJzaIT84qZe"
--4CV1Cnp7mXkDyvb55i77DcNSkKzB8HJzaIT84qZe
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
This is a plain text part.
--4CV1Cnp7mXkDyvb55i77DcNSkKzB8HJzaIT84qZe
Content-Type: text/enriched
Content-Transfer-Encoding: 7bit
<center>This is a centered enriched part</center>
--4CV1Cnp7mXkDyvb55i77DcNSkKzB8HJzaIT84qZe--
See more examples at pimalaya/core/mml.
</details> <details> <summary>How to add attachments to a message?</summary>Read first about the FAQ: How to compose a message?.
From: alice@localhost
To: bob@localhost
Subject: How to attach stuff
Regular binary attachment:
<#part filename=/path/to/file.pdf><#/part>
Custom file name:
<#part filename=/path/to/file.pdf name=custom.pdf><#/part>
Inline image:
<#part disposition=inline filename=/path/to/image.png><#/part>
See more examples at pimalaya/core/mml.
</details> <details> <summary>How to debug Himalaya CLI?</summary>The simplest way is to use --debug and --trace arguments.
The advanced way is based on environment variables:
RUST_LOG=<level>: determines the log level filter, can be one of off, error, warn, info, debug and trace.RUST_SPANTRACE=1: enables the spantrace (a span represent periods of time in which a program was executing in a particular context).RUST_BACKTRACE=1: enables the error backtrace.RUST_BACKTRACE=full: enables the full error backtrace, which include source lines where the error originated from.Logs are written to the stderr, which means that you can redirect them easily to a file:
RUST_LOG=debug himalaya 2>/tmp/himalaya.log
All the lookup mechanisms use the email address domain as base for the lookup. It is heavily inspired from the Thunderbird Autoconfiguration protocol. For example, for the email address [email protected], the lookup is performed as (in this order):
autoconfig.example.comexample.com in the ISPDB (the Thunderbird central database)MX example.com in DNS, and for mx1.mail.hoster.com, look up hoster.com in the ISPDBSRV example.com in DNSimap.example.com, smtp.example.com…)Simply set the environment variable NO_COLOR=1
</details>Special thanks to the NLnet foundation and the European Commission that have been financially supporting the project for years:
If you appreciate the project, feel free to donate using one of the following providers: