plugin IMAP, plugin Maildir: added flag, IMAP's uid management

This commit is contained in:
Goffi 2011-01-17 21:26:16 +01:00
commit f3565fa4a8
2 changed files with 175 additions and 63 deletions

View file

@ -70,7 +70,7 @@ class MaildirBox():
#the trigger
host.trigger.add("MessageReceived", self.MessageReceivedTrigger)
def __destroy__(self):
def __del__(self):
debug('Destroying MaildirBox')
self.host.memory.setPrivate('MAILDIR_data',self.data)
@ -103,39 +103,37 @@ class MaildirBox():
if self.__mailboxes.has_key(boxname):
return self.__mailboxes[boxname]
def __getBoxData(self, boxname):
"""Return the date of a box"""
try:
return self.data[boxname] #the boxname MUST exist in the data
except KeyError:
err_msg=_("Boxname doesn't exist in internal data")
error(_("INTERNAL ERROR: ") + err_msg)
raise MaildirError(err_msg)
def getUid(self, boxname, message_id):
"""Return an unique integer, always ascending, for a message
This is mainly needed for the IMAP protocol
@param boxname: name of the box where the message is
@param message_id: unique id of the message as given by MaildirMailbox
@return: Integer UID"""
try:
box_data = self.data[boxname] #the boxname MUST exist in the data
except KeyError:
err_msg=_("Boxname doesn't exist in internal data")
error(_("INTERNAL ERROR: ") + err_msg)
raise MaildirError(err_msg)
box_data = self.__getBoxData(boxname)
if box_data.has_key(message_id):
ret = box_data[message_id][0]
else:
box_data['cur_idx']+=1
box_data[message_id]=(box_data['cur_idx'],[])
box_data[message_id]=[box_data['cur_idx'],[]]
ret = box_data[message_id]
self.host.memory.setPrivate('MAILDIR_data',self.data)
return ret
def getNextUid(self, boxname):
"""Return next unique integer that will generated
This is mainly needed for the IMAP protocol
@param boxname: name of the box where the message is
@return: Integer UID"""
try:
box_data = self.data[boxname] #the boxname MUST exist in the data
except KeyError:
err_msg=_("Boxname doesn't exist in internal data")
error(_("INTERNAL ERROR: ") + err_msg)
raise MaildirError(err_msg)
box_data = self.__getBoxData(boxname)
return box_data['cur_idx']+1
def getNextExistingUid(self, boxname, uid):
@ -143,14 +141,9 @@ class MaildirBox():
@param boxname: name of the box where the message is
@param uid: uid to start from
@return: uid or None if the is no more message"""
try:
box_data = self.data[boxname] #the boxname MUST exist in the data
except KeyError:
err_msg=_("Boxname doesn't exist in internal data")
error(_("INTERNAL ERROR: ") + err_msg)
raise MaildirError(err_msg)
box_data = self.__getBoxData(boxname)
idx=uid+1
while self.getIdfromUid(boxname, idx) == None: #TODO: this is highly inefficient because getIdfromUid is inefficient, fix this
while self.getIdFromUid(boxname, idx) == None: #TODO: this is highly inefficient because getIdfromUid is inefficient, fix this
idx+=1
if idx>box_data['cur_idx']:
return None
@ -160,27 +153,15 @@ class MaildirBox():
"""Give the max existing uid
@param boxname: name of the box where the message is
@return: uid"""
try:
box_data = self.data[boxname] #the boxname MUST exist in the data
except KeyError:
err_msg=_("Boxname doesn't exist in internal data")
error(_("INTERNAL ERROR: ") + err_msg)
raise MaildirError(err_msg)
box_data = self.__getBoxData(boxname)
return box_data['cur_idx']
def getIdfromUid(self, boxname, message_uid):
def getIdFromUid(self, boxname, message_uid):
"""Return the message unique id from it's integer UID
@param boxname: name of the box where the message is
@param message_uid: unique integer identifier
@return: unique id of the message as given by MaildirMailbox or None if not found"""
try:
box_data = self.data[boxname] #the boxname MUST exist in the data
except KeyError:
err_msg=_("Boxname doesn't exist in internal data")
error(_("INTERNAL ERROR: ") + err_msg)
raise MaildirError(err_msg)
box_data = self.__getBoxData(boxname)
for message_id in box_data.keys(): #TODO: this is highly inefficient on big mailbox, must be replaced in the future
if message_id == 'cur_idx':
continue
@ -188,16 +169,58 @@ class MaildirBox():
return message_id
return None
def getFlags(self, boxname, mess_id):
"""Return the messages flags
@param boxname: name of the box where the message is
@param message_idx: message id as given by MaildirMailbox
@return: list of strings"""
box_data = self.__getBoxData(boxname)
if not box_data.has_key(mess_id):
raise MailboxException("Trying to get flags from an unexisting message")
return box_data[mess_id][1]
def setFlags(self, boxname, mess_id, flags):
"""Change the flags of the message
@param boxname: name of the box where the message is
@param message_idx: message id as given by MaildirMailbox
@param flags: list of strings
"""
box_data = self.__getBoxData(boxname)
assert(type(flags)==list)
if not box_data.has_key(mess_id):
raise MailboxException("Trying to set flags for an unexisting message")
box_data[mess_id][1]=flags
self.host.memory.setPrivate('MAILDIR_data',self.data)
def getMessageIdsWithFlag(self, boxname, flag):
"""Return ids of messages where a flag is set
@param boxname: name of the box where the message is
@param flag: flag to check
@return: list of id (as given by MaildirMailbox)"""
box_data = self.__getBoxData(boxname)
assert(isinstance(flag,basestring))
result = []
for key in box_data:
if key=='cur_idx':
continue
if flag in box_data[key][1]:
result.append(key)
return result
def purgeDeleted(self, boxname):
"""Remove data for messages with flag "\\Deleted"
@param boxname: name of the box where the message is
"""
box_data = self.__getBoxData(boxname)
for mess_id in self.getMessageIdsWithFlag(boxname,"\\Deleted"):
del(box_data[mess_id])
self.host.memory.setPrivate('MAILDIR_data',self.data)
def cleanTable(self, boxname, existant_id):
"""Remove mails which no longuer exist from the table
@param boxname: name of the box to clean
@param existant_id: list of id which actually exist"""
try:
box_data = self.data[boxname] #the boxname MUST exist in the data
except KeyError:
err_msg=_("Boxname doesn't exist in internal data")
error(_("INTERNAL ERROR: ") + err_msg)
raise MaildirError(err_msg)
box_data = self.__getBoxData(boxname)
to_remove=[]
for key in box_data:
if key not in existant_id and key!="cur_idx":
@ -312,7 +335,7 @@ class MailboxUser:
self.maildir.cleanTable(self.name, existant_id)
def __destroy__(self):
def __del__(self):
if observer:
debug("removing observer for %s" % self.name)
self._maildir.removeObserver(observer, self.name, "NEW_MESSAGE")
@ -355,16 +378,83 @@ class MailboxUser:
"""Return the full message
@mess_idx: message index"""
return self.mailbox.getMessage(mess_idx)
def getIdxFromUid(self, mess_uid):
"""Return the message index from the uid
@param mess_uid: message unique identifier
@return: message index, as managed by MaildirMailbox"""
for mess_idx in range (self.getMessageCount()):
if self.getUid(mess_idx) == mess_uid:
return mess_idx
raise IndexError
def getIdxFromId(self, mess_id):
"""Return the message index from the unique index
@param mess_id: message unique index as given by MaildirMailbox
@return: message sequence index"""
for mess_idx in range (self.getMessageCount()):
if self.mailbox.getUidl(mess_idx) == mess_id:
return mess_idx
raise IndexError
def getMessage(self, mess_idx):
"""Return the full message
@mess_idx: message index"""
@param mess_idx: message index"""
return self.mailbox.getMessage(mess_idx)
def getMessageUid(self, mess_uid):
"""Return the full message
@mess_idx: message unique identifier"""
for mess_idx in range (self.getMessageCount()):
if self.getUid(mess_idx) == mess_uid:
return self.mailbox.getMessage(mess_idx)
raise IndexError
@param mess_idx: message unique identifier"""
return self.mailbox.getMessage(self.getIdxFromUid(mess_uid))
def getFlags(self, mess_idx):
"""Return the flags of the message
@param mess_idx: message index
@return: list of strings"""
id = self.getId(mess_idx)
return self.maildir.getFlags(self.name, id)
def getFlagsUid(self, mess_uid):
"""Return the flags of the message
@param mess_uid: message unique identifier
@return: list of strings"""
id = self.maildir.getIdFromUid(self.name,mess_uid)
return self.maildir.getFlags(self.name, id)
def setFlags(self, mess_idx, flags):
"""Change the flags of the message
@param mess_idx: message index
@param flags: list of strings
"""
id = self.getId(mess_idx)
return self.maildir.setFlags(self.name, id, flags)
def setFlagsUid(self, mess_uid, flags):
"""Change the flags of the message
@param mess_uid: message unique identifier
@param flags: list of strings
"""
id = self.maildir.getIdFromUid(self.name,mess_uid)
return self.maildir.setFlags(self.name, id, flags)
def getMessageIdsWithFlag(self, flag):
"""Return ids of messages where a flag is set
@param flag: flag to check
@return: list of id (as given by MaildirMailbox)"""
return self.maildir.getMessageIdsWithFlag(self.name,flag)
def removeDeleted(self):
"""Actually delete message flagged "\\Deleted"
Also purge the internal data of these messages
"""
for mess_id in self.getMessageIdsWithFlag("\\Deleted"):
print ("Deleting %s", mess_id)
self.mailbox.deleteMessage(self.getIdxFromId(mess_id))
self.mailbox = maildir.MaildirMailbox(self.mailbox_path) #We need to reparse the dir to have coherent indexing
self.maildir.purgeDeleted(self.name)
def emptyTrash(self):
"""Delete everything in the .Trash dir"""
import shutils
pdb.set_trace()