Mercurial > libervia-backend
comparison src/plugins/plugin_misc_maildir.py @ 254:9fc32d1d9046
Plugin IMAP, plugin MAILDIR: added IMAP's UID management, mailbox data persistence
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 17 Jan 2011 04:23:31 +0100 |
parents | f45ffbf211e9 |
children | 55b750017b71 |
comparison
equal
deleted
inserted
replaced
253:f45ffbf211e9 | 254:9fc32d1d9046 |
---|---|
60 info(_("Plugin Maildir initialization")) | 60 info(_("Plugin Maildir initialization")) |
61 self.host = host | 61 self.host = host |
62 | 62 |
63 self.__observed={} | 63 self.__observed={} |
64 self.__mailboxes={} | 64 self.__mailboxes={} |
65 self.data=host.memory.getPrivate("MAILDIR_data") or {"INBOX":{"cur_idx":0}} | |
66 #a value in the dictionnary for a mailbox is a dictionnary with the following value | |
67 # - cur_idx: value of the current unique integer increment (UID) | |
68 # - message_id (as returned by MaildirMailbox): a tuple of (UID, [flag1, flag2, ...]) | |
65 | 69 |
66 #the trigger | 70 #the trigger |
67 host.trigger.add("MessageReceived", self.MessageReceivedTrigger) | 71 host.trigger.add("MessageReceived", self.MessageReceivedTrigger) |
72 | |
73 def __destroy__(self): | |
74 debug('Destroying MaildirBox') | |
75 self.host.memory.setPrivate('MAILDIR_data',self.data) | |
68 | 76 |
69 def accessMessageBox(self, boxname, observer=None): | 77 def accessMessageBox(self, boxname, observer=None): |
70 """Create and return a MailboxUser instance | 78 """Create and return a MailboxUser instance |
71 @param boxname: name of the box | 79 @param boxname: name of the box |
72 @param observer: method to call when a NewMessage arrive""" | 80 @param observer: method to call when a NewMessage arrive""" |
93 @param boxname: name of the box to check | 101 @param boxname: name of the box to check |
94 @return: MailboxUser instance or None""" | 102 @return: MailboxUser instance or None""" |
95 if self.__mailboxes.has_key(boxname): | 103 if self.__mailboxes.has_key(boxname): |
96 return self.__mailboxes[boxname] | 104 return self.__mailboxes[boxname] |
97 | 105 |
98 | 106 def getUid(self, boxname, message_id): |
107 """Return an unique integer, always ascending, for a message | |
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: | |
113 box_data = self.data[boxname] #the boxname MUST exist in the data | |
114 except KeyError: | |
115 err_msg=_("Boxname doesn't exist in internal data") | |
116 error(_("INTERNAL ERROR: ") + err_msg) | |
117 raise MaildirError(err_msg) | |
118 if box_data.has_key(message_id): | |
119 ret = box_data[message_id][0] | |
120 else: | |
121 box_data['cur_idx']+=1 | |
122 box_data[message_id]=(box_data['cur_idx'],[]) | |
123 ret = box_data[message_id] | |
124 self.host.memory.setPrivate('MAILDIR_data',self.data) | |
125 return ret | |
126 | |
127 | |
128 def getNextUid(self, boxname): | |
129 """Return next unique integer that will generated | |
130 This is mainly needed for the IMAP protocol | |
131 @param boxname: name of the box where the message is | |
132 @return: Integer UID""" | |
133 try: | |
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 | |
140 | |
141 def getNextExistingUid(self, boxname, uid): | |
142 """Give the next uid of existing message | |
143 @param boxname: name of the box where the message is | |
144 @param uid: uid to start from | |
145 @return: uid or None if the is no more message""" | |
146 try: | |
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 | |
153 while self.getIdfromUid(boxname, idx) == None: #TODO: this is highly inefficient because getIdfromUid is inefficient, fix this | |
154 idx+=1 | |
155 if idx>box_data['cur_idx']: | |
156 return None | |
157 return idx | |
158 | |
159 def getMaxUid(self, boxname): | |
160 """Give the max existing uid | |
161 @param boxname: name of the box where the message is | |
162 @return: uid""" | |
163 try: | |
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'] | |
170 | |
171 | |
172 def getIdfromUid(self, boxname, message_uid): | |
173 """Return the message unique id from it's integer UID | |
174 @param boxname: name of the box where the message is | |
175 @param message_uid: unique integer identifier | |
176 @return: unique id of the message as given by MaildirMailbox or None if not found""" | |
177 try: | |
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 | |
185 if message_id == 'cur_idx': | |
186 continue | |
187 if box_data[message_id][0] == message_uid: | |
188 return message_id | |
189 return None | |
190 | |
191 def cleanTable(self, boxname, existant_id): | |
192 """Remove mails which no longuer exist from the table | |
193 @param boxname: name of the box to clean | |
194 @param existant_id: list of id which actually exist""" | |
195 try: | |
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=[] | |
202 for key in box_data: | |
203 if key not in existant_id and key!="cur_idx": | |
204 to_remove.append(key) | |
205 for key in to_remove: | |
206 del box_data[key] | |
207 | |
99 | 208 |
100 def MessageReceivedTrigger(self, message): | 209 def MessageReceivedTrigger(self, message): |
101 """This trigger catch normal message and put the in the Maildir box. | 210 """This trigger catch normal message and put the in the Maildir box. |
102 If the message is not of "normal" type, do nothing | 211 If the message is not of "normal" type, do nothing |
103 @param message: message xmlstrem | 212 @param message: message xmlstrem |
185 self.maildir=_maildir | 294 self.maildir=_maildir |
186 mailbox_path = os.path.expanduser(os.path.join(self.maildir.host.get_const('local_dir'), MAILDIR_PATH)) | 295 mailbox_path = os.path.expanduser(os.path.join(self.maildir.host.get_const('local_dir'), MAILDIR_PATH)) |
187 self.mailbox_path=mailbox_path | 296 self.mailbox_path=mailbox_path |
188 self.mailbox = maildir.MaildirMailbox(mailbox_path) | 297 self.mailbox = maildir.MaildirMailbox(mailbox_path) |
189 self.observer=observer | 298 self.observer=observer |
299 self.__uid_table_update() | |
300 | |
301 | |
190 if observer: | 302 if observer: |
191 debug("adding observer for %s" % name) | 303 debug("adding observer for %s" % name) |
192 self.maildir.addObserver(observer, name, "NEW_MESSAGE") | 304 self.maildir.addObserver(observer, name, "NEW_MESSAGE") |
305 | |
306 def __uid_table_update(self): | |
307 existant_id=[] | |
308 for mess_idx in range (self.getMessageCount()): | |
309 #we update the uid table | |
310 existant_id.append(self.getId(mess_idx)) | |
311 self.getUid(mess_idx) | |
312 self.maildir.cleanTable(self.name, existant_id) | |
313 | |
193 | 314 |
194 def __destroy__(self): | 315 def __destroy__(self): |
195 if observer: | 316 if observer: |
196 debug("removing observer for %s" % self.name) | 317 debug("removing observer for %s" % self.name) |
197 self._maildir.removeObserver(observer, self.name, "NEW_MESSAGE") | 318 self._maildir.removeObserver(observer, self.name, "NEW_MESSAGE") |
202 @param message: XMPP XML message""" | 323 @param message: XMPP XML message""" |
203 self.mailbox.appendMessage(self.xmppMessage2mail(message)).addCallback(self.emitSignal, "NEW_MESSAGE") | 324 self.mailbox.appendMessage(self.xmppMessage2mail(message)).addCallback(self.emitSignal, "NEW_MESSAGE") |
204 | 325 |
205 def emitSignal(self, ignore, signal): | 326 def emitSignal(self, ignore, signal): |
206 """Emit the signal to the observers""" | 327 """Emit the signal to the observers""" |
207 print ('self: %s, mailbox: %s, count: %i' % (self, self.mailbox, self.getMessageCount())) | 328 self.getUid(self.getMessageCount()-1) #we make an uid for the last message added |
208 self.maildir.emitSignal(self.name, signal) | 329 self.maildir.emitSignal(self.name, signal) |
209 | 330 |
210 def getId(self, mess_idx): | 331 def getId(self, mess_idx): |
211 """Return the Unique ID of the message | 332 """Return the Unique ID of the message |
212 @mess_idx: message index""" | 333 @mess_idx: message index""" |
213 return self.mailbox.getUidl(mess_idx) | 334 return self.mailbox.getUidl(mess_idx) |
214 | 335 |
336 def getUid(self, mess_idx): | |
337 """Return a unique interger id for the message, always ascending""" | |
338 mess_id=self.getId(mess_idx) | |
339 return self.maildir.getUid(self.name,mess_id) | |
340 | |
341 def getNextUid(self): | |
342 return self.maildir.getNextUid(self.name) | |
343 | |
344 def getNextExistingUid(self, uid): | |
345 return self.maildir.getNextExistingUid(self.name, uid) | |
346 | |
347 def getMaxUid(self): | |
348 return self.maildir.getMaxUid(self.name) | |
349 | |
215 def getMessageCount(self): | 350 def getMessageCount(self): |
216 """Return number of mails present in this box""" | 351 """Return number of mails present in this box""" |
217 print "count: %i" % len(self.mailbox.listMessages()) | 352 return len(self.mailbox.list) |
218 return len(self.mailbox.listMessages()) | 353 |
219 | 354 def getMessageIdx(self, mess_idx): |
355 """Return the full message | |
356 @mess_idx: message index""" | |
357 return self.mailbox.getMessage(mess_idx) | |
358 | |
220 def getMessage(self, mess_idx): | 359 def getMessage(self, mess_idx): |
221 """Return the full message | 360 """Return the full message |
222 @mess_idx: message index""" | 361 @mess_idx: message index""" |
223 return self.mailbox.getMessage(mess_idx) | 362 return self.mailbox.getMessage(mess_idx) |
363 | |
364 def getMessageUid(self, mess_uid): | |
365 """Return the full message | |
366 @mess_idx: message unique identifier""" | |
367 for mess_idx in range (self.getMessageCount()): | |
368 if self.getUid(mess_idx) == mess_uid: | |
369 return self.mailbox.getMessage(mess_idx) | |
370 raise IndexError |