Offlineimap
Installation
root:# apt-get install offlineimap phil:$ zcat /usr/share/doc/offlineimap/examples/offlineimap.conf.gz > ~/.offlineimaprc phil:$ mkdir ~/Maildir phil:$ mkdir ~/Maildir/new phil:$ mkdir ~/Maildir/cur phil:$ mkdir ~/Maildir/tmp
Editer ~/.offlineimap
phil@mercure:~$ grep -v '^$\|^#' < ~/.offlineimaprc [general] metadata = ~/.offlineimap accounts = Test maxsyncaccounts = 1 ui = Tk.Blinkenlights, Tk.VerboseUI, Curses.Blinkenlights, TTY.TTYUI, Noninteractive.Basic, Noninteractive.Quiet ignore-readonly = no [mbnames] enabled = no filename = ~/Mutt/muttrc.mailboxes header = "mailboxes " peritem = "+%(accountname)s/%(foldername)s" sep = " " footer = "\n" [ui.Tk.Blinkenlights] loglines = 5 bufferlines = 500 showlog = false fontfamily = Helvetica fontsize = 8 [Account Test] localrepository = LocalExample remoterepository = RemoteExample autorefresh = 3 ## Changed [Repository LocalExample] type = Maildir localfolders = ~/Maildir ## Changed sep = . ## Changed [Repository RemoteExample] type = IMAP remotehost = ssl.teuwen.org ## Changed ssl = yes remoteport = 993 ## Changed remoteuser = philmail ## Changed maxconnections = 3 ## Changed holdconnectionopen = yes ## Changed keepalive = 60 ## Changed nametrans = lambda foldername: re.sub('^INBOX.', , foldername) ## Changed
For remote repository via ssh:
[Repository RemoteExample] type = IMAP remotehost = mx.yobi.be preauthtunnel = ssh -q mx.yobi.be
With on server side ~/.ssh/authorized_keys:
command="/usr/bin/imapd ~/Maildir" ssh-rsa xxxxxxxx(key)
To avoid syncing of some directories from e.g. the remote server, add to the remote repository
folderfilter = lambda foldername: not re.search('(SPAM$|^shared|Mairix|NXP)', foldername)
Deleting Local Folders
OfflineIMAP does a two-way synchronization. That is, if you make a change to the mail on the server, it will be propogated to your local copy, and vise-versa. Some people might think that it would be wise to just delete all their local mail folders periodically. If you do this with OfflineIMAP, remember to also remove your local status cache (~/.offlineimap by default). Otherwise, OfflineIMAP will take this as an intentional deletion of many messages and will interpret your action as requesting them to be deleted from the server as well.
Use with Evolution
OfflineIMAP can work with Evolution. To do so, first configure your OfflineIMAP account to have sep = / in its configuration. Then, configure Evolution with the "Maildir-format mail directories" server type. For the path, you will need to specify the name of the top-level folder inside your OfflineIMAP storage location. You're now set!
So from courierIMAP to Evolution:
sep = / nametrans = lambda foldername: re.sub('^INBOX.', , foldername)
From IMAP of ULg to courierIMAP:
sep = . nametrans = lambda foldername: re.sub('^INBOX\.', '.', foldername)
Errors
With ULg IMAP I got sometimes the following error, only for the folder INBOX, sub-folders are synchronized correctly:
- Syncing INBOX: IMAP -> Maildir
- WARNING: UID validity problem for folder INBOX (saved; got); skipping it
To solve it, simply remove locally ~/.offlineimap/Repository-RemoteAccount/FolderValidity/INBOX
This can be automated in your procmailrc with sth similar to the following rule:
0HBc * ^Subject:.*cron * UID validity problem for folder \/[^ ]+ |rm -f /home/user/.offlineimap/Repository-RemoteAccount/FolderValidity/$MATCH
Warning!!! This is valid only for the ULg server, problem could be deeper, cf man offlineimap
Usage
- On GUI: offlineimap, this will use the TK Blinkenlights by default
- On CLI: offlineimap -u Noninteractive.Basic
Curses.Blinkenlights is ok also but not that helpful to debug - On cron: offlineimap -u Noninteractive.Quiet
Global script for cron
This can be called e.g. every hour, it will seek for ~/.offlineimaprc in each home directory and for each of them, find the configurations for remote directory and check if the remote directory is reachable and if yes, finally, execute offlineimap for this account.
#! /bin/bash
# Philippe Teuwen <phil@teuwen.org> v0.2
[ -x /usr/bin/offlineimap ] || exit 0
# For every existing user who has
# his homedir under /home and
# his ~/.offlineimaprc
# we extract his offlineimap accounts activated (=in accounts list)
# and we call offlineimap in his name only if the corresponding
# remotehosts are responding to a ping
for i in $(cut -f6 -d: /etc/passwd|grep /home);
do
if [ -e $i/.offlineimaprc ];
then
eval $(\
gawk -v user=$(basename $i) '
/^accounts/ {
# Place list of accounts in table a[]
split($3, a, ",")
}
# For each [Account XXX] section
/\[Account/ {
for(i in a)
# if it is an account existing in the table
if($2==a[i]"]")
# Parse the section and extract remoterepository name
for(getline;$0!~/^\[/;getline)
if(/^remoterepository/){
r[i]=$3
next
}
}
# For each [Repository XXX] section
/\[Repository/ {
for(i in r)
# if it is a repository related to our accounts
if($2==r[i]"]")
# Parse the section and extract hostname
for(getline;$0!~/^\[/;getline)
if(/^remotehost/){
h[i]=$3
next
}
}
# Now:
# a[] contains accounts
# h[] contains hostnames
END {
# For each hostname
for(i in h)
# First try if hostname is reachable then
# call offlineimap as the user
printf "su - "user" -s /bin/bash -c \"\
ping -c1 "h[i]" -q >/dev/null 2>&1 && \
nice -n19 offlineimap -1 -o -a "a[i]" -u Noninteractive.Basic > ~/.offlineimap.last.log 2>&1 \
\";"
}
' $i/.offlineimaprc\
)
fi;
done
exit 0