OfflineIMAP

Related articles
isync
notmuch
msmtp
OfflineIMAP
is a Python utility to sync mail from IMAP servers. It does not work with the POP3 protocol or mbox, and is usually paired with a MUA such as
Mutt
.
Installation
Install
the
offlineimap
package.
Configuration
Offlineimap is distributed with two default configuration files, which are both located in
/usr/share/offlineimap/
.
offlineimap.conf
contains every setting and is thoroughly documented. Alternatively,
offlineimap.conf.minimal
is not commented and only contains a small number of settings; see:
#Minimal
.
Copy one of the default configuration files to
~/.offlineimaprc
or
$XDG_CONFIG_HOME/offlineimap/config
.
Note
Writing a comment after an option/value on the same line is invalid syntax, hence take care that comments are placed on their own separate line.
Minimal
The following file is a commented version of
offlineimap.conf.minimal
.
~/.offlineimaprc
[general]
# List of accounts to be synced, separated by a comma.
accounts = main

[Account main]
# Identifier for the local repository; e.g. the maildir to be synced via IMAP.
localrepository = main-local
# Identifier for the remote repository; i.e. the actual IMAP, usually non-local.
remoterepository = main-remote

[Repository main-local]
# OfflineIMAP supports Maildir, GmailMaildir, and IMAP for local repositories.
type = Maildir
# Where should the mail be placed?
localfolders = ~/mail

[Repository main-remote]
# Remote repos can be IMAP or Gmail, the latter being a preconfigured IMAP.
# SSL and STARTTLS are enabled by default.
type = IMAP
remotehost = host.domain.tld
remoteuser = username
# Necessary for SSL connections, if using offlineimap version > 6.5.4
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
Selective folder synchronization
For synchronizing only certain folders, you can use a
folderfilter
in the
remote
section of the account in
~/.offlineimaprc
. For example, the following configuration will only synchronize the folders
Inbox
and
Sent
:
~/.offlineimaprc
[Repository main-remote]
# Synchronize only the folders Inbox and Sent:
folderfilter = lambda foldername: foldername in ["Inbox", "Sent"]
...
For more options, see the
official documentation
.
Custom port
Some IMAP servers might require you to connect on a custom port, instead of the default 993 port. To do so, add a
remoteport
option to the
remote
section in
~/.offlineimaprc
:
~/.offlineimaprc
[Repository main-remote]
remoteport=
1234
Usage
Before running offlineimap, create any parent directories that were allocated to local repositories:
$ mkdir ~/mail
Now, run the program:
$ offlineimap
Mail accounts will now be synced. If anything goes wrong, take a closer look at the error messages. OfflineIMAP is usually very verbose about problems; partly because the developers did not bother with taking away tracebacks from the final product.
Tips and tricks
Running offlineimap in the background
This article or section needs language, wiki syntax or style improvements. See
Help:Style
for reference.
Reason:
Maybe do not use a configuration file with comments as documentation, but describe them in the text? (Discuss in
Talk:OfflineIMAP
)
Most other mail transfer agents assume that the user will be using the tool as a
daemon
by making the program sync periodically by default. In offlineimap, there are a few settings that control backgrounded tasks.
Confusingly, they are spread thin all-over the configuration file:
~/.offlineimaprc
# In the general section
[general]
# Controls how many accounts may be synced simultaneously
maxsyncaccounts = 1

# In the account identifier
[Account main]
# Minutes between syncs
autorefresh = 0.5
# Quick-syncs do not update if the only changes were to IMAP flags.
# autorefresh=0.5 together with quick=10 yields
# 10 quick refreshes between each full refresh, with 0.5 minutes between every 
# refresh, regardless of type.
quick = 10

