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