a6db99a21e
From Ben Kibbey hello, Attached is a patch to enable evaluation of account credentials with the remotehosteval, remoteusereval and remotepasseval configuration options. I needed this because rather than change all my other programs configuration settings when I change, say a password, I store them in a file. So I call a function in pythonfile which parses the credential file and returns the wanted info. Not really very well tested, but not complex either. Offlineimap is great, thanks.
220 lines
8.0 KiB
Python
220 lines
8.0 KiB
Python
# IMAP repository support
|
|
# Copyright (C) 2002 John Goerzen
|
|
# <jgoerzen@complete.org>
|
|
#
|
|
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
from Base import BaseRepository
|
|
from offlineimap import folder, imaputil, imapserver
|
|
from offlineimap.folder.UIDMaps import MappedIMAPFolder
|
|
from offlineimap.threadutil import ExitNotifyThread
|
|
import re, types, os
|
|
from threading import *
|
|
|
|
class IMAPRepository(BaseRepository):
|
|
def __init__(self, reposname, account):
|
|
"""Initialize an IMAPRepository object."""
|
|
BaseRepository.__init__(self, reposname, account)
|
|
self.imapserver = imapserver.ConfigedIMAPServer(self)
|
|
self.folders = None
|
|
self.nametrans = lambda foldername: foldername
|
|
self.folderfilter = lambda foldername: 1
|
|
self.folderincludes = []
|
|
self.foldersort = cmp
|
|
localeval = self.localeval
|
|
if self.config.has_option(self.getsection(), 'nametrans'):
|
|
self.nametrans = localeval.eval(self.getconf('nametrans'),
|
|
{'re': re})
|
|
if self.config.has_option(self.getsection(), 'folderfilter'):
|
|
self.folderfilter = localeval.eval(self.getconf('folderfilter'),
|
|
{'re': re})
|
|
if self.config.has_option(self.getsection(), 'folderincludes'):
|
|
self.folderincludes = localeval.eval(self.getconf('folderincludes'),
|
|
{'re': re})
|
|
if self.config.has_option(self.getsection(), 'foldersort'):
|
|
self.foldersort = localeval.eval(self.getconf('foldersort'),
|
|
{'re': re})
|
|
|
|
def startkeepalive(self):
|
|
keepalivetime = self.getkeepalive()
|
|
if not keepalivetime: return
|
|
self.kaevent = Event()
|
|
self.kathread = ExitNotifyThread(target = self.imapserver.keepalive,
|
|
name = "Keep alive " + self.getname(),
|
|
args = (keepalivetime, self.kaevent))
|
|
self.kathread.setDaemon(1)
|
|
self.kathread.start()
|
|
|
|
def stopkeepalive(self, abrupt = 0):
|
|
if not hasattr(self, 'kaevent'):
|
|
# Keepalive is not active.
|
|
return
|
|
|
|
self.kaevent.set()
|
|
if not abrupt:
|
|
self.kathread.join()
|
|
del self.kathread
|
|
del self.kaevent
|
|
|
|
def holdordropconnections(self):
|
|
if not self.getholdconnectionopen():
|
|
self.dropconnections()
|
|
|
|
def dropconnections(self):
|
|
self.imapserver.close()
|
|
|
|
def getholdconnectionopen(self):
|
|
return self.getconfboolean("holdconnectionopen", 0)
|
|
|
|
def getkeepalive(self):
|
|
return self.getconfint("keepalive", 0)
|
|
|
|
def getsep(self):
|
|
return self.imapserver.delim
|
|
|
|
def gethost(self):
|
|
host = None
|
|
localeval = self.localeval
|
|
|
|
if self.config.has_option(self.getsection(), 'remotehosteval'):
|
|
host = self.getconf('remotehosteval')
|
|
if host != None:
|
|
return localeval.eval(host)
|
|
|
|
host = self.getconf('remotehost')
|
|
if host != None:
|
|
return host
|
|
|
|
def getuser(self):
|
|
user = None
|
|
localeval = self.localeval
|
|
|
|
if self.config.has_option(self.getsection(), 'remoteusereval'):
|
|
user = self.getconf('remoteusereval')
|
|
if user != None:
|
|
return localeval.eval(user)
|
|
|
|
user = self.getconf('remoteuser')
|
|
if user != None:
|
|
return user
|
|
|
|
def getport(self):
|
|
return self.getconfint('remoteport', None)
|
|
|
|
def getssl(self):
|
|
return self.getconfboolean('ssl', 0)
|
|
|
|
def getpreauthtunnel(self):
|
|
return self.getconf('preauthtunnel', None)
|
|
|
|
def getreference(self):
|
|
return self.getconf('reference', '""')
|
|
|
|
def getmaxconnections(self):
|
|
return self.getconfint('maxconnections', 1)
|
|
|
|
def getexpunge(self):
|
|
return self.getconfboolean('expunge', 1)
|
|
|
|
def getpassword(self):
|
|
passwd = None
|
|
localeval = self.localeval
|
|
|
|
if self.config.has_option(self.getsection(), 'remotepasseval'):
|
|
passwd = self.getconf('remotepasseval')
|
|
if passwd != None:
|
|
return localeval.eval(passwd)
|
|
|
|
password = self.getconf('remotepass', None)
|
|
if password != None:
|
|
return password
|
|
passfile = self.getconf('remotepassfile', None)
|
|
if passfile != None:
|
|
fd = open(os.path.expanduser(passfile))
|
|
password = fd.readline().strip()
|
|
fd.close()
|
|
return password
|
|
return None
|
|
|
|
def getfolder(self, foldername):
|
|
return self.getfoldertype()(self.imapserver, foldername,
|
|
self.nametrans(foldername),
|
|
self.accountname, self)
|
|
|
|
def getfoldertype(self):
|
|
return folder.IMAP.IMAPFolder
|
|
|
|
def getfolders(self):
|
|
if self.folders != None:
|
|
return self.folders
|
|
retval = []
|
|
imapobj = self.imapserver.acquireconnection()
|
|
try:
|
|
listresult = imapobj.list(directory = self.imapserver.reference)[1]
|
|
finally:
|
|
self.imapserver.releaseconnection(imapobj)
|
|
for string in listresult:
|
|
if string == None or \
|
|
(type(string) == types.StringType and string == ''):
|
|
# Bug in imaplib: empty strings in results from
|
|
# literals.
|
|
continue
|
|
flags, delim, name = imaputil.imapsplit(string)
|
|
flaglist = [x.lower() for x in imaputil.flagsplit(flags)]
|
|
if '\\noselect' in flaglist:
|
|
continue
|
|
foldername = imaputil.dequote(name)
|
|
if not self.folderfilter(foldername):
|
|
continue
|
|
retval.append(self.getfoldertype()(self.imapserver, foldername,
|
|
self.nametrans(foldername),
|
|
self.accountname, self))
|
|
if len(self.folderincludes):
|
|
imapobj = self.imapserver.acquireconnection()
|
|
try:
|
|
for foldername in self.folderincludes:
|
|
try:
|
|
imapobj.select(foldername, readonly = 1)
|
|
except ValueError:
|
|
continue
|
|
retval.append(self.getfoldertype()(self.imapserver,
|
|
foldername,
|
|
self.nametrans(foldername),
|
|
self.accountname, self))
|
|
finally:
|
|
self.imapserver.releaseconnection(imapobj)
|
|
|
|
retval.sort(lambda x, y: self.foldersort(x.getvisiblename(), y.getvisiblename()))
|
|
self.folders = retval
|
|
return retval
|
|
|
|
def makefolder(self, foldername):
|
|
#if self.getreference() != '""':
|
|
# newname = self.getreference() + self.getsep() + foldername
|
|
#else:
|
|
# newname = foldername
|
|
newname = foldername
|
|
imapobj = self.imapserver.acquireconnection()
|
|
try:
|
|
result = imapobj.create(newname)
|
|
if result[0] != 'OK':
|
|
raise RuntimeError, "Repository %s could not create folder %s: %s" % (self.getname(), foldername, str(result))
|
|
finally:
|
|
self.imapserver.releaseconnection(imapobj)
|
|
|
|
class MappedIMAPRepository(IMAPRepository):
|
|
def getfoldertype(self):
|
|
return MappedIMAPFolder
|