Welcome to Himalaya CLI, the Command-Line Interface to manage emails based on email-lib.

screenshot

Disclaimer: the project is under active development, do not use in production before the final v1.0.0.

Features

Installation

# Arch Linux (official)
$ pacman -S himalaya

# Arch Linux (from sources)
$ yay -S himalaya-git

# Homebrew
$ brew install himalaya

# Scoop
$ scoop install himalaya

# Cargo
$ cargo install himalaya

# Nix
$ nix-env -i himalaya

# Fedora/CentOS
$ dnf copr enable atim/himalaya
$ dnf install himalaya

See the documentation for other installation methods.

Configuration

Please read the documentation.

Contributing

Please read the contributing guide for more detailed information.

A bug tracker is available on SourceHut. [send an email]

A mailing list is available on SourceHut. [send an email] [subscribe] [unsubscribe]

If you want to report a bug, please send an email at ~soywod/pimalaya@todo.sr.ht.

If you want to propose a feature or fix a bug, please send a patch at ~soywod/pimalaya@lists.sr.ht. The simplest way to send a patch is to use git send-email, follow this guide to configure git properly.

If you just want to discuss about the project, feel free to join the Matrix workspace #pimalaya.himalaya or contact me directly @soywod. You can also use the mailing list.

Sponsoring

nlnet

Special thanks to the NLnet foundation and the European Commission that helped the project to receive financial support from:

If you appreciate the project, feel free to donate using one of the following providers:

GitHub Sponsors, PayPal, Ko-fi, Buy Me a Coffee, Liberapay

Quickstart

Installation

The fastest way to get started is to install the pre-built binary matching your system. You can manually download it from the GitHub releases section or let this script do the job for you:

$ curl -sSL https://pimalaya.org/himalaya/cli/install.sh | PREFIX=~/.local sh

See other installation methods.

Configuration

The wizard will create a configuration file for you, just follow the steps:

$ himalaya

Cannot find existing configuration at "~/.config/himalaya/config.toml".
Would you like to create one with the wizard? [Y/n]

See other configuration methods.

Basic usage

structure

  • An account is a set of options allowing users to connect to folders.
  • A folder (aka mailbox) is an email container.
  • An email is composed of an envelope and a message
  • An envelope is a set of properties identifying a message.
  • A message is composed of headers and a body, including attachments.
  • An attachment is (usually) a binary content like an image, a PDF etc.

To get a better overview of the Himalaya CLI features, try this actions:

Advanced usage

Once familiar with the core concept of the tool, have a look at the advanced usage section: you will find a complete usage API categorized by domain. You can also use the -h flag to get information about the current command, or the --help argument for more detailed information.

Troubleshooting

If you have any problem, have a look at the FAQ section or the bug tracker. If nothing helped you:

Installation

Arch Linux

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

Homebrew

Himalaya CLI can be installed with Homebrew:

$ brew install himalaya

Scoop

Himalaya CLI can be installed with Scoop:

$ scoop install himalaya

Cargo

Himalaya CLI can be installed with cargo:

$ cargo install himalaya

You can also use the git repository for a more up-to-date (but less stable) version:

$ cargo install --git https://github.com/soywod/himalaya himalaya

Himalaya CLI comes with few default features:

  • imap: enables IMAP backend features
  • maildir: enables Maildir backend features
  • smtp: enables SMTP backend features
  • sendmail: enables sendmail backend features
  • account-sync: enables account synchronization (including folders and emails)
  • account-discovery: enables account auto discovery for the wizard

There is also other optional features:

  • notmuch: enables notmuch backend features (requires the notmuch lib to be installed on the system)
  • pgp-commands enables the PGP shell commands backend
  • pgp-gpg enables the GPG PGP backend (requires the gpgme lib to be installed on the system)
  • pgp-native enables the native PGP backend

Nix

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/soywod/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

Development

To enter a development shell:

$ nix-shell

# or, with the Flakes feature enabled
$ nix develop

From here, you have access to all the development tools (Rust compiler, cargo, rust language server, code formatter…) necessary to hack on Himalaya.

If you use VSCode, simply open this project folder and accept the workspace extension recommendations.

Troubleshooting

  • See this discussion if you get the hash mismatch in fixed-output derivation error.

Fedora Linux/CentOS/RHEL

Himalaya CLI can be installed on Fedora Linux/CentOS/RHEL via COPR repo:

$ dnf copr enable atim/himalaya
$ dnf install himalaya

Binary

Himalaya CLI can be installed with a prebuilt binary:

# As root:
$ curl -sSL https://pimalaya.org/himalaya/cli/install.sh | sudo sh

# As a regular user:
$ curl -sSL https://pimalaya.org/himalaya/cli/install.sh | PREFIX=~/.local sh

Those commands install the latest binary from the GitHub releases section.

Note: Linux, macOS and Windows are supported. Note that some features may not work as expected on Windows.

Sources

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/soywod/himalaya.git
$ cd himalaya
$ cargo check

Now, you can build Himalaya:

$ cargo build --release

Note: binaries are available in the target/release folder.

Troubleshooting

Could not compile autocfg

On aarch64, compiling autocfg will exhaust all available memory and rustcc will be killed by OS. You need to update llvm-libs to the latest version to solve this problem. This is a llvm bug.

Configuration

Himalaya CLI takes its TOML configuration from one of those paths:

  • $XDG_CONFIG_HOME/himalaya/config.toml
  • $HOME/.config/himalaya/config.toml
  • $HOME/.himalayarc

There is 2 ways to configure Himalaya CLI:

Automatically, using the wizard

You just need to run himalaya. You can configure separated files using the -c|--config argument, for example: himalaya -c /tmp/config.toml.

Note: actually you can only create new configurations with the wizard. There is an opened issue #42 to edit existing configurations using the wizard.

Manually, by editing the TOML file

The file should first contain your global configuration, followed by your accounts configurations. Each account configuration should be located inside a TOML section (table). The table name should be unique, as it is used to identify an account:

# global config

[accounts.example1]
# account config

[accounts.example2]
# account config

# …

Global configuration

The global configuration is the configuration that is applied by default to all your accounts.

display-name

The display name of the user.

It usually corresponds to the full name of the user.

display-name = "Clément DOUIN"

signature

The email signature of the user.

It can be either a path to a file (usually ~/.signature) or a raw string. The signature supports TOML multiline.

signature = "~/.signature"
signature = "Regards,"
signature = """
Thank you,
Regards,
"""

signature-delim

The email signature delimiter of the user signature. Defaults to -- \n.

signature-delim = "~~ \n"

downloads-dir

The downloads directory.

It is mostly used for downloading messages attachments. Defaults to the system temporary directory (usually /tmp).

downloads-dir = "~/Downloads"

Account configuration

See the advanced usage section for the complete settings API.

Example

Here a complete and documented config.sample.toml that you can actually test yourself with the following commands:

# save the sample config locally
curl https://raw.githubusercontent.com/soywod/himalaya/master/config.sample.toml > config.sample.toml

# spawn a testing IMAP/SMTP server using docker
docker run -it --rm -p 3025:3025 -p 3110:3110 -p 3143:3143 -p 3465:3465 -p 3993:3993 -p 3995:3995 -e GREENMAIL_OPTS='-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.verbose' greenmail/standalone:latest

# test the CLI using the sample config
himalaya -c ./config.sample.toml envelope list
# The account name.
[accounts.example]

# The current account will be used by default for all other commands.
default = true

# The display-name and the email are used to build the full email
# address: "My example account" <example@localhost>
display-name = "My example account"
email = "example@localhost"

# The signature can be a string or a path to a file.
signature = "Regards,"
signature-delim = "-- \n"

# Enable the synchronization for this account. Running the command
# `account sync example` will synchronize all folders and all emails
# to a local Maildir at `$XDG_DATA_HOME/himalaya/example`.
sync.enable = false

# Override the default Maildir path for synchronization.
sync.dir = "/tmp/himalaya-sync-example"

# Filter folders to sync
folder.sync.filter.include = ["INBOX"]
# folder.sync.filter.exclude = ["All mails"]
# folder.sync.filter = "all"

# Define main folder aliases
folder.alias.inbox = "INBOX"
folder.alias.sent = "Sent"
folder.alias.drafts = "Drafts"
folder.alias.trash = "Trash"

# Also define custom folder aliases
folder.alias.prev-year = "Archives/2023"

# Default backend used for all the features like adding folders,
# listing envelopes or copying messages.
backend = "imap"

envelope.list.page-size = 10
envelope.list.datetime-fmt = "%F %R%:z"

# Date are converted to the user's local timezone.
envelope.list.datetime-local-tz = true

# Override the backend used for listing envelopes.
# envelope.list.backend = "imap"

# Send notification on receiving new envelopes
envelope.watch.received.notify.summary = "📬 New message from {sender}"

