Offlineimap

From YobiWiki
Jump to navigation Jump to search

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