Mercurial > libervia-backend
comparison src/plugins/plugin_misc_maildir.py @ 255:55b750017b71
plugin IMAP, plugin Maildir: added flag, IMAP's uid management
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 17 Jan 2011 21:26:16 +0100 |
parents | 9fc32d1d9046 |
children | 012c38b56cdd |
comparison
equal
deleted
inserted
replaced
254:9fc32d1d9046 | 255:55b750017b71 |
---|---|
68 # - message_id (as returned by MaildirMailbox): a tuple of (UID, [flag1, flag2, ...]) | 68 # - message_id (as returned by MaildirMailbox): a tuple of (UID, [flag1, flag2, ...]) |
69 | 69 |
70 #the trigger | 70 #the trigger |
71 host.trigger.add("MessageReceived", self.MessageReceivedTrigger) | 71 host.trigger.add("MessageReceived", self.MessageReceivedTrigger) |
72 | 72 |
73 def __destroy__(self): | 73 def __del__(self): |
74 debug('Destroying MaildirBox') | 74 debug('Destroying MaildirBox') |
75 self.host.memory.setPrivate('MAILDIR_data',self.data) | 75 self.host.memory.setPrivate('MAILDIR_data',self.data) |
76 | 76 |
77 def accessMessageBox(self, boxname, observer=None): | 77 def accessMessageBox(self, boxname, observer=None): |
78 """Create and return a MailboxUser instance | 78 """Create and return a MailboxUser instance |
101 @param boxname: name of the box to check | 101 @param boxname: name of the box to check |
102 @return: MailboxUser instance or None""" | 102 @return: MailboxUser instance or None""" |
103 if self.__mailboxes.has_key(boxname): | 103 if self.__mailboxes.has_key(boxname): |
104 return self.__mailboxes[boxname] | 104 return self.__mailboxes[boxname] |
105 | 105 |
106 def getUid(self, boxname, message_id): | 106 def __getBoxData(self, boxname): |
107 """Return an unique integer, always ascending, for a message | 107 """Return the date of a box""" |
108 This is mainly needed for the IMAP protocol | |
109 @param boxname: name of the box where the message is | |
110 @param message_id: unique id of the message as given by MaildirMailbox | |
111 @return: Integer UID""" | |
112 try: | 108 try: |
113 box_data = self.data[boxname] #the boxname MUST exist in the data | 109 return self.data[boxname] #the boxname MUST exist in the data |
114 except KeyError: | 110 except KeyError: |
115 err_msg=_("Boxname doesn't exist in internal data") | 111 err_msg=_("Boxname doesn't exist in internal data") |
116 error(_("INTERNAL ERROR: ") + err_msg) | 112 error(_("INTERNAL ERROR: ") + err_msg) |
117 raise MaildirError(err_msg) | 113 raise MaildirError(err_msg) |
114 | |
115 def getUid(self, boxname, message_id): | |
116 """Return an unique integer, always ascending, for a message | |
117 This is mainly needed for the IMAP protocol | |
118 @param boxname: name of the box where the message is | |
119 @param message_id: unique id of the message as given by MaildirMailbox | |
120 @return: Integer UID""" | |
121 box_data = self.__getBoxData(boxname) | |
118 if box_data.has_key(message_id): | 122 if box_data.has_key(message_id): |
119 ret = box_data[message_id][0] | 123 ret = box_data[message_id][0] |
120 else: | 124 else: |
121 box_data['cur_idx']+=1 | 125 box_data['cur_idx']+=1 |
122 box_data[message_id]=(box_data['cur_idx'],[]) | 126 box_data[message_id]=[box_data['cur_idx'],[]] |
123 ret = box_data[message_id] | 127 ret = box_data[message_id] |
124 self.host.memory.setPrivate('MAILDIR_data',self.data) | 128 self.host.memory.setPrivate('MAILDIR_data',self.data) |
125 return ret | 129 return ret |
126 | 130 |
127 | |
128 def getNextUid(self, boxname): | 131 def getNextUid(self, boxname): |
129 """Return next unique integer that will generated | 132 """Return next unique integer that will generated |
130 This is mainly needed for the IMAP protocol | 133 This is mainly needed for the IMAP protocol |
131 @param boxname: name of the box where the message is | 134 @param boxname: name of the box where the message is |
132 @return: Integer UID""" | 135 @return: Integer UID""" |
133 try: | 136 box_data = self.__getBoxData(boxname) |
134 box_data = self.data[boxname] #the boxname MUST exist in the data | |
135 except KeyError: | |
136 err_msg=_("Boxname doesn't exist in internal data") | |
137 error(_("INTERNAL ERROR: ") + err_msg) | |
138 raise MaildirError(err_msg) | |
139 return box_data['cur_idx']+1 | 137 return box_data['cur_idx']+1 |
140 | 138 |
141 def getNextExistingUid(self, boxname, uid): | 139 def getNextExistingUid(self, boxname, uid): |
142 """Give the next uid of existing message | 140 """Give the next uid of existing message |
143 @param boxname: name of the box where the message is | 141 @param boxname: name of the box where the message is |
144 @param uid: uid to start from | 142 @param uid: uid to start from |
145 @return: uid or None if the is no more message""" | 143 @return: uid or None if the is no more message""" |
146 try: | 144 box_data = self.__getBoxData(boxname) |
147 box_data = self.data[boxname] #the boxname MUST exist in the data | |
148 except KeyError: | |
149 err_msg=_("Boxname doesn't exist in internal data") | |
150 error(_("INTERNAL ERROR: ") + err_msg) | |
151 raise MaildirError(err_msg) | |
152 idx=uid+1 | 145 idx=uid+1 |
153 while self.getIdfromUid(boxname, idx) == None: #TODO: this is highly inefficient because getIdfromUid is inefficient, fix this | 146 while self.getIdFromUid(boxname, idx) == None: #TODO: this is highly inefficient because getIdfromUid is inefficient, fix this |
154 idx+=1 | 147 idx+=1 |
155 if idx>box_data['cur_idx']: | 148 if idx>box_data['cur_idx']: |
156 return None | 149 return None |
157 return idx | 150 return idx |
158 | 151 |
159 def getMaxUid(self, boxname): | 152 def getMaxUid(self, boxname): |
160 """Give the max existing uid | 153 """Give the max existing uid |
161 @param boxname: name of the box where the message is | 154 @param boxname: name of the box where the message is |
162 @return: uid""" | 155 @return: uid""" |
163 try: | 156 box_data = self.__getBoxData(boxname) |
164 box_data = self.data[boxname] #the boxname MUST exist in the data | |
165 except KeyError: | |
166 err_msg=_("Boxname doesn't exist in internal data") | |
167 error(_("INTERNAL ERROR: ") + err_msg) | |
168 raise MaildirError(err_msg) | |
169 return box_data['cur_idx'] | 157 return box_data['cur_idx'] |
170 | 158 |
171 | 159 def getIdFromUid(self, boxname, message_uid): |
172 def getIdfromUid(self, boxname, message_uid): | |
173 """Return the message unique id from it's integer UID | 160 """Return the message unique id from it's integer UID |
174 @param boxname: name of the box where the message is | 161 @param boxname: name of the box where the message is |
175 @param message_uid: unique integer identifier | 162 @param message_uid: unique integer identifier |
176 @return: unique id of the message as given by MaildirMailbox or None if not found""" | 163 @return: unique id of the message as given by MaildirMailbox or None if not found""" |
177 try: | 164 box_data = self.__getBoxData(boxname) |
178 box_data = self.data[boxname] #the boxname MUST exist in the data | |
179 except KeyError: | |
180 err_msg=_("Boxname doesn't exist in internal data") | |
181 error(_("INTERNAL ERROR: ") + err_msg) | |
182 raise MaildirError(err_msg) | |
183 | |
184 for message_id in box_data.keys(): #TODO: this is highly inefficient on big mailbox, must be replaced in the future | 165 for message_id in box_data.keys(): #TODO: this is highly inefficient on big mailbox, must be replaced in the future |
185 if message_id == 'cur_idx': | 166 if message_id == 'cur_idx': |
186 continue | 167 continue |
187 if box_data[message_id][0] == message_uid: | 168 if box_data[message_id][0] == message_uid: |
188 return message_id | 169 return message_id |
189 return None | 170 return None |
190 | 171 |
172 def getFlags(self, boxname, mess_id): | |
173 """Return the messages flags | |
174 @param boxname: name of the box where the message is | |
175 @param message_idx: message id as given by MaildirMailbox | |
176 @return: list of strings""" | |
177 box_data = self.__getBoxData(boxname) | |
178 if not box_data.has_key(mess_id): | |
179 raise MailboxException("Trying to get flags from an unexisting message") | |
180 return box_data[mess_id][1] | |
181 | |
182 def setFlags(self, boxname, mess_id, flags): | |
183 """Change the flags of the message | |
184 @param boxname: name of the box where the message is | |
185 @param message_idx: message id as given by MaildirMailbox | |
186 @param flags: list of strings | |
187 """ | |
188 box_data = self.__getBoxData(boxname) | |
189 assert(type(flags)==list) | |
190 if not box_data.has_key(mess_id): | |
191 raise MailboxException("Trying to set flags for an unexisting message") | |
192 box_data[mess_id][1]=flags | |
193 self.host.memory.setPrivate('MAILDIR_data',self.data) | |
194 | |
195 def getMessageIdsWithFlag(self, boxname, flag): | |
196 """Return ids of messages where a flag is set | |
197 @param boxname: name of the box where the message is | |
198 @param flag: flag to check | |
199 @return: list of id (as given by MaildirMailbox)""" | |
200 box_data = self.__getBoxData(boxname) | |
201 assert(isinstance(flag,basestring)) | |
202 result = [] | |
203 for key in box_data: | |
204 if key=='cur_idx': | |
205 continue | |
206 if flag in box_data[key][1]: | |
207 result.append(key) | |
208 return result | |
209 | |
210 def purgeDeleted(self, boxname): | |
211 """Remove data for messages with flag "\\Deleted" | |
212 @param boxname: name of the box where the message is | |
213 """ | |
214 box_data = self.__getBoxData(boxname) | |
215 for mess_id in self.getMessageIdsWithFlag(boxname,"\\Deleted"): | |
216 del(box_data[mess_id]) | |
217 self.host.memory.setPrivate('MAILDIR_data',self.data) | |
218 | |
191 def cleanTable(self, boxname, existant_id): | 219 def cleanTable(self, boxname, existant_id): |
192 """Remove mails which no longuer exist from the table | 220 """Remove mails which no longuer exist from the table |
193 @param boxname: name of the box to clean | 221 @param boxname: name of the box to clean |
194 @param existant_id: list of id which actually exist""" | 222 @param existant_id: list of id which actually exist""" |
195 try: | 223 box_data = self.__getBoxData(boxname) |
196 box_data = self.data[boxname] #the boxname MUST exist in the data | |
197 except KeyError: | |
198 err_msg=_("Boxname doesn't exist in internal data") | |
199 error(_("INTERNAL ERROR: ") + err_msg) | |
200 raise MaildirError(err_msg) | |
201 to_remove=[] | 224 to_remove=[] |
202 for key in box_data: | 225 for key in box_data: |
203 if key not in existant_id and key!="cur_idx": | 226 if key not in existant_id and key!="cur_idx": |
204 to_remove.append(key) | 227 to_remove.append(key) |
205 for key in to_remove: | 228 for key in to_remove: |
310 existant_id.append(self.getId(mess_idx)) | 333 existant_id.append(self.getId(mess_idx)) |
311 self.getUid(mess_idx) | 334 self.getUid(mess_idx) |
312 self.maildir.cleanTable(self.name, existant_id) | 335 self.maildir.cleanTable(self.name, existant_id) |
313 | 336 |
314 | 337 |
315 def __destroy__(self): | 338 def __del__(self): |
316 if observer: | 339 if observer: |
317 debug("removing observer for %s" % self.name) | 340 debug("removing observer for %s" % self.name) |
318 self._maildir.removeObserver(observer, self.name, "NEW_MESSAGE") | 341 self._maildir.removeObserver(observer, self.name, "NEW_MESSAGE") |
319 self._maildir._removeBoxAccess(self.name, self) | 342 self._maildir._removeBoxAccess(self.name, self) |
320 | 343 |
353 | 376 |
354 def getMessageIdx(self, mess_idx): | 377 def getMessageIdx(self, mess_idx): |
355 """Return the full message | 378 """Return the full message |
356 @mess_idx: message index""" | 379 @mess_idx: message index""" |
357 return self.mailbox.getMessage(mess_idx) | 380 return self.mailbox.getMessage(mess_idx) |
381 | |
382 def getIdxFromUid(self, mess_uid): | |
383 """Return the message index from the uid | |
384 @param mess_uid: message unique identifier | |
385 @return: message index, as managed by MaildirMailbox""" | |
386 for mess_idx in range (self.getMessageCount()): | |
387 if self.getUid(mess_idx) == mess_uid: | |
388 return mess_idx | |
389 raise IndexError | |
390 | |
391 def getIdxFromId(self, mess_id): | |
392 """Return the message index from the unique index | |
393 @param mess_id: message unique index as given by MaildirMailbox | |
394 @return: message sequence index""" | |
395 for mess_idx in range (self.getMessageCount()): | |
396 if self.mailbox.getUidl(mess_idx) == mess_id: | |
397 return mess_idx | |
398 raise IndexError | |
358 | 399 |
359 def getMessage(self, mess_idx): | 400 def getMessage(self, mess_idx): |
360 """Return the full message | 401 """Return the full message |
361 @mess_idx: message index""" | 402 @param mess_idx: message index""" |
362 return self.mailbox.getMessage(mess_idx) | 403 return self.mailbox.getMessage(mess_idx) |
363 | 404 |
364 def getMessageUid(self, mess_uid): | 405 def getMessageUid(self, mess_uid): |
365 """Return the full message | 406 """Return the full message |
366 @mess_idx: message unique identifier""" | 407 @param mess_idx: message unique identifier""" |
367 for mess_idx in range (self.getMessageCount()): | 408 return self.mailbox.getMessage(self.getIdxFromUid(mess_uid)) |
368 if self.getUid(mess_idx) == mess_uid: | 409 |
369 return self.mailbox.getMessage(mess_idx) | 410 def getFlags(self, mess_idx): |
370 raise IndexError | 411 """Return the flags of the message |
412 @param mess_idx: message index | |
413 @return: list of strings""" | |
414 id = self.getId(mess_idx) | |
415 return self.maildir.getFlags(self.name, id) | |
416 | |
417 def getFlagsUid(self, mess_uid): | |
418 """Return the flags of the message | |
419 @param mess_uid: message unique identifier | |
420 @return: list of strings""" | |
421 id = self.maildir.getIdFromUid(self.name,mess_uid) | |
422 return self.maildir.getFlags(self.name, id) | |
423 | |
424 def setFlags(self, mess_idx, flags): | |
425 """Change the flags of the message | |
426 @param mess_idx: message index | |
427 @param flags: list of strings | |
428 """ | |
429 id = self.getId(mess_idx) | |
430 return self.maildir.setFlags(self.name, id, flags) | |
431 | |
432 def setFlagsUid(self, mess_uid, flags): | |
433 """Change the flags of the message | |
434 @param mess_uid: message unique identifier | |
435 @param flags: list of strings | |
436 """ | |
437 id = self.maildir.getIdFromUid(self.name,mess_uid) | |
438 return self.maildir.setFlags(self.name, id, flags) | |
439 | |
440 def getMessageIdsWithFlag(self, flag): | |
441 """Return ids of messages where a flag is set | |
442 @param flag: flag to check | |
443 @return: list of id (as given by MaildirMailbox)""" | |
444 return self.maildir.getMessageIdsWithFlag(self.name,flag) | |
445 | |
446 def removeDeleted(self): | |
447 """Actually delete message flagged "\\Deleted" | |
448 Also purge the internal data of these messages | |
449 """ | |
450 for mess_id in self.getMessageIdsWithFlag("\\Deleted"): | |
451 print ("Deleting %s", mess_id) | |
452 self.mailbox.deleteMessage(self.getIdxFromId(mess_id)) | |
453 self.mailbox = maildir.MaildirMailbox(self.mailbox_path) #We need to reparse the dir to have coherent indexing | |
454 self.maildir.purgeDeleted(self.name) | |
455 | |
456 def emptyTrash(self): | |
457 """Delete everything in the .Trash dir""" | |
458 import shutils | |
459 pdb.set_trace() | |
460 |