# Available placeholders: id, subject, sender, sender.name,
# sender.address, recipient, recipient.name, recipient.address.
envelope.watch.received.notify.body = "{subject}"

# Shell commands can also be executed when envelopes change
# envelope.watch.any.cmd = "mbsync -a"

# Override the backend used for sending messages.
message.send.backend = "smtp"

# Save a copy of sent messages to the sent folder.
message.send.save-copy = false

# IMAP config
imap.host = "localhost"
imap.port = 3143
imap.login = "example@localhost"

# Encryption can be either "tls" (or true), "start-tls" or "none" (or false).
imap.encryption = "none"

# Get password from a raw string (not safe)
imap.passwd.raw = "password"

# Get password from a shell command
# imap.passwd.cmd = "echo password"

# Get password from your global system keyring using secret service
# Keyring secrets can be (re)set with the command `account configure example`
# imap.passwd.keyring = "example-imap-password"

# Customize at which period, in seconds, the IMAP IDLE mode should refresh.
# Defaults to 1740 (29 min), as defined in the RFC.
# imap.watch.timeout = 25

# SMTP config
smtp.host = "localhost"
smtp.port = 3025
smtp.login = "example@localhost"
smtp.encryption = false
smtp.passwd.raw = "password"

# PGP needs to be enabled with one of those cargo feature:
# pgp-commands, pgp-gpg or pgp-native
# pgp.backend = "gpg"

Proton Bridge configuration

When using Proton Bridge, emails are synchronized locally and exposed via a local IMAP/SMTP server. This implies 2 things:

  • Id order may be reversed or shuffled, but envelopes will still be sorted by date
  • SSL/TLS needs to be deactivated manually
display-name = "Clément DOUIN"
downloads-dir = "~/downloads"
signature = "Cordialement,\nClément DOUIN"

[accounts.proton]
default = true
email = "clement.douin@proton.me"

backend = "imap"
imap.host = "127.0.0.1"
imap.port = 1143
imap.encryption = false
imap.login = "clement.douin@proton.me"
imap.passwd.cmd = "pass show proton"

message.send.backend = "smtp"
smtp.host = "127.0.0.1"
smtp.port = 1025
smtp.encryption = false
smtp.login = "clement.douin@proton.me"
smtp.passwd.cmd = "pass show proton"

Gmail configuration

Google passwords cannot be used directly. There is two ways to authenticate yourself:

Using App Passwords

This option is the simplest and the fastest. First, be sure that:

  • IMAP is enabled
  • Two-step authentication is enabled
  • Less secure app access is enabled

Then you can create a dedicated password for Himalaya at https://myaccount.google.com/apppasswords. See the imap-auth section on how to use it.

display-name = "Clément DOUIN"
downloads-dir = "~/Downloads"
signature = "Cordialement,\nClément DOUIN"

[accounts.gmail]
default = true
email = "clement.douin@gmail.com"

folder.alias.inbox = "INBOX"
folder.alias.sent = "[Gmail]/Sent Mail"
folder.alias.drafts = "[Gmail]/Drafts"
folder.alias.trash = "[Gmail]/Trash"

backend = "imap"
imap.host = "imap.gmail.com"
imap.port = 993
imap.login = "clement.douin@gmail.com"
imap.passwd.cmd = "pass show gmail"

message.send.backend = "smtp"
smtp.host = "smtp.gmail.com"
smtp.port = 465
smtp.login = "clement.douin@gmail.com"
smtp.passwd.cmd = "pass show gmail"

Note: passwords are prompted when running the command himalaya accounts configure.

Using OAuth 2.0

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:

display-name = "Clément DOUIN"
downloads-dir = "~/Downloads"
signature = "Cordialement,\nClément DOUIN"

[accounts.gmail]
default = true
email = "clement.douin@gmail.com"

folder.alias.inbox = "INBOX"
folder.alias.sent = "[Gmail]/Sent Mail"
folder.alias.drafts = "[Gmail]/Drafts"
folder.alias.trash = "[Gmail]/Trash"

backend = "imap"
imap.host = "imap.gmail.com"
imap.port = 993
imap.login = "clement.douin@gmail.com"
imap.oauth2.client-id = "<imap.client-id>"
imap.oauth2.auth-url = "https://accounts.google.com/o/oauth2/v2/auth"
imap.oauth2.token-url = "https://www.googleapis.com/oauth2/v3/token"
imap.oauth2.pkce = true
imap.oauth2.scope = "https://mail.google.com/"

message.send.backend = "smtp"
smtp.host = "smtp.gmail.com"
smtp.port = 465
smtp.login = "clement.douin@gmail.com"
smtp.oauth2.client-id = "<smtp.client-id>"
smtp.oauth2.auth-url = "https://accounts.google.com/o/oauth2/v2/auth"
smtp.oauth2.token-url = "https://www.googleapis.com/oauth2/v3/token"
smtp.oauth2.pkce = true
smtp.oauth2.scope = "https://mail.google.com/"

# If you want your SMTP to share the same client id (and so the same access token)
# as your IMAP config, you can add the following:

# smtp.oauth2.client-id = "<imap-client-id>"
# smtp.oauth2.client-secret.keyring = "gmail-imap-oauth2-client-secret"
# smtp.oauth2.access-token.keyring = "gmail-imap-oauth2-access-token"
# smtp.oauth2.refresh-token.keyring = "gmail-imap-oauth2-refresh-token"

Note: client secrets are prompted when running the command himalaya accounts configure.

Outlook configuration

display-name = "Clément DOUIN"
downloads-dir = "~/Downloads"
signature = "Cordialement,\nClément DOUIN"

[accounts.outlook]
default = true
email = "clement.douin@outlook.com"

backend = "imap"
imap.host = "outlook.office365.com"
imap.port = 993
imap.login = "clement.douin@outlook.com"
imap.passwd.cmd = "pass show outlook"

message.send.backend = "smtp"
smtp.host = "smtp.mail.outlook.com"
smtp.port = 587
smtp.encryption = "start-tls"
smtp.login = "clement.douin@outlook.com"
smtp.passwd.cmd = "pass show outlook"

Note: passwords are prompted when running the command himalaya accounts configure.

Using OAuth 2.0

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:

display-name = "Clément DOUIN"
downloads-dir = "~/Downloads"
signature = "Cordialement,\nClément DOUIN"

[accounts.outlook]
default = true
email = "clement.douin@outlook.com"

backend = "imap"
imap.host = "outlook.office365.com"
imap.port = 993
imap.login = "clement.douin@outlook.com"
imap.oauth2.client-id = "<imap.client-id>"
imap.oauth2.auth-url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
imap.oauth2.token-url = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
imap.oauth2.pkce = true
imap.oauth2.scopes = [
  "offline_access",
  "https://outlook.office.com/IMAP.AccessAsUser.All",
]

message.send.backend = "smtp"
smtp.host = "smtp.mail.outlook.com"
smtp.port = 587
smtp.starttls = true
smtp.login = "clement.douin@outlook.com"
smtp.oauth2.client-id = "<smtp.client-id>"
smtp.oauth2.auth-url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
smtp.oauth2.token-url = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
smtp.oauth2.pkce = true
smtp.oauth2.scope = "https://outlook.office.com/SMTP.Send"

Note: client secrets are prompted when running the command himalaya accounts configure.

iCloud Mail configuration

From the iCloud Mail support page:

  • IMAP port = 993.
  • IMAP login = name of your iCloud Mail email address (for example, johnappleseed, not johnappleseed@icloud.com)
  • SMTP port = 587 with STARTTLS
  • SMTP login = full iCloud Mail email address (for example, johnappleseed@icloud.com, not johnappleseed)
[accounts.icloud]
display-name = "John APPLESEED"
email = "johnappleseed@icloud.com"

signature = """
Regards,
John AppleSeed
Sent from iCloud
"""

backend = "imap"
imap.host = "imap.mail.me.com"
imap.port = 993
imap.login = "johnappleseed"
imap.passwd.cmd = "pass show icloud"

message.send.backend = "smtp"
smtp.host = "smtp.mail.me.com"
smtp.port = 587
smtp.encryption = "start-tls"
smtp.login = "johnappleseed@icloud.com"
smtp.passwd.cmd = "pass show icloud"

Note: passwords are prompted when running the command himalaya accounts configure.

Basic usage

structure

  • An account is a set of options allowing users to connect to folders.
  • A folder (aka mailbox) is an email container.
  • An email is composed of an envelope and a message
  • An envelope is a set of properties identifying a message.
  • A message is composed of headers and a body, including attachments.
  • An attachment is (usually) a binary content like an image, a PDF etc.

To get a good overview of the Himalaya CLI features, try these actions:

List folders

$ himalaya folder list

Lists all folders of the current account. 2 properties are displayed:

  • name: the name of the folder
  • desc: the description of the folder

See the advanced version for more details.

Example