# In the remote repository identifier
[Repository main-remote]
# Instead of closing the connection once a sync is complete, offlineimap will
# send empty data to the server to hold the connection open. A value of 60
# attempts to hold the connection for a minute between syncs (both quick and
# autorefresh).This setting has no effect if autorefresh and holdconnectionopen
# are not both set.
keepalive = 60
# OfflineIMAP normally closes IMAP server connections between refreshes if
# the global option autorefresh is specified.  If you wish it to keep the
# connection open, set this to true. This setting has no effect if autorefresh
# is not set.
holdconnectionopen = yes
To start the daemon automatically on login,
start/enable
the
systemd/User
service
offlineimap.service
using the
--user
flag.
In case you have more than one account configured, it is advised to use
offlineimap@.service
instead of increasing maxsyncaccounts parameter
[1]
. Simply
start/enable
offlineimap@youraccountname.service
.
systemd timer
Alternatively, it is possible to manage OfflineIMAP completely using systemd-user
timers
, start/enable
offlineimap-oneshot.timer
with the
--user
flag.
This timer by default runs OfflineIMAP every 15 minutes. This can be easily changed by creating a
drop-in snippet
. For example, the following modifies the timer to check every 5 minutes:
~/.config/systemd/user/offlineimap-oneshot.timer.d/timer.conf
[Timer]
OnUnitInactiveSec=5m
The factual accuracy of this article or section is disputed.
Reason:
This can lead to inconsistencies in the OfflineIMAP's local database. (Discuss in
Talk:OfflineIMAP
)
For more robust solution it is possible to set a watchdog which will kill OfflineIMAP in case of freeze:
~/.config/systemd/user/offlineimap-oneshot.service.d/service.conf
[Service]
WatchdogSec=300
Automatic mailbox generation for mutt
Mutt
cannot be simply pointed to an IMAP or maildir directory and be expected to guess which subdirectories happen to be the mailboxes, yet offlineimap can generate a muttrc fragment containing the mailboxes that it syncs.
~/.offlineimaprc
[mbnames]
enabled = yes
filename = ~/.mutt/mailboxes
header = "mailboxes "
peritem = "+%(accountname)s/%(foldername)s"
sep = " "
footer = "\n"
Then add the following lines to
~/.mutt/muttrc
.
~/.mutt/muttrc
# IMAP: offlineimap
set folder = "~/mail"
source ~/.mutt/mailboxes
set spoolfile = "+account/INBOX"
set record = "+account/Sent\ Items"
set postponed = "+account/Drafts"
account
is the name you have given to your IMAP account in
~/.offlineimaprc
.
Gmail configuration
This remote repository is configured specifically for Gmail support, substituting folder names in uppercase for lowercase, among other small additions. Keep in mind that this configuration does not sync the
All Mail
folder, since it is usually unnecessary and skipping it prevents bandwidth costs:
~/.offlineimaprc
[Repository gmail-remote]
type = Gmail
remoteuser = user@gmail.com
remotepass = password
nametrans = lambda foldername: re.sub ('^\[gmail\]', 'bak',
                               re.sub ('sent_mail', 'sent',
                               re.sub ('starred', 'flagged',
                               re.sub (' ', '_', foldername.lower()))))
folderfilter = lambda foldername: foldername not in ['[Gmail]/All Mail']
# Necessary as of OfflineIMAP 6.5.4
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
# Necessary to work around https://github.com/OfflineIMAP/offlineimap/issues/573 (versions 7.0.12, 7.2.1)
ssl_version = tls1_2
Note
If you have Gmail set to another language, the folder names may appear translated too, e.g. "verzonden_berichten" instead of "sent_mail".
After version 6.3.5, offlineimap also creates remote folders to match your local ones. Thus you may need a nametrans rule for your local repository too that reverses the effects of this nametrans rule. If you do not want to make a reverse nametrans rule, you can disable remote folder creation by putting this in your remote configuration:
createfolders = False
As of 1 October 2012 gmail SSL certificate fingerprint is not always the same. This prevents from using
cert_fingerprint
and makes the
sslcacertfile
way a better solution for the SSL verification (see
#SSL fingerprint does not match
).
OAuth2 access tokens via oama
oama
(
oama-bin
AUR
) is a utility which provides IMAP/SMTP clients with renewal capabilities and authorization of OAuth2 credentials.
OfflineIMAP can call Python code from its configuration. So in the
[general]
section at the beginning, add the line:
~/.offlineimaprc
[general]
pythonfile = ~/.offlineimap.py
And in the Python file, add this code to retrieve OAuth2 access tokens via
oama
:
~/.offlineimap.py
import subprocess

def get_token(email_address):
    return subprocess.run(["oama", "access", email_address], capture_output=True, text=True).stdout
