Using nametrans
Chris Dennis
cgdennis at btinternet.com
Sun Jan 15 16:18:41 GMT 2012
I've finally got offlineimap's 'nametrans' feature to do what I want.
Part of the problem was that I found the documentation and examples to
be somewhat ambiguous in terms of which direction the translation would
happen.
Anyway, I've got it working, so here are my notes which will hopefully
be helpful to others.
The 'nametrans' configuration option allows conversion between different
folder names on the local and remote repositories.
nametrans specifies a Python expression which, given each folder name
from the repository in turn, returns the equivalent name on the other
repository.
In the configuration of the local repository, the nametrans code
receives each local folder name, and returns the name of the equivalent
remote folder.
In the remote repository configuration, the nametrans code gets the
remote folder names, one at a time, and returns the equivalent local names.
Here's a real example. My remote repository is on my ISP's server. The
ISP's spam filter puts spam emails into a folder called 'Spam', and
deleted emails into 'Trash'. The local repository, on a Debian server
running Dovecot IMAP, is accessed by users via Outlook, which likes to
use the folder name 'Junk E-mail' for spam and 'Deleted Items' for
deleted emails.
So to avoid confusion, I've set up name translations:
-----------------------------------------------------------------------
[Repository LocalIMAP]
type = IMAP
remotehost = localhost
...
nametrans = lambda foldername: re.sub ('^Junk E-mail$', 'Spam',
re.sub ('^Deleted Items$', 'Trash',
foldername))
[Repository RemoteIMAP]
type = IMAP
remotehost = isp.example.com
...
nametrans = lambda foldername: re.sub ('^Spam$', 'Junk E-mail',
re.sub ('^Trash$', 'Deleted Items',
foldername))
-----------------------------------------------------------------------
I won't explain Python lambdas and regular expressions here. But
beginners should note
1) the variable name after the word 'lambda' can be anything you
like, but must be the same as is used in the expression after the
':'; it makes sense to call it 'foldername', or just 'f' if you
don't like typing.
2) the re.sub function takes three arguments:
1. regular expression to match against the third argument
2. the string to return if there's a match
3. the value to match against -- here the folder name.
3) the use of ^ and $ to mark the beginning and end of the
match, i.e. to make sure the whole folder name is matched.
4) if there is no match, re.sub() returns the folder name
unchanged.
5) re.sub() can be nested to allow more than one translation.
With this configuration, offlineimap will synchronise the local 'Junk
E-mail' folder with the remote 'Spam' folder, and local 'Deleted Items'
with remote 'Trash' in both directions.
Problems will occur if the 'foreign' name exists as a folder. For
example, if 'Trash' exists on the local repository, you'll get this
error message:
-----------------------------------------------------------------------
ERROR: INFINITE FOLDER CREATION DETECTED! Folder 'Trash' (repository
'LocalIMAP') would be created as folder 'Trash' (repository
'RemoteIMAP'). The latter becomes 'Deleted Items' in return, leading to
infinite folder creation cycles.
SOLUTION: 1) Do set your nametrans rules on both repositories so they
lead to identical names if applied back and forth. 2) Use folderfilter
settings on a repository to prevent some folders from being created on
the other side.
-----------------------------------------------------------------------
I found that message only partially helpful: does it mean use both
solutions 1) and 2), or either?
Solution 3) would be "Remove folder 'Trash' from the local repository",
but if you don't want to do that, then solution 2) is required: add a
folderfilter to stop the local 'Trash' from being copied to the remote
side, like this (in the local repository configuration):
folderfilter = lambda foldername: foldername not in ['Trash']
That folderfilter is only required, in this example, if 'Trash' already
exists locally, or if there is any danger of it being created in the
future. It's always possible that a translated folder name could be
created by the user, so it's safest to add folderfilters for any
translated folder names. To complete my real-world example from above,
I need:
-----------------------------------------------------------------------
[Repository LocalIMAP]
# Has folders: Inbox, Junk E-mail, Deleted Items, etc.
type = IMAP
remotehost = localhost
...
nametrans = lambda foldername: re.sub ('^Junk E-mail$', 'Spam',
re.sub ('^Deleted Items$', 'Trash',
foldername))
folderfilter = lambda foldername: foldername not in ['Spam', 'Trash']
[Repository RemoteIMAP]
# Has folders: Inbox, Spam, Trash, etc.
type = IMAP
remotehost = isp.example.com
...
nametrans = lambda foldername: re.sub ('^Spam$', 'Junk E-mail',
re.sub ('^Trash$', 'Deleted Items',
foldername))
folderfilter = lambda foldername: foldername not in ['Junk E-mail',
'Deleted Items']
-----------------------------------------------------------------------
I hope that's clear, and that it's helpful to people. Perhaps some of
it could be included in the offlineimap documentation.
cheers
Chris
--
Chris Dennis
Fordingbridge, UK
More information about the OfflineIMAP-project
mailing list