$ himalaya folder list
NAME              │DESC                 
Junk              │\HasNoChildren, Junk 
Archives          │\HasChildren         
Archives.FOSS     │\HasNoChildren       
Trash             │\HasNoChildren       
Notes             │\HasNoChildren       
Drafts            │\HasNoChildren       
Sent              │\HasNoChildren       
INBOX             │\HasNoChildren       

List envelopes

$ himalaya envelope list

Lists all envelopes of the current folder. 5 properties are displayed:

  • id: the identifier of the envelope
  • flags: the flags associated to the envelope
  • subject: the subject from the message headers
  • from: the first sender from the message headers
  • to: the first recipient from the message headers
  • date: the date from the message headers

See the advanced version for more details.

Example

$ himalaya envelope list
ID  │FLAGS │SUBJECT                                    │FROM               │DATE                   
937 │      │~soywod/pimalaya#161: TOML parse error: m… │~Phil Crockett     │2023-12-22 15:12+00:00 
938 │      │Re: [dantecatalfamo/himalaya-emacs] Prepa… │Dante Catalfamo    │2023-12-20 23:21-08:00 
939 │      │Re: Short question                         │michiel@nlnet.nl   │2023-12-20 17:39+01:00 
940 │      │Update and important request: EC evaluati… │Michiel Leenaars   │2023-12-20 12:44+00:00 
941 │      │Re: Short question                         │michiel@nlnet.nl   │2023-12-20 12:23+01:00 
942 │      │Short question                             │michiel@nlnet.nl   │2023-12-20 09:40+01:00 
943 │      │Request for payment for 2023-04-034: Pima… │dashboard@nlnet.nl │2023-12-18 13:20+00:00 
944 │      │Re: [TornaxO7/rfc2047-decoder] InvalidByt… │TornaxO7           │2023-12-17 05:55-08:00 
945 │      │Re: [TornaxO7/rfc2047-decoder] InvalidByt… │TornaxO7           │2023-12-17 05:55-08:00 
946 │      │Please confirm the RfP for 2023-04-034: P… │dashboard@nlnet.nl │2023-12-14 23:24+00:00 

Read a message

$ himalaya message read <ID>

Reads message matching the given envelope id.

See the advanced version for more details.

Example

$ himalaya message read 944
From: ~matf <outgoing@sr.ht>
To: soywod <clement.douin@posteo.net>
Subject: ~soywod/pimalaya#154: Configuration wizard: cannot canonicalize path

