/head: changeset 90
Commited changes for 2.0.6
This commit is contained in:
parent
bd9873632c
commit
097d30e987
@ -1,3 +1,22 @@
|
|||||||
|
2002-07-09 20:17 jgoerzen
|
||||||
|
|
||||||
|
* offlineimap.conf, offlineimap.py, debian/changelog,
|
||||||
|
offlineimap/imapserver.py, offlineimap/version.py,
|
||||||
|
offlineimap/folder/IMAP.py: Commited changes for 2.0.6
|
||||||
|
|
||||||
|
2002-07-09 13:13 jgoerzen
|
||||||
|
|
||||||
|
* offlineimap/folder/IMAP.py: Another attempt at the read-only bug
|
||||||
|
|
||||||
|
2002-07-08 12:05 jgoerzen
|
||||||
|
|
||||||
|
* offlineimap/folder/IMAP.py: Another attempt at fixing read-only
|
||||||
|
folders
|
||||||
|
|
||||||
|
2002-07-08 11:38 jgoerzen
|
||||||
|
|
||||||
|
* ChangeLog: Updated for 2.0.5
|
||||||
|
|
||||||
2002-07-08 11:32 jgoerzen
|
2002-07-08 11:32 jgoerzen
|
||||||
|
|
||||||
* debian/changelog, offlineimap/folder/IMAP.py,
|
* debian/changelog, offlineimap/folder/IMAP.py,
|
||||||
|
@ -1,3 +1,16 @@
|
|||||||
|
offlineimap (2.0.6) unstable; urgency=low
|
||||||
|
|
||||||
|
* Added support for holdconnectionopen and keepalive. This feature
|
||||||
|
allows for an IMAP server connection(s) to be held open until
|
||||||
|
the next sync process, permitting faster restart times.
|
||||||
|
* Another try at read-only folder support. This is nasty because I
|
||||||
|
have no way to test it and imaplib's read-only support is weird.
|
||||||
|
* Closing out old bug; fixed in 1.0.2. Closes: #150803.
|
||||||
|
* Optimized algorithm so that a SELECT is never issued for folders
|
||||||
|
that contain no messages.
|
||||||
|
|
||||||
|
-- John Goerzen <jgoerzen@complete.org> Tue, 9 Jul 2002 20:05:24 -0500
|
||||||
|
|
||||||
offlineimap (2.0.5) unstable; urgency=low
|
offlineimap (2.0.5) unstable; urgency=low
|
||||||
|
|
||||||
* Fixed a folderfilter example. Partially fixes #152079.
|
* Fixed a folderfilter example. Partially fixes #152079.
|
||||||
|
@ -215,3 +215,19 @@ remoteuser = username
|
|||||||
|
|
||||||
maxconnections = 1
|
maxconnections = 1
|
||||||
|
|
||||||
|
# OfflineIMAP normally closes IMAP server connections between refreshes if
|
||||||
|
# the global option autorefresh is specified. If you wish it to keep the
|
||||||
|
# connection open, set this to true. If not specified, the default is
|
||||||
|
# false. Keeping the connection open means a faster sync start the
|
||||||
|
# next time and may use fewer server resources on connection, but uses
|
||||||
|
# more server memory. This setting has no effect if autorefresh is not set.
|
||||||
|
|
||||||
|
holdconnectionopen = no
|
||||||
|
|
||||||
|
# If you want to have "keepalives" sent while waiting between syncs,
|
||||||
|
# specify the amount of time IN SECONDS between keepalives here. Note that
|
||||||
|
# sometimes more than this amount of time might pass, so don't make it
|
||||||
|
# tight. This setting has no effect if autorefresh and holdconnectionopen
|
||||||
|
# are not both set.
|
||||||
|
|
||||||
|
# keepalive = 60
|
||||||
|
@ -74,6 +74,8 @@ for account in accounts:
|
|||||||
|
|
||||||
mailboxes = []
|
mailboxes = []
|
||||||
mailboxlock = Lock()
|
mailboxlock = Lock()
|
||||||
|
servers = {}
|
||||||
|
|
||||||
def addmailbox(accountname, remotefolder):
|
def addmailbox(accountname, remotefolder):
|
||||||
mailboxlock.acquire()
|
mailboxlock.acquire()
|
||||||
mailboxes.append({'accountname' : accountname,
|
mailboxes.append({'accountname' : accountname,
|
||||||
@ -88,28 +90,14 @@ def syncaccount(accountname, *args):
|
|||||||
accountmetadata = os.path.join(metadatadir, accountname)
|
accountmetadata = os.path.join(metadatadir, accountname)
|
||||||
if not os.path.exists(accountmetadata):
|
if not os.path.exists(accountmetadata):
|
||||||
os.mkdir(accountmetadata, 0700)
|
os.mkdir(accountmetadata, 0700)
|
||||||
host = config.get(accountname, "remotehost")
|
|
||||||
user = config.get(accountname, "remoteuser")
|
|
||||||
port = None
|
|
||||||
if config.has_option(accountname, "remoteport"):
|
|
||||||
port = config.getint(accountname, "remoteport")
|
|
||||||
ssl = config.getboolean(accountname, "ssl")
|
|
||||||
usetunnel = config.has_option(accountname, "preauthtunnel")
|
|
||||||
reference = '""'
|
|
||||||
if config.has_option(accountname, "reference"):
|
|
||||||
reference = config.get(accountname, "reference")
|
|
||||||
|
|
||||||
server = None
|
server = None
|
||||||
# Connect to the remote server.
|
if accountname in servers:
|
||||||
if usetunnel:
|
server = servers[accountname]
|
||||||
server = imapserver.IMAPServer(tunnel = tunnels[accountname],
|
|
||||||
reference = reference,
|
|
||||||
maxconnections = config.getint(accountname, "maxconnections"))
|
|
||||||
else:
|
else:
|
||||||
server = imapserver.IMAPServer(user, passwords[accountname],
|
server = imapserver.ConfigedIMAPServer(config, accountname, passwords)
|
||||||
host, port, ssl,
|
servers[accountname] = server
|
||||||
config.getint(accountname, "maxconnections"),
|
|
||||||
reference = reference)
|
|
||||||
remoterepos = repository.IMAP.IMAPRepository(config, accountname, server)
|
remoterepos = repository.IMAP.IMAPRepository(config, accountname, server)
|
||||||
|
|
||||||
# Connect to the Maildirs.
|
# Connect to the Maildirs.
|
||||||
@ -134,7 +122,9 @@ def syncaccount(accountname, *args):
|
|||||||
thread.start()
|
thread.start()
|
||||||
folderthreads.append(thread)
|
folderthreads.append(thread)
|
||||||
threadutil.threadsreset(folderthreads)
|
threadutil.threadsreset(folderthreads)
|
||||||
server.close()
|
if not (config.has_option(accountname, 'holdconnectionopen') and \
|
||||||
|
config.getboolean(accountname, 'holdconnectionopen')):
|
||||||
|
server.close()
|
||||||
finally:
|
finally:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -213,9 +203,31 @@ def sync_with_timer():
|
|||||||
if config.has_option('general', 'autorefresh'):
|
if config.has_option('general', 'autorefresh'):
|
||||||
refreshperiod = config.getint('general', 'autorefresh') * 60
|
refreshperiod = config.getint('general', 'autorefresh') * 60
|
||||||
while 1:
|
while 1:
|
||||||
|
# Set up keep-alives.
|
||||||
|
kaevents = {}
|
||||||
|
kathreads = {}
|
||||||
|
for accountname in accounts:
|
||||||
|
if config.has_option(accountname, 'holdconnectionopen') and \
|
||||||
|
config.getboolean(accountname, 'holdconnectionopen') and \
|
||||||
|
config.has_option(accountname, 'keepalive'):
|
||||||
|
event = Event()
|
||||||
|
kaevents[accountname] = event
|
||||||
|
thread = ExitNotifyThread(target = servers[accountname].keepalive,
|
||||||
|
args = (config.getint(accountname, 'keepalive'), event))
|
||||||
|
thread.setDaemon(1)
|
||||||
|
thread.start()
|
||||||
|
kathreads[accountname] = thread
|
||||||
if ui.sleep(refreshperiod) == 2:
|
if ui.sleep(refreshperiod) == 2:
|
||||||
|
# Cancel keep-alives, but don't bother terminating threads
|
||||||
|
for event in kaevents.values():
|
||||||
|
event.set()
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
# Cancel keep-alives and wait for threads to terminate.
|
||||||
|
for event in kaevents.values():
|
||||||
|
event.set()
|
||||||
|
for thread in kathreads.values():
|
||||||
|
thread.join()
|
||||||
syncitall()
|
syncitall()
|
||||||
|
|
||||||
def threadexited(thread):
|
def threadexited(thread):
|
||||||
|
@ -59,8 +59,6 @@ class IMAPFolder(BaseFolder):
|
|||||||
def cachemessagelist(self):
|
def cachemessagelist(self):
|
||||||
imapobj = self.imapserver.acquireconnection()
|
imapobj = self.imapserver.acquireconnection()
|
||||||
try:
|
try:
|
||||||
# Needed for fetch below
|
|
||||||
imapobj.select(self.getfullname(), readonly = 1)
|
|
||||||
self.messagelist = {}
|
self.messagelist = {}
|
||||||
response = imapobj.status(self.getfullname(), '(MESSAGES)')[1][0]
|
response = imapobj.status(self.getfullname(), '(MESSAGES)')[1][0]
|
||||||
result = imaputil.imapsplit(response)[1]
|
result = imaputil.imapsplit(response)[1]
|
||||||
@ -69,6 +67,8 @@ class IMAPFolder(BaseFolder):
|
|||||||
# No messages? return.
|
# No messages? return.
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Needed for fetch below
|
||||||
|
imapobj.select(self.getfullname(), readonly = 1)
|
||||||
# Now, get the flags and UIDs for these.
|
# Now, get the flags and UIDs for these.
|
||||||
response = imapobj.fetch('1:%d' % maxmsgid, '(FLAGS UID)')[1]
|
response = imapobj.fetch('1:%d' % maxmsgid, '(FLAGS UID)')[1]
|
||||||
finally:
|
finally:
|
||||||
|
@ -28,13 +28,14 @@ class UsefulIMAPMixIn:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def select(self, mailbox='INBOX', readonly=None):
|
def select(self, mailbox='INBOX', readonly=None):
|
||||||
if self.getselectedfolder() == mailbox and not readonly:
|
if self.getselectedfolder() == mailbox:
|
||||||
|
self.is_readonly = readonly
|
||||||
# No change; return.
|
# No change; return.
|
||||||
return
|
return
|
||||||
result = self.__class__.__bases__[1].select(self, mailbox, readonly)
|
result = self.__class__.__bases__[1].select(self, mailbox, readonly)
|
||||||
if result[0] != 'OK':
|
if result[0] != 'OK':
|
||||||
raise ValueError, "Error from select: %s" % str(result)
|
raise ValueError, "Error from select: %s" % str(result)
|
||||||
if self.getstate() == 'SELECTED' and not readonly:
|
if self.getstate() == 'SELECTED':
|
||||||
self.selectedfolder = mailbox
|
self.selectedfolder = mailbox
|
||||||
else:
|
else:
|
||||||
self.selectedfolder = None
|
self.selectedfolder = None
|
||||||
@ -147,4 +148,70 @@ class IMAPServer:
|
|||||||
self.availableconnections = []
|
self.availableconnections = []
|
||||||
self.connectionlock.release()
|
self.connectionlock.release()
|
||||||
|
|
||||||
|
def keepalive(self, timeout, event):
|
||||||
|
"""Sends a NOOP to each connection recorded. It will wait a maximum
|
||||||
|
of timeout seconds between doing this, and will continue to do so
|
||||||
|
until the Event object as passed is true. This method is expected
|
||||||
|
to be invoked in a separate thread, which should be join()'d after
|
||||||
|
the event is set."""
|
||||||
|
while 1:
|
||||||
|
event.wait(timeout)
|
||||||
|
if event.isSet():
|
||||||
|
return
|
||||||
|
self.connectionlock.acquire()
|
||||||
|
numconnections = len(self.assignedconnections) + \
|
||||||
|
len(self.availableconnections)
|
||||||
|
self.connectionlock.release()
|
||||||
|
threads = []
|
||||||
|
imapobjs = []
|
||||||
|
|
||||||
|
for i in range(numconnections):
|
||||||
|
imapobj = self.acquireconnection()
|
||||||
|
imapobjs.append(imapobj)
|
||||||
|
thread = threadutil.ExitNotifyThread(target = imapobj.noop)
|
||||||
|
thread.setDaemon(1)
|
||||||
|
thread.start()
|
||||||
|
threads.append(thread)
|
||||||
|
|
||||||
|
for thread in threads:
|
||||||
|
# Make sure all the commands have completed.
|
||||||
|
thread.join()
|
||||||
|
|
||||||
|
for imapobj in imapobjs:
|
||||||
|
self.releaseconnection(imapobj)
|
||||||
|
|
||||||
|
class ConfigedIMAPServer(IMAPServer):
|
||||||
|
"""This class is designed for easier initialization given a ConfigParser
|
||||||
|
object and an account name. The passwordhash is used if
|
||||||
|
passwords for certain accounts are known. If the password for this
|
||||||
|
account is listed, it will be obtained from there."""
|
||||||
|
def __init__(self, config, accountname, passwordhash = {}):
|
||||||
|
"""Initialize the object. If the account is not a tunnel,
|
||||||
|
the password is required."""
|
||||||
|
host = config.get(accountname, "remotehost")
|
||||||
|
user = config.get(accountname, "remoteuser")
|
||||||
|
port = None
|
||||||
|
if config.has_option(accountname, "remoteport"):
|
||||||
|
port = config.getint(accountname, "remoteport")
|
||||||
|
ssl = config.getboolean(accountname, "ssl")
|
||||||
|
usetunnel = config.has_option(accountname, "preauthtunnel")
|
||||||
|
reference = '""'
|
||||||
|
if config.has_option(accountname, "reference"):
|
||||||
|
reference = config.get(accountname, "reference")
|
||||||
|
server = None
|
||||||
|
password = None
|
||||||
|
if accountname in passwordhash:
|
||||||
|
password = passwordhash[accountname]
|
||||||
|
|
||||||
|
# Connect to the remote server.
|
||||||
|
if usetunnel:
|
||||||
|
IMAPServer.__init__(self,
|
||||||
|
tunnel = config.get(accountname, "preauthtunnel"),
|
||||||
|
reference = reference,
|
||||||
|
maxconnections = config.getint(accountname, "maxconnections"))
|
||||||
|
else:
|
||||||
|
if not password:
|
||||||
|
password = config.get(accountname, 'remotepass')
|
||||||
|
IMAPServer.__init__(self, user, password, host, port, ssl,
|
||||||
|
config.getint(accountname, "maxconnections"),
|
||||||
|
reference = reference)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
productname = 'OfflineIMAP'
|
productname = 'OfflineIMAP'
|
||||||
versionstr = "2.0.5"
|
versionstr = "2.0.6"
|
||||||
|
|
||||||
versionlist = versionstr.split(".")
|
versionlist = versionstr.split(".")
|
||||||
major = versionlist[0]
|
major = versionlist[0]
|
||||||
|
Loading…
Reference in New Issue
Block a user