offlineimap rev 540
"Automatic Subversion Change Mailer" <[email protected]> Mon, 28 Jul 2003 14:02:39 -0500 (CDT)
| Newsgroups | gmane.mail.imap.offlineimap.subversion |
|---|---|
| Message-ID | <[email protected]> |
You are receiving this message because
all commits get sent to this address.
Author: jgoerzen
Date: 2003-07-28 14:02:02 -0500 (Mon, 28 Jul 2003)
New Revision: 540
Modified:
offlineimap/branches/twisted/TODO
offlineimap/branches/twisted/offlineimap/folder/Base.py
offlineimap/branches/twisted/offlineimap/folder/IMAP.py
offlineimap/branches/twisted/offlineimap/imaputil.py
Log:
Made a bit more progress
Diff:
Added: offlineimap/branches/twisted/TODO
==============================================================================
--- offlineimap/branches/twisted/TODO 2003-07-28 15:49:43 UTC (rev 539)
+++ offlineimap/branches/twisted/TODO 2003-07-28 19:02:02 UTC (rev 540)
@@ -0,0 +1 @@
+Test with multiple folders
Modified: offlineimap/branches/twisted/offlineimap/folder/Base.py
==============================================================================
--- offlineimap/branches/twisted/offlineimap/folder/Base.py 2003-07-28 15:49:43 UTC (rev 539)
+++ offlineimap/branches/twisted/offlineimap/folder/Base.py 2003-07-28 19:02:02 UTC (rev 540)
@@ -139,7 +139,9 @@
raise NotImplementedException
def getmessage(self, uid):
- """Returns the content of the specified message."""
+ """Returns the content of the specified message.
+
+ Returns Deferred"""
raise NotImplementedException
def savemessage(self, uid, content, flags):
@@ -224,31 +226,66 @@
if register:
UIBase.getglobalui().registerthread(self.getaccountname())
UIBase.getglobalui().copyingmessage(uid, self, applyto)
+ d = self.getmessage(uid)
+ d.addCallback(self.syncmessagesto_neguid_msg_worker, uid, dest, applyto,
+ register)
+
+ def syncmessagesto_neguid_worker(self, message, uid, dest, applyto,
+ register):
successobject = None
successuid = None
- message = self.getmessage(uid)
+ #message = self.getmessage(uid) Now passed in
flags = self.getmessageflags(uid)
- for tryappend in applyto:
- successuid = tryappend.savemessage(uid, message, flags)
- if successuid >= 0:
- successobject = tryappend
- break
- # Did we succeed?
- if successobject != None:
- if successuid: # Only if IMAP actually assigned a UID
- # Copy the message to the other remote servers.
- for appendserver in \
- [x for x in applyto if x != successobject]:
- appendserver.savemessage(successuid, message, flags)
- # Copy to its new name on the local server and delete
- # the one without a UID.
- self.savemessage(successuid, message, flags)
- self.deletemessage(uid) # It'll be re-downloaded.
- else:
- # Did not find any server to take this message. Ignore.
- pass
+ return syncmessagesto_neguid_tryappend(0, None,
+ trylist, flags, message, uid, dest,
+ applyto, register)
+
+ def syncmessagesto_neguid_tryappend(self, successuid, lasttry,
+ trylist, flags,
+ message, uid, dest, applyto, register):
+ if successuid >= 0:
+ # Last server took this message. Proceed.
+ return syncmessagesto_neguid_realappend(successuid, lasttry,
+ flags, message, uid, dest, applyto, register)
+ if not len(trylist):
+ # Did not find any server to take thie message. Ignore.
+ return
+
+ # Process the next one.
+ tryappend = trylist[0]
+ trylist = trylist[1:]
+ d = tryappend.savemessage(uid, message, flags)
+ d.addCallback(self.syncmessagesto_neguid_tryappend,
+ tryappend, trylist, flags, message, uid, dest,
+ applyto, register)
+ return d
+
+
+ def syncmessagesto_neguid_realappend(self, successuid, successobject,
+ flags, message, uid, dest, applyto,
+ register):
+ # Did we succeed?
+ #if successobject != None: Assumed given above logic
+ #
+ # I'm not so sure about this successuid thing....
+ deferreds = []
+ if successuid: # Only if IMAP actually assigned a UID
+ # Copy the message to the other remote servers.
+ for appendserver in \
+ [x for x in applyto if x != successobject]:
+ d = appendserver.savemessage(successuid, message, flags)
+ deferreds.append(d)
+ # Copy to its new name on the local server and delete
+ # the one without a UID.
+ # Why was this indented another level before?
+ d = self.savemessage(successuid, message, flags)
+ deferreds.append(d)
+ d = self.deletemessage(uid) # It'll be re-downloaded.
+ deferreds.append(d)
+ return defer.DeferredList(deferreds)
+
def syncmessagesto_neguid(self, dest, applyto):
"""Pass 1 of folder synchronization.
@@ -279,24 +316,44 @@
# really needed.
if register:
UIBase.getglobalui().registerthread(self.getaccountname())
+ print uid
+ print type(uid)
+ flags = self.getmessageflags(uid)
UIBase.getglobalui().copyingmessage(uid, self, applyto)
message = ''
# If any of the destinations actually stores the message body,
# load it up.
for object in applyto:
if object.storesmessages():
- message = self.getmessage(uid)
- break
- flags = self.getmessageflags(uid)
- for object in applyto:
- newuid = object.savemessage(uid, message, flags)
- if newuid > 0 and newuid != uid:
- # Change the local uid.
- self.savemessage(newuid, message, flags)
- self.deletemessage(uid)
- uid = newuid
-
+ d = self.getmessage(uid)
+ d.addCallback(self.copymessageto_worker, uid, applyto, flags)
+ return d
+ return self.copymessageto_worker('', uid, applyto, flags)
+ def copymessageto_worker(self, message, uid, applyto, flags):
+ if len(applyto) == 0:
+ return
+
+ object = applyto[0]
+ d = object.savemessage(uid, message, flags)
+ d.addCallback(self.copymessageto_saveuid, message, uid, applyto[1:],
+ flags)
+ return d
+
+ def copymessageto_saveuid(self, newuid, message, uid, applyto, flags):
+ if newuid > 0 and newuid != uid:
+ # Change the local uid.
+ d = self.savemessage(newuid, message, flags)
+ d.addCallback(lambda x, uid: self.deletemessage(uid),
+ uid)
+ uid = newuid
+ d.addCallback(lambda x, message, uid, applyto, flags:
+ self.copymessageto_worker(message, uid, applyto, flags),
+ message, uid, applyto, flags)
+ return d
+ else:
+ return self.copymessageto_worker(message, uid, applyto, flags)
+
def syncmessagesto_copy(self, dest, applyto):
"""Pass 2 of folder synchronization.
Modified: offlineimap/branches/twisted/offlineimap/folder/IMAP.py
==============================================================================
--- offlineimap/branches/twisted/offlineimap/folder/IMAP.py 2003-07-28 15:49:43 UTC (rev 539)
+++ offlineimap/branches/twisted/offlineimap/folder/IMAP.py 2003-07-28 19:02:02 UTC (rev 540)
@@ -100,13 +100,12 @@
# maindefer.callback(None)
# return
# FIXME: not yet as robust as below.
- print self.getname(), "flags_uids", flags_uids
- flags, uids = flags_uids
- flags = flags[1]
+ flagshash, uids = flags_uids
+ flagshash = flagshash[1]
uids = uids[1]
- for msg in flags.keys():
- flags = imaputil.flagsimap2maildir(flags)
- uid = uids[msg]
+ for msg in flagshash.keys():
+ flags = imaputil.flagsimap2maildir(flagshash[msg]['FLAGS'])
+ uid = long(uids[msg]['UID'])
self.messagelist[uid] = {'uid': uid, 'flags': flags}
print self.getname(), "Cached at", self.messagelist
@@ -132,12 +131,19 @@
def getmessage(self, uid):
imapobj = self.imapserver.acquireconnection()
- try:
- imapobj.select(self.getfullname(), readonly = 1)
- return imapobj.uid('fetch', '%d' % uid, '(BODY.PEEK[])')[1][0][1].replace("\r\n", "\n")
- finally:
- self.imapserver.releaseconnection(imapobj)
-
+ d = imapobj.examine(self.getfullname())
+ d.addCallback(lambda x, uid, useuid, hdr: \
+ imapobj.fetchSpecific(uid, useuid, hdr),
+ str(uid), 1, 'BODY.PEEK[]')
+ d.addCallback(self.getmessage_process)
+ return d
+
+ def getmessage_process(self, message):
+ print "getmessage_process: message is", message
+ key = message.keys()[0]
+ print "returning", message[key]
+ return message[key].replace("\r\n", "\n")
+
def getmessageflags(self, uid):
return self.messagelist[uid]['flags']
@@ -195,88 +201,105 @@
return long(matchinguids[0])
def savemessage(self, uid, content, flags):
- imapobj = self.imapserver.acquireconnection()
+ d = self.imapserver.acquireconnection()
+ d.addCallback(self.savemessage_step1, uid, content, flags)
+ return d
+
+ def savemessage_step1(self, imapobj, uid, content, flags):
ui = UIBase.getglobalui()
- ui.debug('imap', 'savemessage: called')
+ ui.debug('imap', 'savemessage_step1: called')
+ d = imapobj.select(self.getfullname())
+ d.addCallback(self.savemessage_step2, imapobj, uid, content, flags)
+
+ def savemessage_step2(self, ignore, imapobj, uid, content, flags):
+ # This backend always assigns a new uid, so the uid arg is ignored.
+ # In order to get the new uid, we need to save off the message ID.
+
+ message = rfc822.Message(StringIO(content))
+ datetuple = rfc822.parsedate(message.getheader('Date'))
+ # Will be None if missing or not in a valid format.
+ if datetuple == None:
+ datetuple = time.localtime()
try:
- try:
- imapobj.select(self.getfullname()) # Needed for search
- except imapobj.readonly:
- ui.msgtoreadonly(self, uid, content, flags)
- # Return indicating message taken, but no UID assigned.
- # Fudge it.
- return 0
-
- # This backend always assigns a new uid, so the uid arg is ignored.
- # In order to get the new uid, we need to save off the message ID.
+ if datetuple[0] < 1981:
+ raise ValueError
+ # This could raise a value error if it's not a valid format.
+ date = imaputil.Time2Internaldate(datetuple)
+ except ValueError:
+ # Argh, sometimes it's a valid format but year is 0102
+ # or something. Argh. It seems that Time2Internaldate
+ # will rause a ValueError if the year is 0102 but not 1902,
+ # but some IMAP servers nonetheless choke on 1902.
+ date = imaputil.Time2Internaldate(time.localtime())
- message = rfc822.Message(StringIO(content))
- datetuple = rfc822.parsedate(message.getheader('Date'))
- # Will be None if missing or not in a valid format.
- if datetuple == None:
- datetuple = time.localtime()
- try:
- if datetuple[0] < 1981:
- raise ValueError
- # This could raise a value error if it's not a valid format.
- date = imaplib.Time2Internaldate(datetuple)
- except ValueError:
- # Argh, sometimes it's a valid format but year is 0102
- # or something. Argh. It seems that Time2Internaldate
- # will rause a ValueError if the year is 0102 but not 1902,
- # but some IMAP servers nonetheless choke on 1902.
- date = imaplib.Time2Internaldate(time.localtime())
+ ui.debug('imap', 'savemessage: using date ' + str(date))
+ content = re.sub("(?<!\r)\n", "\r\n", content)
+ ui.debug('imap', 'savemessage: initial content is: ' + repr(content))
- ui.debug('imap', 'savemessage: using date ' + str(date))
- content = re.sub("(?<!\r)\n", "\r\n", content)
- ui.debug('imap', 'savemessage: initial content is: ' + repr(content))
+ (headername, headervalue) = self.savemessage_getnewheader(content)
+ ui.debug('imap', 'savemessage: new headers are: %s: %s' % \
+ (headername, headervalue))
+ content = self.savemessage_addheader(content, headername,
+ headervalue)
+ ui.debug('imap', 'savemessage: new content is: ' + repr(content))
+ ui.debug('imap', 'savemessage: new content length is ' + \
+ str(len(content)))
- (headername, headervalue) = self.savemessage_getnewheader(content)
- ui.debug('imap', 'savemessage: new headers are: %s: %s' % \
- (headername, headervalue))
- content = self.savemessage_addheader(content, headername,
- headervalue)
- ui.debug('imap', 'savemessage: new content is: ' + repr(content))
- ui.debug('imap', 'savemessage: new content length is ' + \
- str(len(content)))
+ d = imapobj.append(self.getfullname(),
+ StringIO(content),
+ imaputil.flagsmaildir2imap(flags),
+ date)
+ # Checkpoint. Let it write out the messages.
+ d.addCallback(lambda ignore: imapobj.check())
+ d.addCallback(self.savemessage_fetchuid, imapobj, headername, headervalue, flags, 0)
+ return d
- assert(imapobj.append(self.getfullname(),
- imaputil.flagsmaildir2imap(flags),
- date, content)[0] == 'OK')
+ def savemessage_fetchuid(self, ignore, imapobj, headername, headervalue,
+ flags, previousattempts):
+ ui.debug('imap', 'savemessage: attempt %d to get new UID' \
+ % previousattempts)
+ d = self.savemessage_searchforheader(imapobj, headername,
+ headervalue)
+ if previousattempts == 1:
+ # This is our last try.
+ d.addCallback(self.savemessage_register, flags)
+ return d
- # Checkpoint. Let it write out the messages, etc.
- assert(imapobj.check()[0] == 'OK')
+ d.addCallback(self.savemessage_tryregister, imapobj, headername,
+ headervalue, flags, previousattempts)
+ return d
- # Keep trying until we get the UID.
- try:
- ui.debug('imap', 'savemessage: first attempt to get new UID')
- uid = self.savemessage_searchforheader(imapobj, headername,
- headervalue)
- except ValueError:
- ui.debug('imap', 'savemessage: first attempt to get new UID failed. Going to run a NOOP and try again.')
- assert(imapobj.noop()[0] == 'OK')
- uid = self.savemessage_searchforheader(imapobj, headername,
- headervalue)
- finally:
- self.imapserver.releaseconnection(imapobj)
+ def savemessage_tryregister(self, uid, imapobj, headername, headervalue,
+ flags, previousattempts):
+ if not uid:
+ d = imapobj.noop()
+ d.addCallback(self.savemessage_fetchuid, imapobj, headername,
+ headervalue, flags,
+ previousattempts + 1)
+ return d
+ else:
+ return self.savemessage_register(None, uid, flags)
+ def savemessage_register(self, ignore, uid, flags):
+ #self.imapserver.releaseconnection(imapobj)
self.messagelist[uid] = {'uid': uid, 'flags': flags}
ui.debug('imap', 'savemessage: returning %d' % uid)
return uid
def savemessageflags(self, uid, flags):
imapobj = self.imapserver.acquireconnection()
- try:
- try:
- imapobj.select(self.getfullname())
- except imapobj.readonly:
- UIBase.getglobalui().flagstoreadonly(self, [uid], flags)
- return
- result = imapobj.uid('store', '%d' % uid, 'FLAGS',
- imaputil.flagsmaildir2imap(flags))
- assert result[0] == 'OK', 'Error with store: ' + r[1]
- finally:
- self.imapserver.releaseconnection(imapobj)
+ d = imapobj.select(self.getfullname())
+ d.addCallback(self.savemessageflags_worker, imapobj, uid, flags)
+ d.addCallback(self.savemessageflags_store, uid, flags)
+ return d
+
+ def savemessageflags_worker(self, ignore, imapobj, uid, flags):
+ return imapobj.setFlags(str(uid),
+ imaputil.flagsmaildir2imap(flags),
+ uid = 1)
+
+ def savemessageflags_store(self, result, uid, flags):
+ print "savemessageflags_store: result =", result
result = result[1][0]
if not result:
self.messagelist[uid]['flags'] = flags
Modified: offlineimap/branches/twisted/offlineimap/imaputil.py
==============================================================================
--- offlineimap/branches/twisted/offlineimap/imaputil.py 2003-07-28 15:49:43 UTC (rev 539)
+++ offlineimap/branches/twisted/offlineimap/imaputil.py 2003-07-28 19:02:02 UTC (rev 540)
@@ -19,6 +19,7 @@
import re, string, types
from offlineimap.ui import UIBase
from twisted.internet import defer
+from imaplib import Time2Internaldate, Internaldate2tuple
quotere = re.compile('^("(?:[^"]|\\\\")*")')
@@ -136,14 +137,14 @@
debug("imapsplit() returning:", retval)
return retval
-def flagsimap2maildir(flagstring):
+def flagsimap2maildir(imapflaglist):
flagmap = {'\\seen': 'S',
'\\answered': 'R',
'\\flagged': 'F',
'\\deleted': 'T',
'\\draft': 'D'}
retval = []
- imapflaglist = [x.lower() for x in flagstring[1:-1].split()]
+ imapflaglist = [x.lower() for x in imapflaglist]
for imapflag in imapflaglist:
if flagmap.has_key(imapflag):
retval.append(flagmap[imapflag])
@@ -161,7 +162,7 @@
if flagmap.has_key(mdflag):
retval.append(flagmap[mdflag])
retval.sort()
- return '(' + ' '.join(retval) + ')'
+ return retval
def listjoin(list):
start = None