I built `himalaya` from sources using the `cargo` instructions in the documentation, then followed the configuration wizard (it's nice), but unfortunately it seems unable to save the `config.toml`:

✘ cannot canonicalize path "/home/droidian/.config/himalaya/config.toml"
? Where would you like to save your configuration? (/home/droidian/.config/himalaya/config.toml) ›  

The same happens whether I `mkdir -p ~/.config/himalaya` or not.

Any ideas? This is on aarch64.


-- 
View on the web: https://todo.sr.ht/~soywod/pimalaya/154

Write & send a message

There are multiple ways to send a message:

Compose a message interactively

$ himalaya message write

Opens your editor (the one specified in the $EDITOR environment variable) to edit a new message, then sends it. The edition stops when you exit your editor.

You can customize the editor for a given command by prefixing it with a custom $EDITOR environment variable:

$ EDITOR=nano himalaya message write

See the advanced version for more details.

Reply to a message interactively

$ himalaya message reply <ID>

Similar to write a new message: finds the message matching the given envelope identifier, opens your editor to edit a reply message then sends it.

Note: you can reply to all recipients with the flag -A|--all.

See the advanced version for more details.

Forward a message interactively

$ himalaya message forward <ID>

Similar to write a new message: finds the message matching the given envelope identifier, opens your editor to edit a forward message then sends it.

See the advanced version for more details.

Send a message

$ himalaya message send [MESSAGE]...

Sends the given message. The message can come from arguments or from the standard input (if the terminal is not interactive).

See the advanced version for more details.

Example

$ cat /tmp/email.eml | himalaya message send
$ himalaya message send < /tmp/email.eml
$ himalaya message send 'From: alice@localhost
To: bob@localhost
Subject: Hello

Hello, world!'

Download attachments

$ himalaya attachment download <ID>

Downloads all attachments found in the message matching the given envelope id to your downloads directory.

See the advanced version for more details.

Example

$ himalaya attachment download 3384
2 attachment(s) found for message 3384!
Downloading "~/downloads/document.pdf"…
Downloading "~/downloads/screenshot.png"…
Downloaded 2 attachments!

Watch for envelopes changes

$ himalaya envelope watch

Watches the current folder and executes hooks when changes occur on envelopes.

If synchronization is enabled, the command will watch local cached folders. To force the command to watch remote folders, you can either:

  1. Force the remote backend for the watch envelopes feature, for example:

    # ~/.config/himalaya/config.toml
    
    envelope.watch.backend = "imap"
    
  2. Disable the cache with the --disable-cache flag:

    $ himalaya envelope watch --disable-cache
    

See the advanced version for more details.

Examples

Get notified on new emails

To receive system notifications when new emails arrive in the INBOX:

# ~/.config/himalaya/config.toml

# Available placeholders:
# id, subject, sender, sender.name, sender.address, recipient, recipient.name, recipient.address.

envelope.watch.received.notify.summary = "📬 New message from {sender}"
envelope.watch.received.notify.body = "{subject}"
$ himalaya envelope watch

Synchronize account on new emails

To run commands when new emails arrive in the INBOX:

# ~/.config/himalaya/config.toml

envelope.watch.received.cmd = "himalaya account sync"
$ himalaya envelope watch

Synchronize an account for offline usage

$ himalaya account sync

Synchronizes current account’s folders and emails locally, for an offline usage of the CLI.

Before using this feature, be sure that you enabled it (either by using the wizard or by manually editing the configuration file):

[accounts.example]
sync.enable = true

See the advanced version for more details.

Examples

Dry run

Run the synchronization without applying any changes. Instead, a report will be printed to stdout containing all the changes the synchronization plans to do.

$ himalaya account sync --dry-run
Envelopes patch:
 - Updating flags seen of right cached envelope 14031 (INBOX)
 - Copying right envelope 14047 to left folder INBOX
 - Updating flags seen of left cached envelope 1704194588.#7M923748111P3344451V65024I15206527.soywod,S=7401 (INBOX)
 - Setting flags seen of right envelope 14030 (INBOX)
 - Setting flags seen of right envelope 14031 (INBOX)
 - Updating flags seen of right cached envelope 14030 (INBOX)
 - Updating flags seen of left cached envelope 1704194588.#9M963882549P3344451V65024I15206530.soywod,S=6999 (INBOX)

Estimated patch length for account example to be synchronized: 7

Synchronize only one folder

$ himalaya account sync --include-folder INBOX

Exclude a folder from the sync

$ himalaya account sync --exclude-folder All

Advanced usage

$ himalaya [OPTIONS] <COMMAND>

Commands

structure

Names in yellow correspond to domains covered by Himalaya CLI. Every domain has its own dedicated command: account, folder, envelope, flag, message, attachment, template.

Options

These options are global, which means they can be used in all commands and subcommands.

-c|--config

Override the default configuration file path.

The given path is shell-expanded then canonicalized (if applicable). If the path does not point to a valid file, the wizard will propose to assist you in the creation of the configuration file.

-o|--output

Customize the output format

The output format determine how to display commands output to the terminal. The possible values are:

  • json: output will be in a form of a JSON-compatible object
  • plain: output will be in a form of either a plain text or table, depending on the command

-C|--color

Control when to use colors

The default setting is ‘auto’, which means himalaya will try to guess when to use colors. For example, if himalaya is printing to a terminal, then it will use colors, but if it is redirected to a file or a pipe, then it will suppress color output. himalaya will suppress color output in some other circumstances as well. For example, if the $TERM environment variable is not set or set to dumb, then himalaya will not use colors.

The possible values are:

  • never: colors will never be used
  • always: colors will always be used regardless of where output is sent
  • ansi: like ‘always’, but emits ANSI escapes (even in a Windows console)
  • auto: himalaya tries to be smart

--debug

Enable logs with spantrace.

This is the same as running the command with RUST_LOG=debug environment variable.

--trace

Enable verbose logs with backtrace.

This is the same as running the command with RUST_LOG=trace and RUST_BACKTRACE=1 environment variables.

Settings

imap

Configuration related to IMAP. See the documentation.

maildir

Configuration related to Maildir. See the documentation.

notmuch

Configuration related to notmuch. See the documentation.

smtp

Configuration related to SMTP. See the documentation.

sendmail

Configuration related to sendmail. See the documentation.

pgp

Configuration related end-to-end PGP encryption. See the documentation.

API by domain

structure

Names in yellow correspond to domains covered by Himalaya CLI. Every domain has its own dedicated command: account, folder, envelope, flag, message, attachment, template.

Accounts

structure

An account is a group of settings, identified by an account name. Settings are directly taken from your TOML configuration file. Accounts can be managed with those commands:

Settings

email (required)

The email address of the user account.

email = "clement.douin@posteo.net"

default

The current account will be used by default for all other commands.

default = true

display-name

The display name of the user.

It usually corresponds to the full name of the user.

display-name = "Clément DOUIN"

signature

The email signature of the user.

It can be either a path to a file (usually ~/.signature) or a raw string. The signature supports TOML multiline.

signature = "~/.signature"
signature = "Regards,"
signature = """
Thank you,
Regards,
"""

signature-delim

The email signature delimiter of the user signature. Defaults to -- \n.

signature-delim = "~~ \n"

backend

Default backend used for all the features like adding folders, listing envelopes or copying messages.

# valid backends: maildir, imap, notmuch
backend = "imap"

Check up account

$ himalaya account check-up [OPTIONS] [ACCOUNT]

Check up the given account (or the default one if omitted).

This command performs a checkup of the given account. It checks if the configuration is valid, if backend can be created and if sessions work as expected.

Configure account

$ himalaya account configure [OPTIONS] <ACCOUNT>

Configure interactively the current selected account. For example, it can prompt the IMAP password, the IMAP OAuth 2.0 client secret etc.

Options

-r|--reset

Reset the configuration, which means you may be prompted again for passwords or secrets.

List accounts

$ himalaya account list [OPTIONS]

Lists all accounts defined in your configuration file. 3 properties are displayed:

  • name: the name of the account (the TOML table section)
  • backends: the list of all backend used for all features
  • default: represents the defaultness of the account (“yes” if the option default = true is set, “no” otherwise)

Options

-w|--max-width

The maximum width the table should not exceed.

This argument will force the table not to exceed the given width in pixels. Columns may shrink with ellipsis in order to fit the width.

Synchronize an account

$ himalaya account sync [OPTIONS] [ACCOUNT]

Synchronizes folders and emails of the given account (or the default one if omitted) locally, on your filesystem, for an offline usage of the CLI.

Disclaimer: this feature is still in beta, we recommand you to backup your emails before using it. Do not use in production before the final v1.0.0.

Since the v0.7.0, you can synchronize your folders and your emails locally. To enable this feature, add the following entry in the configuration of the account you want to synchronize:

[accounts.example]
sync.enable = true

By default, Himalaya stores your emails at $XDG_DATA_HOME/pimalaya/email/sync/<account-name>-cache using the Maildir++ format. The location can be customized with the sync.dir option:

[accounts.example]
sync.enable = true
sync.dir = "~/.Mail/my-account-name"

Himalaya also stores 2 lightweight Maildir at $XDG_CACHE_HOME/pimalaya/email/sync/<hash> which contains the previous state of every local and remote envelopes. This way Himalaya tries to guess which side (local or remote) needs to be updated. In case of conflict, Himalaya takes the solution that does not loose any data. For instance: if an envelope exists in the local Maildir and in the local cache, but not remotely nor in the remote cache, we cannot determine if an email has been added locally or removed remotely. In this case, Himalaya will consider that the email has been added locally in order not to loose data.

Warning: if you want to restart the synchronization from scratch, make sure to delete all data and cache folders, otherwise Himalaya may consider that emails have been removed locally and needs to be removed remotely, which would lead to a complete wipeout of your data!.

Options

-d|--dry-run

Run the synchronization without applying any changes.

Instead, a report will be printed to stdout containing all the changes the synchronization plan to do.

-F|--include-folder

Synchronize only specific folders (can be repeated).

Only the given folders will be synchronized (including associated envelopes and messages). Useful when you need to speed up the synchronization process. A good usecase is to synchronize only the INBOX in order to quickly check for new messages.

Overrides the config option sync.strategy.

-x|--exclude-folder

Omit specific folders from the synchronization.

The given folders will be excluded from the synchronization (including associated envelopes and messages). Useful when you have heavy folders that you do not want to take care of, or to speed up the synchronization process.

Overrides the config option sync.strategy.

-A|--all-folders

Synchronizes all existing folders.

Settings

sync.enable

Enable the synchronization for the current account.

Enabling the synchronization allows you to run the command account sync <account-name>, which synchronizes all folders and its associated emails to a local Maildir. All other commands also operate on this Maildir backend rather than the default one, which makes your account usable even offline.

sync.enable = true

sync.dir

Customize the root directory where the Maildir cache is saved.

Defaults to $XDG_DATA_HOME/pimalaya/email/sync/<account-name>.

sync.dir = "~/.local/share/himalaya/custom"

folder.sync.filter

Use the given strategy to synchronize folders:

  • folder.sync.filter = "all" (default): Synchronizes all folders.

  • folder.sync.filter.include = ["INBOX", "Sent"]: Synchronizes only folders matching the given names.

  • folder.sync.filter.exclude = ["Trash"]: Synchronizes all folders except the ones matching the given names.

Folders

structure

A folder (as known as mailbox, or directory) contains one or more emails. Folders can be managed with those commands:

Settings

folder.alias(es)

Define custom folder aliases.

Aliases are resolved when calling backend features. There are 4 special aliases that can be used by the lib, for example when saving a copy of a sent message to the sent folder:

  • inbox: main folder containing incoming messages

  • draft(s): folder containing draft messages

  • sent: folder containing sent messages

  • trash: folder containing trashed messages

folder.alias.inbox = "INBOX"
folder.alias.drafts = "[Gmail]/Drafts"
folder.alias.sent = "Envoyés"
folder.alias.trash = "Deleted"
folder.alias.work = "Archives.Work"

Create a folder

$ himalaya folder create [OPTIONS] <FOLDER>

This command allows you to create a new folder using the given name.

Options

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

folder.create.backend

Override the backend used for creating folders.

# valid backends: maildir, imap, notmuch
folder.create.backend = "imap"

List folders

$ himalaya folder list [OPTIONS]

Lists all folders of the given account (via the global option -a|--account, or the default one if omitted). 2 properties are displayed:

  • name: the name of the folder
  • desc: the description of the folder

Options

-w|--max-width

The maximum width the table should not exceed.

This argument will force the table not to exceed the given width in pixels. Columns may shrink with ellipsis in order to fit the width.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

folder.list.backend

Override the backend used for listing folders.

# valid backends: maildir, imap, notmuch
folder.list.backend = "imap"

Example

$ himalaya folder list --disable-cache --account posteo
NAME              │DESC                 
Junk              │\HasNoChildren, Junk 
Archives          │\HasChildren         
Archives.FOSS     │\HasNoChildren       
Trash             │\HasNoChildren       
Notes             │\HasNoChildren       
Drafts            │\HasNoChildren       
Sent              │\HasNoChildren       
INBOX             │\HasNoChildren       

Expunge a folder

$ himalaya folder expunge [OPTIONS] <FOLDER>

The concept of expunging is similar to the IMAP one: it definitely deletes emails from the given folder that contain the “deleted” flag.

Options

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

folder.expunge.backend

Override the backend used for expunging folders.

# valid backends: maildir, imap, notmuch
folder.expunge.backend = "imap"

Purge a folder

$ himalaya folder purge [OPTIONS] <FOLDER>

All emails from the given folder are definitely deleted. The purged folder will remain empty after execution of the command.

Options

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

folder.purge.backend

Override the backend used for purging folders.

# valid backends: maildir, imap, notmuch
folder.purge.backend = "imap"

Delete a folder

$ himalaya folder delete [OPTIONS] <FOLDER>

All emails from the given folder are definitely deleted. The folder is also deleted after execution of the command.

Options

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

folder.delete.backend

Override the backend used for deleting folders.

# valid backends: maildir, imap, notmuch
folder.delete.backend = "imap"

Envelopes

structure

An envelope is a small representation of a message. It contains an identifier (given by the backend), some flags as well as few headers from the message itself. Folders can be managed with those commands:

List, filter and sort envelopes

$ himalaya envelope list [OPTIONS] [QUERY]...

Lists envelopes included in the given folder (defaults to INBOX), and filter/sort them according to the given query. 5 properties are displayed:

  • id: the identifier of the envelope
  • flags: the flags associated to the envelope
  • subject: the subject from the message headers
  • from: the first sender from the message headers
  • to: the first recipient from the message headers
  • date: the date from the message headers

Query

The query allows you to filter and/or sort envelopes. It can be composed of a filter query, a sort query or both at the same time.

See the ABNF grammar for more detailed information (advanced).

Filter query

A filter query is composed of operators and conditions.

There is 3 operators:

  • not <condition>: filter envelopes that do not match the condition
  • <condition> and <condition>: filter envelopes that match both conditions
  • <condition> or <condition>: filter envelopes that match one of the conditions

And there is 8 conditions:

  • date <yyyy-mm-dd>: filter envelopes that match the given date
  • before <yyyy-mm-dd>: filter envelopes with date strictly before the given one
  • after <yyyy-mm-dd>: filter envelopes with date stricly after the given one
  • from <pattern>: filter envelopes with senders matching the given pattern
  • to <pattern>: filter envelopes with recipients matching the given pattern
  • subject <pattern>: filter envelopes with subject matching the given pattern
  • body <pattern>: filter envelopes with text bodies matching the given pattern
  • flag <flag>: filter envelopes matching the given flag

Sort query

A sort query starts by order by, and is composed of kinds and orders.

There is 4 kinds:

  • date [order]: sort envelopes by date
  • from [order]: sort envelopes by sender
  • to [order]: sort envelopes by recipient
  • subject [order]: sort envelopes by subject

Note: the order can be omitted. If so, the ascending order is used by default.

And there is 2 orders:

  • <kind> asc: sort envelopes by the given kind in ascending order
  • <kind> desc: sort envelopes by the given kind in descending order

Options

-f|--folder

The folder name.

Defaults to INBOX.

-p|--page

The page number.

The page number starts from 1 (which is the default). Giving a page number to big will result in a out of bound error.

-s|--page-size

The page size.

Determine the amount of envelopes a page should contain.

Note: a page size at 0 means no pagination.

-w|--max-width

The maximum width the table should not exceed.

This argument will force the table not to exceed the given width in pixels. Columns may shrink with ellipsis in order to fit the width.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

envelope.list.backend

Override the backend used for listing envelopes.

# valid backends: maildir, imap, notmuch
envelope.list.backend = "imap"

envelope.list.page-size

Define the size of a page when listing envelopes.

A page size of 0 disables the pagination and shows all available envelopes.

envelope.list.page-size = 10

envelope.list.datetime-fmt

Customize the format for displaying envelopes date.

See chrono::format::strftime for supported formats. Defaults to "%F %R%:z" (eg: 2023-05-04 07:49-07:00).

envelope.list.datetime-fmt = "%d-%m-%Y, %R"

envelope.list.datetime-local-tz

Transform envelopes date timezone into the user’s local one.

For example, if the user’s local timezone is UTC, the envelope date 2023-06-15T09:00:00+02:00 becomes 2023-06-15T07:00:00-00:00.

envelope.list.datetime-local-tz = true

Examples

$ himalaya envelope list --disable-cache --account posteo Archives.FOSS
ID  │FLAGS │SUBJECT                                    │FROM               │DATE                   
937 │      │~soywod/pimalaya#161: TOML parse error: m… │~Phil Crockett     │2023-12-22 15:12+00:00 
938 │      │Re: [dantecatalfamo/himalaya-emacs] Prepa… │Dante Catalfamo    │2023-12-20 23:21-08:00 
939 │      │Re: Short question                         │michiel@nlnet.nl   │2023-12-20 17:39+01:00 
940 │      │Update and important request: EC evaluati… │Michiel Leenaars   │2023-12-20 12:44+00:00 
941 │      │Re: Short question                         │michiel@nlnet.nl   │2023-12-20 12:23+01:00 
942 │      │Short question                             │michiel@nlnet.nl   │2023-12-20 09:40+01:00 
943 │      │Request for payment for 2023-04-034: Pima… │dashboard@nlnet.nl │2023-12-18 13:20+00:00 
944 │      │Re: [TornaxO7/rfc2047-decoder] InvalidByt… │TornaxO7           │2023-12-17 05:55-08:00 
945 │      │Re: [TornaxO7/rfc2047-decoder] InvalidByt… │TornaxO7           │2023-12-17 05:55-08:00 
946 │      │Please confirm the RfP for 2023-04-034: P… │dashboard@nlnet.nl │2023-12-14 23:24+00:00 
$ himalaya envelope list from michiel or from nlnet order by date desc
ID  │FLAGS │SUBJECT                                    │FROM               │DATE                   
939 │      │Re: Short question                         │michiel@nlnet.nl   │2023-12-20 17:39+01:00 
940 │      │Update and important request: EC evaluati… │Michiel Leenaars   │2023-12-20 12:44+00:00 
941 │      │Re: Short question                         │michiel@nlnet.nl   │2023-12-20 12:23+01:00 
942 │      │Short question                             │michiel@nlnet.nl   │2023-12-20 09:40+01:00 
943 │      │Request for payment for 2023-04-034: Pima… │dashboard@nlnet.nl │2023-12-18 13:20+00:00 
946 │      │Please confirm the RfP for 2023-04-034: P… │dashboard@nlnet.nl │2023-12-14 23:24+00:00 

Watch for envelopes changes

$ himalaya envelope watch [OPTIONS] [FOLDER]

Watches the given folder (defaults to INBOX) and executes hooks when changes occur on envelopes.

If synchronization is enabled, the command will watch local cached folders. To force the command to watch remote folders, you can either:

  1. Force the remote backend for the watch envelopes feature, for example:

    envelope.watch.backend = "imap"
    
  2. Disable the cache with the --disable-cache flag:

    $ himalaya envelope watch --disable-cache
    

Options

-f|--folder

The name of the folder. Defaults to INBOX.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

envelope.watch.{event}.{hook}

Configure the hook to execute when receiving a specific watch event.

Possible values of event:

  • envelope.watch.received.{hook}: trigger the hook when receiving a new envelope

  • envelope.watch.any.{hook}: trigger the hook for any other event

Possible values of hook:

  • envelope.watch.{event}.cmd: trigger the given shell command

  • envelope.watch.{event}.notify: send a system notification

    • envelope.watch.{event}.notify.summary: customize the summary (title) of the notification

    • envelope.watch.{event}.notify.body: customize the body (content) of the notification

    Both summary and body accept placeholders that will be replaced at runtime:

    • {id}: the envelope id

    • {subject}: the envelope subject

    • {sender}: the sender name or his email address

    • {sender.name}: the sender name or unknown

    • {sender.address}: the sender email address

    • {recipient}: the recipient name or his email address

    • {recipient.name}: the recipient name or unknown

    • {recipient.address}: the recipient email address

envelope.watch.received.notify.summary = "📬 New message from {sender}"
envelope.watch.received.notify.body = "{subject}"

envelope.watch.any.cmd = "mbsync -a"

Note: it is possible to cumulate hooks for a same event. For example it is possible to send a system notification and execute a command when receiving a new envelope.

Flags

structure

A flag is a tag associated to an envelope. Existing flags are seen, answered, flagged, deleted, draft. Other flags are considered custom, which are not always supported (the synchronization does not take care of them yet). Flags can be managed with those commands:

Add flags

$ himalaya flag add [OPTIONS] <ID-OR-FLAG>...

This command allows you to attach the given flag(s) to the given envelope(s).

Options

-f|--folder

The name of the folder.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

flag.add.backend

Override the backend used for adding flags.

# valid backends: maildir, imap, notmuch
flag.add.backend = "imap"

Set flags

$ himalaya flag set [OPTIONS] <ID-OR-FLAG>...

This command allows you to replace existing flags of the given envelope(s) with the given flag(s).

Options

-f|--folder

The name of the folder.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

flag.set.backend

Override the backend used for setting flags.

# valid backends: maildir, imap, notmuch
flag.set.backend = "imap"

Remove flags

$ himalaya flag remove [OPTIONS] <ID-OR-FLAG>...

This command allows you to remove the given flag(s) from the given envelope(s).

Options

-f|--folder

The name of the folder.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

flag.remove.backend

Override the backend used for removing flags.

# valid backends: maildir, imap, notmuch
flag.remove.backend = "imap"

Messages

structure

A message is the content of an email. It is composed of headers (located at the top of the message) and a body (located at the bottom of the message). Both are separated by two new lines. Messages can be managed with those commands:

Read a message

$ himalaya message read [OPTIONS] <ID>...

Reads message(s) matching the given envelope id(s).

Note: when reading message(s), the seen flag is automatically applied to the corresponding envelope(s). To prevent this behaviour, use the --preview flag instead.

Options

-f|--folder

The name of the folder.

-p|--preview

Read the message without applying the “seen” flag to its corresponding envelope.

-r|--raw

Read only body of text/html parts.

This argument is useful when you need to read the HTML version of a message. Combined with --no-headers, you can write it to a .html file and open it with your favourite browser.

--no-headers

Read only the body of the message.

All headers will be removed from the message.

-H|--header

Prefill the template with custom headers (can be repeated).

A raw header should follow the pattern KEY:VAL.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

message.read.backend

Override the backend used for reading messages.

# valid backends: maildir, imap, notmuch
message.read.backend = "imap"

message.read.headers

Define visible headers at the top of messages when reading them.

message.read.headers = ["Date", "From", "To", "Subject"]

message.read.format

Define the text/plain format as defined in the RFC 2646.

# The content should fit its container (default).
message.read.format = "auto"

# The content should not be restricted.
message.read.format = "flowed"

# The content should fit in a fixed amount of pixels.
message.read.format.fixed = 80

Example

$ himalaya message read --disable-cache --account posteo --folder Archives.FOSS 944
From: ~matf <outgoing@sr.ht>
To: soywod <clement.douin@posteo.net>
Subject: ~soywod/pimalaya#154: Configuration wizard: cannot canonicalize path

I built `himalaya` from sources using the `cargo` instructions in the documentation, then followed the configuration wizard (it's nice), but unfortunately it seems unable to save the `config.toml`:

✘ cannot canonicalize path "/home/droidian/.config/himalaya/config.toml"
? Where would you like to save your configuration? (/home/droidian/.config/himalaya/config.toml) ›  

The same happens whether I `mkdir -p ~/.config/himalaya` or not.

Any ideas? This is on aarch64.


-- 
View on the web: https://todo.sr.ht/~soywod/pimalaya/154

Write a new message

$ himalaya message write [OPTIONS] [BODY]...

Writes a new message by editing a MML template. A template is a pseudo-message following this format:

Header1: val1
Header2: val2
Header3: val3
…

Body

Headers are located at the top of the template, whereas the body is located at the bottom of the template. Headers and body need to be separated by an empty new line.

Headers

Templates accept 8 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 message
  • Subject: represents the subject of the message
  • From: represents the address of the sender
  • To: represents the addresses of the receivers
  • Reply-To: represents the address the receiver should reply to instead of the From header
  • Cc: 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:

  • a single email address user@domain
  • a named address Name <user@domain>
  • a quoted named address "Name" <user@domain>

Multiple address are separated by a coma ,: user@domain, Name <user@domain>, "Name" <user@domain>.

Body

Templates bodies can be simple strings. During the compilation they are transformed into text/plain parts. So writing a template can be as simple as:

From: alice@localhost
To: Bob <bob@localhost>
Subject: Hello from Himalaya

Hello, world!

Templates bodies can also be written in MIME Meta Language, see the templates section for more information about the syntax.

Edition

Templates are edited using your default editor (the one specified in the $EDITOR environment variable).

Once the editor exited, the following actions will be prompted:

(s)end, (e)dit, (l)ocal/(r)emote draft or (d)iscard?
  • s compiles the template then sends the message
  • e reopens your editor with the template
  • l saves the template locally
  • r saves the template remotely (in the draft folder)
  • d discards the template

Options

-H|--header

Prefill the template with custom headers (can be repeated).

A raw header should follow the pattern KEY:VAL.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

message.write.backend

Override the backend used for writing messages.

# valid backends: maildir, imap, notmuch
message.write.backend = "imap"

message.write.headers

Define visible headers at the top of messages when writing them (new/reply/forward).

message.write.headers = ["Date", "From", "To", "Subject"]

Reply to a message

$ himalaya message reply [OPTIONS] <ID> [BODY]...

This command allows you to reply to the given message using the editor defined in your environment variable $EDITOR. When the edition process finishes, you can choose between saving or sending the final message.

Options

-f|--folder

The name of the folder.

-A|--all

Reply to all recipients.

This argument will add all recipients for the To and Cc headers.

-H|--header

Prefill the template with custom headers (can be repeated).

A raw header should follow the pattern KEY:VAL.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

message.write.backend

Override the backend used for writing messages.

# valid backends: maildir, imap, notmuch
message.write.backend = "imap"

message.write.headers

Define visible headers at the top of messages when writing them (new/reply/forward).

message.write.headers = ["Date", "From", "To", "Subject"]

Forward a message

$ himalaya message forward [OPTIONS] <ID> [BODY]...

This command allows you to forward the given message using the editor defined in your environment variable $EDITOR. When the edition process finishes, you can choose between saving or sending the final message.

Options

-f|--folder

The name of the folder.

-H|--header

Prefill the template with custom headers.

A raw header should follow the pattern KEY:VAL.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

message.write.backend

Override the backend used for writing messages.

# valid backends: maildir, imap, notmuch
message.write.backend = "imap"

message.write.headers

Define visible headers at the top of messages when writing them (new/reply/forward).

message.write.headers = ["Date", "From", "To", "Subject"]

Mailto

$ himalaya message mailto [OPTIONS] <URL>

Parse and edit a message from a mailto URL string.

This command allows you to edit a message from the mailto format using the editor defined in your environment variable $EDITOR. When the edition process finishes, you can choose between saving or sending the final message.

Options

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Save a message

$ himalaya message save [OPTIONS] [MESSAGE]...

This command allows you to add a raw message to the given folder.

Options

-f|--folder

The name of the folder.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Examples

$ cat /tmp/email.eml | himalaya message save
$ himalaya message save < /tmp/email.eml
$ himalaya message save 'From: alice@localhost
To: bob@localhost
Subject: Hello

Hello, world!'

Send a message

$ himalaya message send [OPTIONS] [MESSAGE]...

This command allows you to send a raw message and to save a copy to your send folder.

The raw message can be send either as a regular argument or using standard input (pipe or redirection).

Options

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

message.send.backend

Override the backend used for sending messages.

# valid backends: smtp, sendmail
message.send.backend = "smtp"

message.send.save-copy

Should save a copy to the sent folder of the message being sent.

message.send.save-copy = true

message.send.pre-hook

The hook called just before sending a message.

The command should take a raw message as standard input (stdin) and returns the modified raw message to the standard output (stdout).

message.send.pre-hook = "process-markdown.sh"

Example

$ cat /tmp/email.eml | himalaya message send
$ himalaya message send < /tmp/email.eml
$ himalaya message send 'From: alice@localhost
To: bob@localhost
Subject: Hello

Hello, world!'

Copy a message

$ himalaya message copy [OPTIONS] <FROM> <TO> <ID>...

Copy a message from a source folder to a target folder.

Options

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

message.copy.backend

Override the backend used for copying messages.

# valid backends: maildir, imap, notmuch
message.copy.backend = "imap"

Move a message

$ himalaya message move [OPTIONS] <FROM> <TO> <ID>...

Move a message from a source folder to a target folder.

Options

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

message.move.backend

Override the backend used for moving messages.

# valid backends: maildir, imap, notmuch
message.move.backend = "imap"

Delete a message

$ himalaya message delete [OPTIONS] <ID>...

Mark as deleted a message from a folder.

This command does not really delete the message: if the given folder points to the trash folder, it adds the “deleted” flag to its envelope, otherwise it moves it to the trash folder. Only the expunge folder command truly deletes messages.

Options

-f|--folder

The name of the folder.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

message.delete.style

Override the message deletion style.

Message deletion can be performed either by moving messages to the Trash folder or by adding the Deleted flag to their respective envelopes.

# valid style: folder, flag
message.delete.style = "folder"

Attachments

structure

An attachment is a MIME part where either:

  • The Content-Disposition header is attachment
  • The Content-Disposition header is inline with a filename parameter defined.

All other parts (inline without filename, form data, extensions etc) are not considered attachments.

Attachments can be managed with those commands:

Download attachments

$ himalaya attachment download [OPTIONS] <ID>...

Downloads all attachments found in message(s) matching the given envelope id(s) to your downloads directory.

Options

-f|--folder

The name of the folder.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Settings

downloads-dir

The downloads directory.

It is mostly used for downloading messages attachments. Defaults to the system temporary directory (usually /tmp).

downloads-dir = "~/Downloads"

Templates

structure

A template is a simplified representation of a message based on the MIME Meta Language. Templates allow you to add multiple parts to a message (including binary attachments like images or PDFs) from the body itself, using a simple XML-based language. A template looks like this:

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>

and is compiled into a valid 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 here.

Templates can be managed with those commands:

Generate a new template

$ himalaya template write [OPTIONS] [BODY]...

Generate a template for writing a new message from scratch.

The generated template is prefilled with your email address in a From header as well as your signature.

Options

-H|--header

Prefill the template with custom headers (can be repeated).

A raw header should follow the pattern KEY:VAL.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Generate a reply template

$ himalaya template reply [OPTIONS] <ID> [BODY]...

Generate a template for replying to a message.

The generated template is prefilled with your email in a From header as well as your signature. The replied message is also prefilled in the body of the template, with all lines prefixed by the symbol greater than “>”.

Options

-f|--folder

The name of the folder.

-A|--all

Reply to all recipients.

This argument will add all recipients for the To and Cc headers.

-H|--header

Prefill the template with custom headers (can be repeated).

A raw header should follow the pattern KEY:VAL.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Generate a forward template

$ himalaya template forward [OPTIONS] <ID> [BODY]...

Generate a template for forwarding a message.

The generated template is prefilled with your email in a From header as well as your signature. The forwarded message is also prefilled in the body of the template, prefixed by a separator.

Options

-f|--folder

The name of the folder.

-H|--header

Prefill the template with custom headers (can be repeated).

A raw header should follow the pattern KEY:VAL.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Save a template

$ himalaya template save [OPTIONS] [TEMPLATE]...

Save a template to a folder.

This command allows you to save a template to the given folder. The template is compiled into a MIME message before being saved to the folder. If you want to save a raw message, use the message save command instead.

Options

-f|--folder

The name of the folder.

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Examples

$ cat ~/email.eml | himalaya template save --folder Archives
$ himalaya template save --folder Archives < ~/email.eml

Send a template

$ himalaya template send [OPTIONS] [TEMPLATE]...

This command allows you to send a template and save a copy to the sent folder. The template is compiled into a MIME message before being sent. If you want to send a raw message, use the message send command instead.

Options

--disable-cache

Disable any sort of cache.

The action depends on commands it apply on. For example, when listing envelopes using the IMAP backend, this flag will ensure that envelopes are fetched from the IMAP server rather than the synchronized local Maildir.

-a|--account

Override the default account.

An account name corresponds to an entry in the table at the root level of your TOML configuration file.

Examples

$ cat ~/email.eml | himalaya template send
$ himalaya template send < ~/email.eml

IMAP configuration

imap.host (required)

Represents the IMAP server hostname.

imap.port (required)

Represents the IMAP server port.

imap.login (required)

Represents the IMAP account login.

imap.passwd/oauth2 (required)

The IMAP account authentication mechanism:

  • imap.passwd: Regular password authentication.

    • imap.passwd.raw: Raw password (unsafe, not recommanded). [string]

    • imap.passwd.cmd: Password retrieved from the given shell command. [string]

    • imap.passwd.keyring: Password retrieved from your system’s default password manager at the given entry. [string]

  • imap.oauth2: OAuth 2.0 authorization mechanism. This mechanism requires additional options:

    • imap.oauth2.client-id (required): Client identifier issued to the client during the registration process described by Section 2.2. [string]

    • imap.oauth2.auth-url (required): URL of the authorization server’s authorization endpoint. [string]

    • imap.oauth2.token-url (required): URL of the authorization server’s token endpoint. [string]

    • imap.oauth2.method: OAuth 2.0 authentication method. Default: XOAUTH. [XOAUTH|OAUTHBEARER]

    • imap.oauth2.client-secret: Override how the client secret is retrieved:

      • imap.oauth2.client-secret.raw: Raw client secret (unsafe, not recommanded). [string]

      • imap.oauth2.client-secret.cmd: Client secret retrieved from the given shell command. [string]

      • imap.oauth2.client-secret.keyring: Client secret retrieved from your system’s default password manager at the given entry. [string]

      If omitted, the client secret is retrieves from your system’s default password manager at the entry <account-name>-imap.oauth2-client-secret.

    • imap.oauth2.access-token: Override how the access token is retrieved:

      • imap.oauth2.access-token.raw: Raw access token (for debugging purpose). [string]

      • imap.oauth2.access-token.cmd: Access token retrieved from the given shell command. [string]

      • imap.oauth2.access-token.keyring: Access token retrieved from your system’s default password manager at the given entry. [string]

      If omitted, the access token is retrieves from your system’s default password manager at the entry <account-name>-imap.oauth2-access-token.

    • imap.oauth2.refresh-token: Override how the refresh token is retrieved:

      • imap.oauth2.refresh-token.raw: Raw refresh token (for debugging purpose). [string]

      • imap.oauth2.refresh-token.cmd: Refresh token retrieved from the given shell command. [string]

      • imap.oauth2.refresh-token.keyring: Refresh token retrieved from your system’s default password manager at the given entry. [string]

      If omitted, the refresh token is retrieves from your system’s default password manager at the entry <account-name>-imap.oauth2-refresh-token.

    • imap.oauth2.pkce: Enable the Proof Key of Code Exchange. [bool]

    • imap.oauth2.scope: Access token scope, as defined by the authorization server. Variants possible:

      • imap.oauth2.scope: One scope. [string]

      • imap.oauth2.scopes: One or more scopes. [list[string]]

imap.encryption

The IMAP encryption protocol to use.

  • imap.encryption = "tls" | true (default): use required encryption (SSL/TLS).

  • imap.encryption = "start-tls": use opportunistic encryption (StartTLS).

  • imap.encryption = "none" | false: do not use any encryption.

imap.watch.timeout

Customize the timeout used to refresh the IMAP IDLE command in background.

Defaults to 29 min as defined in the RFC.

Examples

backend = "imap"

imap.host = "imap.localhost"
imap.port = 993
imap.login = "test@localhost"
imap.encryption = "tls"
imap.auth = "passwd"
# you can use directly your password from the config (unsafe, not recommanded):
imap.passwd.raw = "<your-password>"
# you can retrieve your app password via a shell command:
imap.passwd.cmd = "pass show my-account"
# supports pipelines:
imap.passwd.cmd = ["pass show my-account", "head -1"]
# you can also use the keyring system and override the entry name:
imap.passwd.keyring = "my-account-imap.passwd"
backend = "imap"

imap.host = "imap.localhost"
imap.port = 993
imap.login = "test@localhost"
imap.auth = "oauth2"
imap.oauth2.client-id = "my-oauth2-client-id"
imap.oauth2.auth-url = "http://localhost/oauth2/auth"
imap.oauth2.token-url = "http://localhost/oauth2/token"
imap.oauth2.pkce = true
imap.oauth2.scope = "all"
imap.encryption = true

Maildir configuration

maildir.root-dir (required)

The Maildir root directory.

The path should point to the root level of the Maildir directory (the one containing the cur, new and tmp folders). Path is shell-expanded, which means environment variables and tilde ~ are replaced by their values.

Note: with the Maildir backend, the folder.alias option can contain path to other Maildir folders. For example, if your inbox is located at /my/maildir and your sent folder at /my/maildir/sent, then you can set up this kind of alias:

maildir.root-dir = "/my/maildir"

folder.alias.inbox = "/my/maildir"
folder.alias.sent = "/my/maildir/sent"

Notmuch configuration

To activate this backend, you need to:

  1. Compile himalaya from sources with the notmuch feature enabled:
$ cargo install --features notmuch himalaya
  1. Have the libnotmuch available on your system.

notmuch.database-path

The path to the Notmuch database.

The path should point to the root directory containing the Notmuch database (usually the root Maildir directory). Path is shell-expanded, which means environment variables and tilde ~ are replaced by their values. Defaults to the default Notmuch database location if omitted.

notmuch.maildir-path

Override the default path to the Maildir folder.

Path is shell-expanded, which means environment variables and tilde ~ are replaced by their values. Defaults to database_path if omitted.

notmuch.config-path

Override the default Notmuch configuration file path.

Path is shell-expanded, which means environment variables and tilde ~ are replaced by their values.

notmuch.profile

Override the default Notmuch profile name.

SMTP configuration

smtp.host (required)

Represents the SMTP server hostname.

smtp.port (required)

Represents the SMTP server port.

smtp.login (required)

Represents the SMTP account login.

smtp.passwd/oauth2 (required)

The SMTP account authentication mechanism:

  • smtp.passwd: Regular password authentication.

    • smtp.passwd.raw: Raw password (unsafe, not recommanded). [string]

    • smtp.passwd.cmd: Password retrieved from the given shell command. [string]

    • smtp.passwd.keyring: Password retrieved from your system’s default password manager at the given entry. [string]

  • smtp.oauth2: OAuth 2.0 authorization mechanism. This mechanism requires additional options:

    • smtp.oauth2.client-id (required): Client identifier issued to the client during the registration process described by [Section 2.2]. [string]

    • smtp.oauth2.auth-url (required): URL of the authorization server’s authorization endpoint. [string]

    • smtp.oauth2.token-url (required): URL of the authorization server’s token endpoint. [string]

    • smtp.oauth2.method: OAuth 2.0 authentication method. Default: XOAUTH. [XOAUTH|OAUTHBEARER]

    • smtp.oauth2.client-secret: Override how the client secret is retrieved:

      • smtp.oauth2.client-secret.raw: Raw client secret (unsafe, not recommanded). [string]

      • smtp.oauth2.client-secret.cmd: Client secret retrieved from the given shell command. [string]

      • smtp.oauth2.client-secret.keyring: Client secret retrieved from your system’s default password manager at the given entry. [string]

      If omitted, the client secret is retrieves from your system’s default password manager at the entry <account-name>-smtp.oauth2-client-secret.

    • smtp.oauth2.access-token: Override how the access token is retrieved:

      • smtp.oauth2.access-token.raw: Raw access token (for debugging purpose). [string]

      • smtp.oauth2.access-token.cmd: Access token retrieved from the given shell command. [string]

      • smtp.oauth2.access-token.keyring: Access token retrieved from your system’s default password manager at the given entry. [string]

      If omitted, the access token is retrieves from your system’s default password manager at the entry <account-name>-smtp.oauth2-access-token.

    • smtp.oauth2.refresh-token: Override how the refresh token is retrieved:

      • smtp.oauth2.refresh-token.raw: Raw refresh token (for debugging purpose). [string]

      • smtp.oauth2.refresh-token.cmd: Refresh token retrieved from the given shell command. [string]

      • smtp.oauth2.refresh-token.keyring: Refresh token retrieved from your system’s default password manager at the given entry. [string]

      If omitted, the refresh token is retrieves from your system’s default password manager at the entry <account-name>-smtp.oauth2-refresh-token.

    • smtp.oauth2.pkce: Enable the Proof Key of Code Exchange. [bool]

    • smtp.oauth2.scope: Access token scope, as defined by the authorization server. Variants possible:

      • smtp.oauth2.scope: One scope. [string]

      • smtp.oauth2.scopes: One or more scopes. [list[string]]

smtp.encryption

The SMTP encryption protocol to use.

  • smtp.encryption = "tls" | true (default): use required encryption (SSL/TLS).

  • smtp.encryption = "start-tls": use opportunistic encryption (StartTLS).

  • smtp.encryption = "none" | false: do not use any encryption.

Example

message.send.backend = "smtp"

smtp.host = "smtp.localhost"
smtp.port = 465
smtp.login = "test@localhost"
smtp.passwd.raw = "my-unsafe-password"
smtp.encryption = "tls"
message.send.backend = "smtp"

smtp.host = "smtp.localhost"
smtp.port = 587
smtp.login = "test@localhost"
smtp.oauth2-client-id = "my-oauth2-client-id"
smtp.oauth2-auth-url = "http://localhost/oauth2/auth"
smtp.oauth2-token-url = "http://localhost/oauth2/token"
smtp.oauth2-pkce = true
smtp.oauth2-scopes = ["read", "write"]
smtp.encryption = "start-tls"

Sendmail configuration

sendmail.cmd (required)

Represents the shell command used to send emails.

sendmail.cmd = "/usr/sbin/sendmail"

PGP configuration

pgp.backend (required)

Customize the PGP backend:

  • pgp.backend = "cmds": Use the PGP backend based on shell commands.

    Note: Himalaya needs to be compiled with the cargo feature pgp-commands to activate this backend.

  • pgp.backend = "gpg": Use the PGP backend based on GPG.

    Note: Himalaya needs to be compiled with the cargo feature pgp-gpg to activate this backend.

    Note: the gpgme lib needs to be available on the system for this backend to work.

  • pgp.backend = "native": Use the native PGP backend.

    The native PGP backend is using rPGP, a Rust implementation of the OpenPGP standard.

    Note: Himalaya needs to be compiled with the cargo feature pgp-native to activate this backend.

Commands-based PGP configuration

Note: Himalaya needs to be compiled with the cargo feature pgp-commands to activate this backend.

pgp.backend = "gpg"

Enables the PGP backend based on the shell commands.

pgp.encrypt-cmd

Represents the shell command used to encrypt email parts.

Defaults to gpg --encrypt --quiet --armor <recipients>, where <recipients> is the placeholder for recipients’ email. See also pgp.encrypt-recipient-fmt and pgp.encrypt-recipients-sep.

pgp.encrypt-recipient-fmt

Represents the template string used to format <recipients> from pgp.encrypt-cmd. [string]

Defaults to --recipient <recipient>, where <recipient> is the placeholder for a recipient’s email.

pgp.encrypt-recipients-sep

Represents the separator used to concatenate all pgp.encrypt-recipient-fmt. [string]

Defaults to (space).

pgp.decrypt-cmd

Represents the shell command used to decrypt email parts. [string]

The encrypted email part is send using stdin. Defaults to gpg --decrypt --quiet.

pgp.sign-cmd

Represents the shell command used to sign email parts. [string]

The email part to sign is send using stdin. Defaults to gpg --sign --quiet --armor.

pgp.verify-cmd

Represents the shell command used to verify email parts. [string]

The signed part is send using stdin. Defaults to gpg --verify --quiet.

Examples

[my-account]
pgp.backend = "cmds"
pgp.encrypt-cmd = "gpg --encrypt --quiet --armor <recipients>"
pgp.decrypt-cmd = "gpg --decrypt --quiet"
pgp.sign-cmd = "gpg --sign --quiet --armor"
pgp.verify-cmd = "gpg --verify --quiet"
[my-account.pgp]
backend = "commands" # alias for cmds
encrypt-cmd = "gpg --encrypt --quiet --armor <recipients>"
decrypt-cmd = "gpg --decrypt --quiet"
sign-cmd = "gpg --sign --quiet --armor"
verify-cmd = "gpg --verify --quiet"

GPG configuration

Note: Himalaya needs to be compiled with the cargo feature pgp-gpg to activate this backend.

Note: the gpgme lib needs to be available on the system for this backend to work.

pgp.backend = "gpg"

Enables the PGP backend based on the gpgme library.

Examples

[my-account]
pgp.backend = "gpg"
[my-account.pgp]
backend = "gpg"

Native PGP configuration

Note: Himalaya needs to be compiled with the cargo feature pgp-native to activate this backend.

pgp.backend = "native"

Enable the Rust native PGP backend.

pgp.secret-key

Represents the PGP secret key in its ASCII armored version.

# The secret key is located at the given path
pgp.secret-key.path = "/tmp/secret.key"

# The secret key is located in the user's global keyring at the given entry.
pgp.secret-key.keyring = "secret-entry"

This field is configured via himalaya account configure.

pgp.secret-key-passphrase

Represents the secret key passphrase.

# Raw passphrase (unsafe, not recommanded)
pgp.secret-key-passphrase.raw = "passphrase"

# Passphrase retrieved from the given shell command
pgp.secret-key-passphrase.cmd = "pass show passphrase"

# Passphrase retrieved from your system's default password manager at the given entry.
pgp.secret-key-passphrase.keyring = "passphrase-entry"

pgp.wkd

Discovers public keys using the Web Key Directory protocol.

pgp.wkd = true

pgp.key-servers

Discovers public keys using the given key servers.

Key servers should be valid URLs. Supported schemes:

  • http:// and https://: URL should point to a valid public key.

  • hkp:// and hkps://: URL should point to a valid Web Key Directory service.

pgp.key-servers = ["https://meta.sr.ht/privacy/pubkey", "hkps://keys.openpgp.org"]

Examples

[my-account]
pgp.backend = "native"
pgp.secret-key.path = "~/.pgp/secret.key"
pgp.secret-key-passphrase.cmd = "pass show secret"
pgp.wkd = true
pgp.key-servers = ["hkps://keys.openpgp.org", "hkps://keys.mailvelope.com"]
[my-account.pgp]
backend = "native"
secret-key.keyring = "my-account-pgp-secret-key"
secret-key-passphrase.keyring = "my-account-pgp-secret-key-passphrase"
key-servers = ["https://meta.sr.ht/privacy/pubkey"]

Generate man pages

$ himalaya manual [OPTIONS] <DIR>

Generate manual pages to a directory.

This command allows you to generate manual pages (following the man page format) to the given directory. If the directory does not exist, it will be created. Any existing man pages will be overriden.

Generate completion scripts

$ himalaya completion [OPTIONS] <SHELL>

Print completion script for a shell to stdout.

This command allows you to generate completion script for a given shell. The script is printed to the standard output. If you want to write it to a file, just use unix redirection.

Available shells: bash, elvish, fish, powershell, zsh.

FAQ

How different is Himalaya CLI from aerc or Mutt?

This tool is a CLI, not a TUI. There is no main loop that blocks your terminal. Instead you run shell commands to interact with your emails.

The other difference is that Himalaya CLI tries not to reinvent the wheel by using email-lib, which contains all the logic associated to email management. Himalaya CLI does not contain any logic related to IMAP or SMTP, it focuses instead on the User Interface.

How can I debug Himalaya CLI?

The simplest way is to use --debug and --trace arguments.

The advanced way is based on environment variables:

  • RUST_LOG=<level>: determine 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

How the wizard discovers IMAP and SMTP configs?

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 test@example.com, the lookup is performed as (in this order):

  1. check for autoconfig.example.com
  2. look up of example.com in the ISPDB (the Thunderbird central database)
  3. look up MX example.com in DNS, and for mx1.mail.hoster.com, look up hoster.com in the ISPDB
  4. look up SRV example.com in DNS
  5. try to guess (imap.example.com, smtp.example.com…)

How to save a copy of a sent message?

Add the following option in your configuration:

message.send.save-copy = true

This option is disabled by default, because some email providers automatically save copies of sent messages.


Feel free to send any suggestion at ~soywod/pimalaya@lists.sr.ht.