#imap #mailbox #oauth2

app imap-tools

A collection of tools to manipulate IMAP mailboxes

37 stable releases

Uses new Rust 2024

1.11.1 May 7, 2026
1.10.2 Apr 28, 2026
1.8.3 Mar 25, 2026
1.7.3 Oct 9, 2025
1.3.1 Nov 17, 2024

#127 in Authentication

MIT license

255KB
6K SLoC

IMAP Tools

Installation

$ cargo install imap-tools

Usage

Most tools have the same generic arguments :

  • -c - --config - The configuration file to use.

Next, these arguments can be either set on the command line or in the config file.

  • -u - --username - The username to use for login.
  • -p - --password - The password to use for login.
  • -P - --password_command - A command to use to get the password.
  • -s - --server - The imap server, defaults to localhost.
  • -d - --debug - Dump all the imap dialogue.
  • -n - --dry-run - Don't change anything on the server.

So a configuration file may start with:

password-command = "secret-tool lookup id example"
server           = "imap.example.com"
username         = "alice@example.com"

# This will match all mailboxes
[[filters]]
  reference = ""
  pattern   = "*"

# This will match the first level of mailboxes, and then only keep mailboxes
# whose full path contain strings in `include`.
[[filters]]
  reference = ""
  pattern   = "%"
  include   = ["INBOX", "Sent"]

There are four fields that allow a finer selection of mailboxes. They are include, exclude, include_re and exclude_re. The first two will include and exclude based on basic string matching. The later two will need to be valid Regex patterns, and will also include mailboxes and exclude them.

Some tools like clean have an extra parameter added globally, and/or to each filter, description is provided when this happens. If a filter does not have the extra parameter set, the global one gets used instead. For example if you have these filters with extras:

extra = "foo"

[[filters]]
  reference = ""
  name = "*"
  extra = "bar"

[[filters]]
  reference = "foo"
  name = "*"

[[filters]]
  reference = "bar"
  name = "*"

They would end up as if this had been written as:

[[filters]]
  reference = ""
  name = "*"
  extra = "bar"

[[filters]]
  reference = "foo"
  name = "*"
  extra = "foo"

[[filters]]
  reference = "bar"
  name = "*"
  extra = "foo"

Example usage

$ imap-tools list -c config.toml

Tools

list

This tool will list the mailboxes that would be processed by other tools. It helps you figure out your filters without actually doing anything.

finddup

This tool will go over all the mailboxes from an imap server, find messages with duplicate message ids, and remove duplicates.

clean

This tool will go over the mailboxes and cleanup old messages according to simples rules.

The rules are added to a filter using the extra parameter. For example:

[[filters]]
  reference = ""
  name = "*"

  [filters.extra]
    0MB = 105
    5MB = 85
    10MB = 55

The reference and name are the same as for other tools. extra is a map of mailbox size in MB to days of messages that should be kept. In this example, messages are kept up to 105 days, unless the mailbox is larger than 5MB, and oldest message is newer than 105 days, then messages are kept up to 85 days, unless the mailbox is more than 10MB and the oldest message is less than 55 days old.

archive

This tool will "archive", aka move, old emails from mailboxes into archive mailboxes. Its extra parameter contains a number of days and a string format for the archive mailbox location. The string format can contain is passed through strftime so all its specifiers can be used. The strftime calls are made based on the date on which each email was received. (Called the internaldate in IMAP terms). The string format can also contain %%MBX (yes, with two %) that will be replaced with the full mailbox name. For example:

[[filters]]
  reference = ""
  name = "*"

  [filters.extra]
    days   = 200
    format = "Archive/%Y/%%MBX"

Will move messages older than 200 days into the archive mailbox. If the mailbox is INBOX/bob, and the email is from 2024, it will be moved into Archive/2024/INBOX/bob.

Another example could be:

[[filters]]
  reference = ""
  name = "*"

  [filters.extra]
    days   = 200
    format = "%%MBX/old/%Y/%m"

If the mailbox is INBOX/bob, and the email is from september 2024, it will be moved into INBOX/bob/old/2024/09.

Authentication

The auth field (config file or --auth CLI flag) selects the SASL mechanism. The default is login (standard IMAP LOGIN command).

auth value Mechanism Credential needed Notes
login IMAP LOGIN password / password-command Default
plain SASL PLAIN password / password-command Requires TLS to avoid cleartext
cram-md5 SASL CRAM-MD5 password / password-command Challenge/response, no TLS required
scram-sha-1 SASL SCRAM-SHA-1 password / password-command Mutual-auth, RFC 5802
scram-sha-256 SASL SCRAM-SHA-256 password / password-command Preferred over SHA-1, RFC 7677
xoauth2 SASL XOAUTH2 oauth2-command Bearer token, for Gmail / Office 365

Example using SCRAM-SHA-256:

auth             = "scram-sha-256"
server           = "imap.example.com"
username         = "user@example.com"
password-command = "pass show imap/example"

OAuth2 (Gmail / Office 365)

Gmail and Office 365 no longer accept plain-password IMAP login. Use auth = "xoauth2" together with oauth2-command, a shell command whose stdout is a valid bearer access token.

auth           = "xoauth2"
server         = "imap.gmail.com"
port           = 993
username       = "user@gmail.com"
oauth2-command = "oauth2l fetch --output_format=bare https://mail.google.com/"

imap-tools does not handle token refresh or caching; delegate that to an external tool:

  • Gmailoauth2l or mutt_oauth2.py. Obtain a refresh token once (follow the tool's setup guide), then use the command above.
  • Office 365mutt_oauth2.py with --provider microsoft.

The access token is fetched fresh on every invocation. If it has expired, the IMAP server will return an authentication error.

imap

Permit somewhat "raw" imap commands

list

This is comparable to the list command, but it does not need a config file.

create

Permits direct creation of a mailbox

delete

Permits direct deletion of a mailbox

Dependencies

~23–44MB
~617K SLoC