Merge branch 'ss/better-error-throwing-and-id-sequence' into next

Conflicts:
	offlineimap/folder/IMAP.py
	offlineimap/imaputil.py

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2011-09-06 20:15:05 +02:00
commit 67863017e2
2 changed files with 49 additions and 56 deletions

View File

@ -110,76 +110,70 @@ class IMAPFolder(BaseFolder):
self.imapserver.releaseconnection(imapobj)
return False
# TODO: Make this so that it can define a date that would be the oldest messages etc.
def cachemessagelist(self):
imapobj = self.imapserver.acquireconnection()
maxage = self.config.getdefaultint("Account %s" % self.accountname,
"maxage", -1)
maxsize = self.config.getdefaultint("Account %s" % self.accountname,
"maxsize", -1)
self.messagelist = {}
imapobj = self.imapserver.acquireconnection()
try:
# Primes untagged_responses
imaptype, imapdata = imapobj.select(self.getfullname(), readonly = 1, force = 1)
res_type, imapdata = imapobj.select(self.getfullname(), True)
maxage = self.config.getdefaultint("Account " + self.accountname, "maxage", -1)
maxsize = self.config.getdefaultint("Account " + self.accountname, "maxsize", -1)
# By default examine all UIDs in this folder
msgsToFetch = '1:*'
if (maxage != -1) | (maxsize != -1):
try:
search_condition = "(";
search_cond = "(";
if(maxage != -1):
#find out what the oldest message is that we should look at
oldest_time_struct = time.gmtime(time.time() - (60*60*24*maxage))
if(maxage != -1):
#find out what the oldest message is that we should look at
oldest_struct = time.gmtime(time.time() - (60*60*24*maxage))
#format this manually - otherwise locales could cause problems
monthnames_standard = ["Jan", "Feb", "Mar", "Apr", "May", \
"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
#format months manually - otherwise locales cause problems
monthnames = ["Jan", "Feb", "Mar", "Apr", "May", \
"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
our_monthname = monthnames_standard[oldest_time_struct[1]-1]
daystr = "%(day)02d" % {'day' : oldest_time_struct[2]}
date_search_str = "SINCE " + daystr + "-" + our_monthname \
+ "-" + str(oldest_time_struct[0])
month = monthnames[oldest_struct[1]-1]
daystr = "%(day)02d" % {'day' : oldest_struct[2]}
search_condition += date_search_str
search_cond += "SINCE %s-%s-%s" % (daystr, month,
oldest_struct[0])
if(maxsize != -1):
if(maxage != -1): #There are two conditions - add a space
search_condition += " "
if(maxsize != -1):
if(maxage != -1): # There are two conditions, add space
search_cond += " "
search_cond += "SMALLER %d" % maxsize
search_condition += "SMALLER " + self.config.getdefault("Account " + self.accountname, "maxsize", -1)
search_cond += ")"
search_condition += ")"
searchresult = imapobj.search(None, search_condition)
res_type, res_data = imapobj.search(None, search_cond)
if res_type != 'OK':
raise OfflineImapError("SEARCH in folder [%s]%s failed. "
"Search string was '%s'. Server responded '[%s] %s'" % (
self.getrepository(), self,
search_cond, res_type, res_data),
OfflineImapError.ERROR.FOLDER)
#result would come back seperated by space - to change into a fetch
#statement we need to change space to comma
messagesToFetch = searchresult[1][0].replace(" ", ",")
except KeyError:
return
if len(messagesToFetch) < 1:
# No messages; return
return
else:
# 1. Some mail servers do not return an EXISTS response
# if the folder is empty. 2. ZIMBRA servers can return
# multiple EXISTS replies in the form 500, 1000, 1500,
# 1623 so check for potentially multiple replies.
if imapdata == [None]:
return
# Result UIDs are seperated by space, coalesce into ranges
msgsToFetch = imaputil.uid_sequence(res_data.split())
if not msgsToFetch:
return # No messages to sync
maxmsgid = 0
for msgid in imapdata:
maxmsgid = max(long(msgid), maxmsgid)
if maxmsgid < 1:
#no messages; return
return
messagesToFetch = '1:%d' % maxmsgid;
# Now, get the flags and UIDs for these.
# We could conceivably get rid of maxmsgid and just say
# '1:*' here.
response = imapobj.fetch(messagesToFetch, '(FLAGS UID)')[1]
# Get the flags and UIDs for these. single-quotes prevent
# imaplib2 from quoting the sequence.
res_type, response = imapobj.fetch("'%s'" % msgsToFetch,
'(FLAGS UID)')
if res_type != 'OK':
raise OfflineImapError("FETCHING UIDs in folder [%s]%s failed. "
"Server responded '[%s] %s'" % (
self.getrepository(), self,
res_type, response),
OfflineImapError.ERROR.FOLDER)
finally:
self.imapserver.releaseconnection(imapobj)
for messagestr in response:
# looks like: '1 (FLAGS (\\Seen Old) UID 4807)' or None if no msg
# Discard initial message number.

View File

@ -191,10 +191,8 @@ def flagsmaildir2imap(maildirflaglist):
def uid_sequence(uidlist):
"""Collapse UID lists into shorter sequence sets
[1,2,3,4,5,10,12,13] will return "1:5,10,12:13". This function
converts items to numeric type and sorts the list to always produce
the minimal collapsed set.
[1,2,3,4,5,10,12,13] will return "1:5,10,12:13". This function sorts
the list, and only collapses if subsequent entries form a range.
:returns: The collapsed UID list as string"""
def getrange(start, end):
if start == end:
@ -208,6 +206,7 @@ def uid_sequence(uidlist):
sorted_uids = sorted(map(int, uidlist))
for item in iter(sorted_uids):
item = int(item)
if start == None: # First item
start, end = item, item
elif item == end + 1: # Next item in a range