diff --git a/head/offlineimap.conf b/head/offlineimap.conf index 6448edd..39279b0 100644 --- a/head/offlineimap.conf +++ b/head/offlineimap.conf @@ -16,6 +16,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +################################################## +# General definitions +################################################## + [general] # This specifies where imapsync is to store its metadata. @@ -31,11 +35,38 @@ metadata = ~/.imapsync accounts = Test -# This is an account definition clause. +################################################## +# Mailbox name recorder +################################################## + +[mbnames] + +# imapsync can record your mailbox names in a format you specify. +# You can define the header, each mailbox item, the separator, +# and the footer. Here is an example for Mutt. +# If enabled is yes, all six setting must be specified, even if they +# are just the empty string "". +# +# The header, peritem, sep, and footer are all Python expressions passed +# through eval, so you can (and must) use Python quoting. + +enabled = no +filename = ~/Mutt/muttrc.mailboxes +header = "mailboxes " +peritem = "+%(accountname)s/%(foldername)s" +sep = " " +footer = "\n" + +################################################## +# Accounts +################################################## + +# This is an account definition clause. You'll have one of these +# for each account listed in general/accounts above. [Test] # Specify the remote hostname. -remotehost = pi.complete.org +remotehost = examplehost # Whether or not to use SSL. ssl = yes @@ -50,7 +81,13 @@ remoteuser = pilot # prompted. # remotepass = fake - # Specify local repository. localfolders = ~/Test + +# You can specify a folder translator. This must be a eval-able +# Python expression that takes a foldername arg and returns the new +# value. I suggest a lambda. This example will remove "INBOX." from +# the leading edge of folders (great for Courier IMAP users) + +# nametrans = lambda foldername: re.sub('^INBOX.', '', foldername) diff --git a/head/offlineimap.py b/head/offlineimap.py index c9e1b0b..1eb0c77 100644 --- a/head/offlineimap.py +++ b/head/offlineimap.py @@ -17,7 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -from imapsync import imaplib, imaputil, imapserver, repository, folder +from imapsync import imaplib, imaputil, imapserver, repository, folder, mbnames import re, os, os.path, imapsync, sys from ConfigParser import ConfigParser @@ -43,6 +43,7 @@ accounts = accounts.split(",") server = None remoterepos = None localrepos = None +mailboxes = [] for accountname in accounts: ui.acct(accountname) @@ -63,7 +64,7 @@ for accountname in accounts: # Connect to the remote server. server = imapserver.IMAPServer(user, password, host, port, ssl) - remoterepos = repository.IMAP.IMAPRepository(server) + remoterepos = repository.IMAP.IMAPRepository(config, accountname, server) # Connect to the Maildirs. localrepos = repository.Maildir.MaildirRepository(os.path.expanduser(config.get(accountname, "localfolders"))) @@ -75,8 +76,10 @@ for accountname in accounts: remoterepos.syncfoldersto(localrepos) for remotefolder in remoterepos.getfolders(): + mailboxes.append({'accountname': accountname, + 'foldername': remotefolder.getvisiblename()}) # Load local folder. - localfolder = localrepos.getfolder(remotefolder.getname()) + localfolder = localrepos.getfolder(remotefolder.getvisiblename()) if not localfolder.isuidvalidityok(remotefolder): ui.validityproblem(remotefolder) continue @@ -92,7 +95,7 @@ for accountname in accounts: len(remotefolder.getmessagelist().keys())) # Load status folder. - statusfolder = statusrepos.getfolder(remotefolder.getname()) + statusfolder = statusrepos.getfolder(remotefolder.getvisiblename()) statusfolder.cachemessagelist() if not statusfolder.isnewfolder(): @@ -109,3 +112,4 @@ for accountname in accounts: statusfolder.save() +mbnames.genmbnames(config, mailboxes) diff --git a/head/offlineimap/__init__.py b/head/offlineimap/__init__.py index c7421b3..551f2de 100644 --- a/head/offlineimap/__init__.py +++ b/head/offlineimap/__init__.py @@ -1 +1,2 @@ -import ui, folder, repository +import ui, folder, repository, mbnames + diff --git a/head/offlineimap/folder/Base.py b/head/offlineimap/folder/Base.py index 9735002..786a1b2 100644 --- a/head/offlineimap/folder/Base.py +++ b/head/offlineimap/folder/Base.py @@ -16,11 +16,16 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +import __main__ + class BaseFolder: def getname(self): """Returns name""" return self.name + def getvisiblename(self): + return self.name + def getroot(self): """Returns the root of the folder, in a folder-specific fashion.""" return self.root diff --git a/head/offlineimap/folder/IMAP.py b/head/offlineimap/folder/IMAP.py index abb651e..9356ebb 100644 --- a/head/offlineimap/folder/IMAP.py +++ b/head/offlineimap/folder/IMAP.py @@ -22,13 +22,17 @@ import rfc822 from StringIO import StringIO class IMAPFolder(BaseFolder): - def __init__(self, imapserver, name): + def __init__(self, imapserver, name, visiblename): self.name = imaputil.dequote(name) self.root = imapserver.root self.sep = imapserver.delim self.imapserver = imapserver self.imapobj = self.imapserver.makeconnection() self.messagelist = None + self.visiblename = visiblename + + def getvisiblename(self): + return self.visiblename def getuidvalidity(self): x = self.imapobj.status(self.getfullname(), ('UIDVALIDITY'))[1][0] diff --git a/head/offlineimap/mbnames.py b/head/offlineimap/mbnames.py new file mode 100644 index 0000000..24944ee --- /dev/null +++ b/head/offlineimap/mbnames.py @@ -0,0 +1,34 @@ +# Mailbox name generator +# Copyright (C) 2002 John Goerzen +# +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import os.path + +def genmbnames(config, boxlist): + """Takes a configparser object and a boxlist, which is a list of hashes + containing 'accountname' and 'foldername' keys.""" + if not config.getboolean("mbnames", "enabled"): + return + file = open(os.path.expanduser(config.get("mbnames", "filename")), "wt") + file.write(eval(config.get("mbnames", "header"))) + itemlist = [eval(config.get("mbnames", "peritem", raw=1)) % item for item in boxlist] + file.write(eval(config.get("mbnames", "sep")).join(itemlist)) + file.write(eval(config.get("mbnames", "footer"))) + file.close() + + + diff --git a/head/offlineimap/repository/Base.py b/head/offlineimap/repository/Base.py index 52ba5a3..4c91157 100644 --- a/head/offlineimap/repository/Base.py +++ b/head/offlineimap/repository/Base.py @@ -45,11 +45,11 @@ class BaseRepository: srchash = {} for folder in srcfolders: - srchash[folder.getname().replace(src.getsep(), dest.getsep())] = \ + srchash[folder.getvisiblename().replace(src.getsep(), dest.getsep())] = \ folder desthash = {} for folder in destfolders: - desthash[folder.getname()] = folder + desthash[folder.getvisiblename()] = folder # # Find new folders. diff --git a/head/offlineimap/repository/IMAP.py b/head/offlineimap/repository/IMAP.py index e7ed88b..6e942f7 100644 --- a/head/offlineimap/repository/IMAP.py +++ b/head/offlineimap/repository/IMAP.py @@ -18,20 +18,27 @@ from Base import BaseRepository from imapsync import folder, imaputil +import re class IMAPRepository(BaseRepository): - def __init__(self, imapserver): + def __init__(self, config, accountname, imapserver): """Initialize an IMAPRepository object. Takes an IMAPServer object.""" self.imapserver = imapserver + self.config = config + self.accountname = accountname self.imapobj = imapserver.makeconnection() self.folders = None + self.nametrans = lambda foldername: foldername + if config.has_option(accountname, 'nametrans'): + self.nametrans = eval(config.get(accountname, 'nametrans')) def getsep(self): return self.imapserver.delim def getfolder(self, foldername): - return folder.IMAP.IMAPFolder(self.imapserver, foldername) + return folder.IMAP.IMAPFolder(self.imapserver, foldername, + self.nametrans(foldername)) def getfolders(self): if self.folders != None: @@ -41,6 +48,7 @@ class IMAPRepository(BaseRepository): flags, delim, name = imaputil.imapsplit(string) if '\\Noselect' in imaputil.flagsplit(flags): continue - retval.append(folder.IMAP.IMAPFolder(self.imapserver, name)) + retval.append(folder.IMAP.IMAPFolder(self.imapserver, name, + self.nametrans(imaputil.dequote(name)))) self.folders = retval return retval diff --git a/head/offlineimap/ui/UIBase.py b/head/offlineimap/ui/UIBase.py index 698914e..9f87624 100644 --- a/head/offlineimap/ui/UIBase.py +++ b/head/offlineimap/ui/UIBase.py @@ -38,6 +38,9 @@ class UIBase: def getpass(s, accountname, host, port, user): raise NotImplementedException + def folderlist(s, list): + return ', '.join(["%s[%s]" % (s.getnicename(x), x.getname()) for x in list]) + ################################################## MESSAGES def init_banner(s): @@ -81,21 +84,21 @@ class UIBase: df.getname())) def copyingmessage(s, uid, src, destlist): - ds = ["%s[%s]" % (s.getnicename(x), x.getname()) for x in destlist].join(', ') + ds = s.folderlist(destlist) s._msg("Copy message %d %s[%s] -> %s" % (uid, s.getnicename(src), src.getname(), ds)) def deletingmessage(s, uid, destlist): - ds = ["%s[%s]" % (s.getnicename(x), x.getname()) for x in destlist].join(', ') + ds = s.folderlist(destlist) s._msg("Deleting message %d in %s" % (uid, ds)) def addingflags(s, uid, flags, destlist): - ds = ["%s[%s]" % (s.getnicename(x), x.getname()) for x in destlist].join(', ') + ds = s.folderlist(destlist) s._msg("Adding flags %s to message %d on %s" % \ (flags.join(", "), uid, ds)) def deletingflags(s, uid, flags, destlist): - ds = ["%s[%s]" % (s.getnicename(x), x.getname()) for x in destlist].join(', ') + ds = s.folderlist(destlist) s._msg("Deleting flags %s to message %d on %s" % \ (flags.join(", "), uid, ds))