And now back to the configuration file, in the repository section of a Gmail account, add the following:
~/.offlineimaprc
auth_mechanisms = XOAUTH2
oauth2_client_id =
YOUR_OAUTH2_CLIENT_ID
oauth2_client_secret =
YOUR_OAUTH2_CLIENT_SECRET
oauth2_request_url = https://accounts.google.com/o/oauth2/token
oauth2_access_token_eval = get_token("
YOUR_EMAIL_ADDRESS_FOR_THIS_ACCOUNT
")
Password management
.netrc
Add the following lines to your
~/.netrc
:
machine hostname.tld
    login [your username]
    password [your password]
Do not forget to give the file appropriate rights like 600 or 700:
$ chmod 600 ~/.netrc
Note
OfflineIMAP
does not know
how to retrieve passwords when more than one account is stored in the
.netrc
file.
Using GPG
GNU Privacy Guard can be used for storing a password in an encrypted file. First set up
GnuPG
and then follow the steps in this section. It is assumed that you can use your GPG private key
without entering a password
all the time.
First type in the password for the email account in a plain text file. Do this in a secure directory with
700
permissions located on a
tmpfs
to avoid writing the unencrypted password to the disk. Then
encrypt
the file with GnuPG setting yourself as the recipient.
Remove the plain text file since it is no longer needed. Move the encrypted file to the final location, e.g.
~/.offlineimappass.gpg
.
Now create a python function that will decrypt the password:
~/.offlineimap.py
#! /usr/bin/env python
from subprocess import check_output

def get_pass():
    return check_output("gpg -dq ~/.offlineimappass.gpg", shell=True).rstrip(b"\n")
Load this file from
~/.offlineimaprc
and specify the defined function:
~/.offlineimaprc
[general]
# Path to file with arbitrary Python code to be loaded
pythonfile = ~/.offlineimap.py
...

[Repository
example
]
# Decrypt and read the encrypted password
remotepasseval = get_pass()
...
Using pass
pass
is a simple password manager from the command line based on GPG.
First create a password for your email account(s):
$ pass insert Mail/
account
Now create a python function that will decrypt the password:
~/.offlineimap.py
#! /usr/bin/env python
from subprocess import check_output

def get_pass(account):
    return check_output("pass Mail/" + account, shell=True).splitlines()[0]
This is an example for a multi-account setup. You can customize the argument to
pass
as defined previously.
Load this file from
~/.offlineimaprc
and specify the defined function:
~/.offlineimaprc
[general]
# Path to file with arbitrary Python code to be loaded
pythonfile = ~/.offlineimap.py
...

[Repository Gmail]
# Decrypt and read the encrypted password
remotepasseval = get_pass("Gmail")
...
Gnome keyring
In configuration for remote repositories the remoteusereval/remotepasseval fields can be set to custom python code that evaluates to the username/password. The code can be a call to a function defined in a Python script pointed to by 'pythonfile' config field. Create
~/.offlineimap.py
according to the subsection below and use it in the configuration:
[general]
pythonfile = ~/.offlineimap.py

[Repository examplerepo]
type = IMAP
remotehost = mail.example.com
remoteusereval = get_username("examplerepo")
remotepasseval = get_password("examplerepo")
gkgetsecret.py
This article or section needs language, wiki syntax or style improvements. See
Help:Style
for reference.
Reason:
Since this is now a single subsection, it should be merged with the introduction above. (Discuss in
Talk:OfflineIMAP
)
Ensure that
gnome-keyring
,
python2
AUR
,
python2-gobject
AUR
and
libsecret
are installed. Then create
~/.offlineimap.py
with the following contents:
gkgetsecret.py
and set
pythonfile = ~/.offlineimap.py
in
~/.offlineimaprc
as described above.
If you created a password using
seahorse
, you can retrieve it from its description. For instance, the password for a repository
Work
which is stored in gnome-keyring with the description
Password for me@myworkemail.com
can be retrieved by adding the following to
~/.offlineimaprc
:
[Repository Work]
...
remotepasseval = get_pw_from_desc("Password for me@myworkemail.com")
For configurations where you wish to store the username as well, it is better if the password is created using
secret-tool
as this can be used to set attributes such as the username and repository name. Consider a password created with the following command:
$ secret-tool store --label "Password for Work Email" username me@myworkemail.com repo Work
The username and password for this account can be retrieved by adding the following to
~/.offlineimaprc
:
[Repository Work]
...
remoteusereval = get_val_from_attrs("username", "repo", "Work")
remotepasseval = get_pw_from_attrs("repo", "Work")
python-keyring
There is a general solution that should work for any keyring. Install
python-keyring
and then change  your ~/.offlineimaprc to say something like:
[general]
pythonfile = /home/user/offlineimap.py
...
[Repository RemoteEmail]
remoteuser = username@host.net
remotepasseval = keyring.get_password("host","username")
...
and somewhere in ~/offlineimap.py add
import keyring
.
Now all you have to do is set your password, either using python script like so:
$ python
>>> import keyring
>>> keyring.set_password("host","username", "MYPASSWORD")
or you can use keyring command provided by python-keyring package
$ keyring --help
$ keyring set host username
Password for 'username' in 'host':
$ keyring get host username
password
and it will grab the password from your (kwallet/gnome-) keyring instead of having to keep it in plaintext or enter it each time.
Emacs EasyPG
See
https://www.emacswiki.org/emacs/OfflineIMAP#toc2
KeePassXC with Freedesktop.org secret-service
Install
libsecret
, in KeepassXC settings enable Freedesktop.org secret-service integration, expose entries in
Database Settings > Secret Service Integration
and add additional attribute
Title
with
account@name.org
in
Edit Entry > Advanced
settings. Now the command
secret-tool lookup Title account@name.org
should print the password in the console. Next create a python script:
~/.script.py
#! /usr/bin/env python
import os
from subprocess import check_output

def get_pass(account):
    return check_output("secret-tool lookup Title " + account, shell=True).splitlines()[0].decode("UTF-8")
An equivalent script which relies on
python-secretstorage
is:
~/.script.py
#! /usr/bin/env python
import secretstorage
from contextlib import closing
def get_pass(title):
    with closing(secretstorage.dbus_init()) as conn:
        assert(secretstorage.check_service_availability(conn))
        collection = secretstorage.get_default_collection(conn)
        if collection.is_locked():
            collection.unlock()
        matches = collection.search_items({"Title": title})
        entry = next(matches)
        if entry.is_locked():
            entry.unlock()
        return(entry.get_secret())
Load this file from
~/.offlineimaprc
and specify the defined function:
~/.offlineimaprc
[general]
# Path to file with arbitrary Python code to be loaded
pythonfile = ~/.script.py
...
[Repository Gmail]
# Decrypt and read the encrypted password
remotepasseval = get_pass("account@name.org")
...
Troubleshooting
Overriding UI and autorefresh settings
For the sake of troubleshooting, it is sometimes convenient to launch offlineimap with a more verbose UI, no background syncs and perhaps even a debug level:
$ offlineimap [ -o ] [ -d <debug_type> ] [ -u <ui> ]
-o
Disable autorefresh, keepalive, etc.
-d <debug_type>
Where
<debug_type>
is one of
imap
,
maildir
or
thread
. Debugging imap and maildir are, by far, the most useful.
-u <ui>
Where
<ui>
is one of
CURSES.BLINKENLIGHTS
,
TTY.TTYUI
,
NONINTERACTIVE.BASIC
,
NONINTERACTIVE.QUIET
or
MACHINE.MACHINEUI
. TTY.TTYUI is sufficient for debugging purposes.
Note
More recent versions use the following for <ui>:
blinkenlights
,
ttyui
,
basic
,
quiet
or
machineui
.
Folder could not be created
In version 6.5.3, offlineimap gained the ability to create folders in the remote repository, as described
here
.
This can lead to errors of the following form when using
nametrans
on the remote repository:
ERROR: Creating folder bar on repository foo-remote
  Folder 'bar'[foo-remote] could not be created. Server responded: ('NO', ['[ALREADYEXISTS] Duplicate folder name bar (Failure)'])
The solution is to provide an inverse
nametrans
lambda for the local repository, e.g.
~/.offlineimaprc
[Repository foo-local]
nametrans = lambda foldername: foldername.replace('bar', 'BAR')

[Repository foo-remote]
nametrans = lambda foldername: foldername.replace('BAR', 'bar')
For working out the correct inverse mapping. the output of
offlineimap --info
should help.
After updating the mapping, it may be necessary to remove all of the folders under
$HOME/.offlineimap/
for the affected accounts.
SSL fingerprint does not match
ERROR: Server SSL fingerprint 'keykeykey' for hostname 'example.com' does not match configured fingerprint. Please verify and set 'cert_fingerprint' accordingly if not set yet.
To solve this, add to
~/.offlineimaprc
(in the same section as
ssl = yes
) one of the following:
either add
cert_fingerprint
, with the certificate fingerprint of the remote server. This checks whether the remote server certificate matches the given fingerprint.
cert_fingerprint = keykeykey
or add
sslcacertfile
with the path to the system CA certificates file. Needs
ca-certificates
installed. This validates the remote ssl certificate chain against the Certification Authorities in that file.
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
Copying message, connection closed
ERROR: Copying message -2 [acc: email] connection closed
Folder sent [acc: email]: ERROR: while syncing sent [account email] connection closed
Cause of this can be creation of same message both locally and on server. This happens if your email provider automatically saves sent mails to same folder as your local client. If you encounter this, disable save of sent messages in your local client.
See also
Official OfflineIMAP mailing list
Mutt + Gmail + Offlineimap
- An outline of brisbin's simple gmail/mutt setup using cron to keep offlineimap syncing.