comparison src/plugins/plugin_misc_maildir.py @ 594:e629371a28d3

Fix pep8 support in src/plugins.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 18 Jan 2013 17:55:35 +0100
parents beaf6bec2fcd
children 84a6e83157c2
comparison
equal deleted inserted replaced
593:70bae685d05c 594:e629371a28d3
19 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """ 20 """
21 21
22 from logging import debug, info, error 22 from logging import debug, info, error
23 import warnings 23 import warnings
24 warnings.filterwarnings('ignore','the MimeWriter',DeprecationWarning,'twisted' ) #FIXME: to be removed, see http://twistedmatrix.com/trac/ticket/4038 24 warnings.filterwarnings('ignore', 'the MimeWriter', DeprecationWarning, 'twisted') # FIXME: to be removed, see http://twistedmatrix.com/trac/ticket/4038
25 from twisted.internet import protocol 25 from twisted.internet import protocol
26 from twisted.words.protocols.jabber import error as jab_error 26 from twisted.words.protocols.jabber import error as jab_error
27 from twisted.cred import portal,checkers 27 from twisted.cred import portal, checkers
28 from twisted.mail import imap4,maildir 28 from twisted.mail import imap4, maildir
29 from email.parser import Parser 29 from email.parser import Parser
30 import email.message 30 import email.message
31 from email.charset import Charset 31 from email.charset import Charset
32 import os,os.path 32 import os
33 from cStringIO import StringIO 33 from cStringIO import StringIO
34 from twisted.internet import reactor 34 from twisted.internet import reactor
35 import pdb 35 import pdb
36 from sat.core.exceptions import ProfileUnknownError 36 from sat.core.exceptions import ProfileUnknownError
37 from sat.memory.persistent import PersistentBinaryDict 37 from sat.memory.persistent import PersistentBinaryDict
38 38
39
40 from zope.interface import implements 39 from zope.interface import implements
41 40
42
43 PLUGIN_INFO = { 41 PLUGIN_INFO = {
44 "name": "Maildir Plugin", 42 "name": "Maildir Plugin",
45 "import_name": "Maildir", 43 "import_name": "Maildir",
46 "type": "Misc", 44 "type": "Misc",
47 "protocols": [], 45 "protocols": [],
48 "dependencies": [], 46 "dependencies": [],
49 "main": "MaildirBox", 47 "main": "MaildirBox",
50 "handler": "no", 48 "handler": "no",
51 "description": _("""Intercept "normal" type messages, and put them in a Maildir type box""") 49 "description": _("""Intercept "normal" type messages, and put them in a Maildir type box""")
52 } 50 }
53 51
54 MAILDIR_PATH = "Maildir" 52 MAILDIR_PATH = "Maildir"
53
55 54
56 class MaildirError(Exception): 55 class MaildirError(Exception):
57 pass 56 pass
57
58 58
59 class MaildirBox(object): 59 class MaildirBox(object):
60 60
61 def __init__(self, host): 61 def __init__(self, host):
62 info(_("Plugin Maildir initialization")) 62 info(_("Plugin Maildir initialization"))
63 self.host = host 63 self.host = host
64 64
65 self.__observed={} 65 self.__observed = {}
66 self.data={} #list of profile spectific data. key = profile, value = PersistentBinaryDict where key=mailbox name, 66 self.data = {} # list of profile spectific data. key = profile, value = PersistentBinaryDict where key=mailbox name,
67 # and value is a dictionnary with the following value 67 # and value is a dictionnary with the following value
68 # - cur_idx: value of the current unique integer increment (UID) 68 # - cur_idx: value of the current unique integer increment (UID)
69 # - message_id (as returned by MaildirMailbox): a tuple of (UID, [flag1, flag2, ...]) 69 # - message_id (as returned by MaildirMailbox): a tuple of (UID, [flag1, flag2, ...])
70 pList=host.memory.getProfilesList #shorter :) 70 pList = host.memory.getProfilesList # shorter :)
71 self.__mailboxes={} #key: profile, value: {boxname: MailboxUser instance} 71 self.__mailboxes = {} # key: profile, value: {boxname: MailboxUser instance}
72 72
73 #the triggers 73 #the triggers
74 host.trigger.add("MessageReceived", self.messageReceivedTrigger) 74 host.trigger.add("MessageReceived", self.messageReceivedTrigger)
75 75
76 def profileConnected(self, profile): 76 def profileConnected(self, profile):
77 """Called on profile connection, create profile data""" 77 """Called on profile connection, create profile data"""
78 self.data[profile] = PersistentBinaryDict("plugin_maildir", profile) 78 self.data[profile] = PersistentBinaryDict("plugin_maildir", profile)
79 self.__mailboxes[profile]={} 79 self.__mailboxes[profile] = {}
80
80 def dataLoaded(ignore): 81 def dataLoaded(ignore):
81 if not self.data[profile]: 82 if not self.data[profile]:
82 #the mailbox is new, we initiate the data 83 #the mailbox is new, we initiate the data
83 self.data[profile]["INBOX"] = {"cur_idx":0} 84 self.data[profile]["INBOX"] = {"cur_idx": 0}
84 self.data[profile].load().addCallback(dataLoaded) 85 self.data[profile].load().addCallback(dataLoaded)
85 86
86 def profileDisconnected(self, profile): 87 def profileDisconnected(self, profile):
87 """Called on profile disconnection, free profile's resources""" 88 """Called on profile disconnection, free profile's resources"""
88 del self.__mailboxes[profile] 89 del self.__mailboxes[profile]
106 @param boxname: name of the box 107 @param boxname: name of the box
107 @param observer: method to call when a NewMessage arrive""" 108 @param observer: method to call when a NewMessage arrive"""
108 profile = self.host.memory.getProfileName(profile_key) 109 profile = self.host.memory.getProfileName(profile_key)
109 if not profile: 110 if not profile:
110 raise ProfileUnknownError(profile_key) 111 raise ProfileUnknownError(profile_key)
111 if not self.__mailboxes[profile].has_key(boxname): 112 if boxname not in self.__mailboxes[profile]:
112 self.__mailboxes[profile][boxname]=MailboxUser(self, boxname, observer, profile=profile) 113 self.__mailboxes[profile][boxname] = MailboxUser(self, boxname, observer, profile=profile)
113 else: 114 else:
114 if observer: 115 if observer:
115 self.addObserver(observer, profile, boxname) 116 self.addObserver(observer, profile, boxname)
116 return self.__mailboxes[profile][boxname] 117 return self.__mailboxes[profile][boxname]
117 118
118 def _getProfilePath(self, profile): 119 def _getProfilePath(self, profile):
119 """Return a unique path for profile's mailbox 120 """Return a unique path for profile's mailbox
120 The path must be unique, usable as a dir name, and bijectional""" 121 The path must be unique, usable as a dir name, and bijectional"""
121 return profile.replace('/','_').replace('..','_') #FIXME: this is too naive to work well, must be improved 122 return profile.replace('/', '_').replace('..', '_') # FIXME: this is too naive to work well, must be improved
122 123
123 def _removeBoxAccess(self, boxname, mailboxUser, profile): 124 def _removeBoxAccess(self, boxname, mailboxUser, profile):
124 """Remove a reference to a box 125 """Remove a reference to a box
125 @param name: name of the box 126 @param name: name of the box
126 @param mailboxUser: MailboxUser instance""" 127 @param mailboxUser: MailboxUser instance"""
127 if not self.__mailboxes.has_key(boxname): 128 if boxname not in self.__mailboxes:
128 err_msg=_("Trying to remove an mailboxUser not referenced") 129 err_msg = _("Trying to remove an mailboxUser not referenced")
129 error(_("INTERNAL ERROR: ") + err_msg) 130 error(_("INTERNAL ERROR: ") + err_msg)
130 raise MaildirError(err_msg) 131 raise MaildirError(err_msg)
131 assert self.__mailboxes[profile][boxname]==mailboxUser 132 assert self.__mailboxes[profile][boxname] == mailboxUser
132 del __mailboxes[profile][boxname] 133 del __mailboxes[profile][boxname]
133 134
134 def _checkBoxReference(self, boxname, profile): 135 def _checkBoxReference(self, boxname, profile):
135 """Check if there is a reference on a box, and return it 136 """Check if there is a reference on a box, and return it
136 @param boxname: name of the box to check 137 @param boxname: name of the box to check
137 @return: MailboxUser instance or None""" 138 @return: MailboxUser instance or None"""
138 if self.__mailboxes.has_key(profile): 139 if profile in self.__mailboxes:
139 if self.__mailboxes[profile].has_key(boxname): 140 if boxname in self.__mailboxes[profile]:
140 return self.__mailboxes[profile][boxname] 141 return self.__mailboxes[profile][boxname]
141 142
142 def __getBoxData(self, boxname, profile): 143 def __getBoxData(self, boxname, profile):
143 """Return the date of a box""" 144 """Return the date of a box"""
144 try: 145 try:
145 return self.data[profile][boxname] #the boxname MUST exist in the data 146 return self.data[profile][boxname] # the boxname MUST exist in the data
146 except KeyError: 147 except KeyError:
147 err_msg=_("Boxname doesn't exist in internal data") 148 err_msg = _("Boxname doesn't exist in internal data")
148 error(_("INTERNAL ERROR: ") + err_msg) 149 error(_("INTERNAL ERROR: ") + err_msg)
149 raise MaildirError(err_msg) 150 raise MaildirError(err_msg)
150 151
151 def getUid(self, boxname, message_id, profile): 152 def getUid(self, boxname, message_id, profile):
152 """Return an unique integer, always ascending, for a message 153 """Return an unique integer, always ascending, for a message
153 This is mainly needed for the IMAP protocol 154 This is mainly needed for the IMAP protocol
154 @param boxname: name of the box where the message is 155 @param boxname: name of the box where the message is
155 @param message_id: unique id of the message as given by MaildirMailbox 156 @param message_id: unique id of the message as given by MaildirMailbox
156 @return: Integer UID""" 157 @return: Integer UID"""
157 box_data = self.__getBoxData(boxname, profile) 158 box_data = self.__getBoxData(boxname, profile)
158 if box_data.has_key(message_id): 159 if message_id in box_data:
159 ret = box_data[message_id][0] 160 ret = box_data[message_id][0]
160 else: 161 else:
161 box_data['cur_idx']+=1 162 box_data['cur_idx'] += 1
162 box_data[message_id]=[box_data['cur_idx'],[]] 163 box_data[message_id] = [box_data['cur_idx'], []]
163 ret = box_data[message_id] 164 ret = box_data[message_id]
164 self.data[profile].force(boxname) 165 self.data[profile].force(boxname)
165 return ret 166 return ret
166 167
167 def getNextUid(self, boxname, profile): 168 def getNextUid(self, boxname, profile):
168 """Return next unique integer that will generated 169 """Return next unique integer that will generated
169 This is mainly needed for the IMAP protocol 170 This is mainly needed for the IMAP protocol
170 @param boxname: name of the box where the message is 171 @param boxname: name of the box where the message is
171 @return: Integer UID""" 172 @return: Integer UID"""
172 box_data = self.__getBoxData(boxname, profile) 173 box_data = self.__getBoxData(boxname, profile)
173 return box_data['cur_idx']+1 174 return box_data['cur_idx'] + 1
174 175
175 def getNextExistingUid(self, boxname, uid, profile): 176 def getNextExistingUid(self, boxname, uid, profile):
176 """Give the next uid of existing message 177 """Give the next uid of existing message
177 @param boxname: name of the box where the message is 178 @param boxname: name of the box where the message is
178 @param uid: uid to start from 179 @param uid: uid to start from
179 @return: uid or None if the is no more message""" 180 @return: uid or None if the is no more message"""
180 box_data = self.__getBoxData(boxname, profile) 181 box_data = self.__getBoxData(boxname, profile)
181 idx=uid+1 182 idx = uid + 1
182 while self.getIdFromUid(boxname, idx, profile) == None: #TODO: this is highly inefficient because getIdfromUid is inefficient, fix this 183 while self.getIdFromUid(boxname, idx, profile) is None: # TODO: this is highly inefficient because getIdfromUid is inefficient, fix this
183 idx+=1 184 idx += 1
184 if idx>box_data['cur_idx']: 185 if idx > box_data['cur_idx']:
185 return None 186 return None
186 return idx 187 return idx
187 188
188 def getMaxUid(self, boxname, profile): 189 def getMaxUid(self, boxname, profile):
189 """Give the max existing uid 190 """Give the max existing uid
196 """Return the message unique id from it's integer UID 197 """Return the message unique id from it's integer UID
197 @param boxname: name of the box where the message is 198 @param boxname: name of the box where the message is
198 @param message_uid: unique integer identifier 199 @param message_uid: unique integer identifier
199 @return: unique id of the message as given by MaildirMailbox or None if not found""" 200 @return: unique id of the message as given by MaildirMailbox or None if not found"""
200 box_data = self.__getBoxData(boxname, profile) 201 box_data = self.__getBoxData(boxname, profile)
201 for message_id in box_data.keys(): #TODO: this is highly inefficient on big mailbox, must be replaced in the future 202 for message_id in box_data.keys(): # TODO: this is highly inefficient on big mailbox, must be replaced in the future
202 if message_id == 'cur_idx': 203 if message_id == 'cur_idx':
203 continue 204 continue
204 if box_data[message_id][0] == message_uid: 205 if box_data[message_id][0] == message_uid:
205 return message_id 206 return message_id
206 return None 207 return None
209 """Return the messages flags 210 """Return the messages flags
210 @param boxname: name of the box where the message is 211 @param boxname: name of the box where the message is
211 @param message_idx: message id as given by MaildirMailbox 212 @param message_idx: message id as given by MaildirMailbox
212 @return: list of strings""" 213 @return: list of strings"""
213 box_data = self.__getBoxData(boxname, profile) 214 box_data = self.__getBoxData(boxname, profile)
214 if not box_data.has_key(mess_id): 215 if mess_id not in box_data:
215 raise MailboxException("Trying to get flags from an unexisting message") 216 raise MailboxException("Trying to get flags from an unexisting message")
216 return box_data[mess_id][1] 217 return box_data[mess_id][1]
217 218
218 def setFlags(self, boxname, mess_id, flags, profile): 219 def setFlags(self, boxname, mess_id, flags, profile):
219 """Change the flags of the message 220 """Change the flags of the message
220 @param boxname: name of the box where the message is 221 @param boxname: name of the box where the message is
221 @param message_idx: message id as given by MaildirMailbox 222 @param message_idx: message id as given by MaildirMailbox
222 @param flags: list of strings 223 @param flags: list of strings
223 """ 224 """
224 box_data = self.__getBoxData(boxname, profile) 225 box_data = self.__getBoxData(boxname, profile)
225 assert(type(flags)==list) 226 assert(type(flags) == list)
226 flags=[flag.upper() for flag in flags] #we store every flag UPPERCASE 227 flags = [flag.upper() for flag in flags] # we store every flag UPPERCASE
227 if not box_data.has_key(mess_id): 228 if mess_id not in box_data:
228 raise MailboxException("Trying to set flags for an unexisting message") 229 raise MailboxException("Trying to set flags for an unexisting message")
229 box_data[mess_id][1]=flags 230 box_data[mess_id][1] = flags
230 self.data[profile].force(boxname) 231 self.data[profile].force(boxname)
231 232
232 def getMessageIdsWithFlag(self, boxname, flag, profile): 233 def getMessageIdsWithFlag(self, boxname, flag, profile):
233 """Return ids of messages where a flag is set 234 """Return ids of messages where a flag is set
234 @param boxname: name of the box where the message is 235 @param boxname: name of the box where the message is
235 @param flag: flag to check 236 @param flag: flag to check
236 @return: list of id (as given by MaildirMailbox)""" 237 @return: list of id (as given by MaildirMailbox)"""
237 box_data = self.__getBoxData(boxname, profile) 238 box_data = self.__getBoxData(boxname, profile)
238 assert(isinstance(flag,basestring)) 239 assert(isinstance(flag, basestring))
239 flag=flag.upper() 240 flag = flag.upper()
240 result = [] 241 result = []
241 for key in box_data: 242 for key in box_data:
242 if key=='cur_idx': 243 if key == 'cur_idx':
243 continue 244 continue
244 if flag in box_data[key][1]: 245 if flag in box_data[key][1]:
245 result.append(key) 246 result.append(key)
246 return result 247 return result
247 248
248 def purgeDeleted(self, boxname, profile): 249 def purgeDeleted(self, boxname, profile):
249 """Remove data for messages with flag "\\Deleted" 250 """Remove data for messages with flag "\\Deleted"
250 @param boxname: name of the box where the message is 251 @param boxname: name of the box where the message is
251 """ 252 """
252 box_data = self.__getBoxData(boxname, profile) 253 box_data = self.__getBoxData(boxname, profile)
253 for mess_id in self.getMessageIdsWithFlag(boxname,"\\Deleted", profile): 254 for mess_id in self.getMessageIdsWithFlag(boxname, "\\Deleted", profile):
254 del(box_data[mess_id]) 255 del(box_data[mess_id])
255 self.data[profile].force(boxname) 256 self.data[profile].force(boxname)
256 257
257 def cleanTable(self, boxname, existant_id, profile): 258 def cleanTable(self, boxname, existant_id, profile):
258 """Remove mails which no longuer exist from the table 259 """Remove mails which no longuer exist from the table
259 @param boxname: name of the box to clean 260 @param boxname: name of the box to clean
260 @param existant_id: list of id which actually exist""" 261 @param existant_id: list of id which actually exist"""
261 box_data = self.__getBoxData(boxname, profile) 262 box_data = self.__getBoxData(boxname, profile)
262 to_remove=[] 263 to_remove = []
263 for key in box_data: 264 for key in box_data:
264 if key not in existant_id and key!="cur_idx": 265 if key not in existant_id and key != "cur_idx":
265 to_remove.append(key) 266 to_remove.append(key)
266 for key in to_remove: 267 for key in to_remove:
267 del box_data[key] 268 del box_data[key]
268 269
269 def addObserver(self, callback, profile, boxname, signal="NEW_MESSAGE"): 270 def addObserver(self, callback, profile, boxname, signal="NEW_MESSAGE"):
270 """Add an observer for maildir box changes 271 """Add an observer for maildir box changes
271 @param callback: method to call when the the box is updated 272 @param callback: method to call when the the box is updated
272 @param boxname: name of the box to observe 273 @param boxname: name of the box to observe
273 @param signal: which signal is observed by the caller""" 274 @param signal: which signal is observed by the caller"""
274 if not self.__observed.has_key((profile,boxname)): 275 if (profile, boxname) not in self.__observed:
275 self.__observed[(profile,boxname)]={} 276 self.__observed[(profile, boxname)] = {}
276 if not self.__observed[(profile,boxname)].has_key(signal): 277 if signal not in self.__observed[(profile, boxname)]:
277 self.__observed[(profile,boxname)][signal]=set() 278 self.__observed[(profile, boxname)][signal] = set()
278 self.__observed[(profile,boxname)][signal].add(callback) 279 self.__observed[(profile, boxname)][signal].add(callback)
279 280
280 def removeObserver(self, callback, profile, boxname, signal="NEW_MESSAGE"): 281 def removeObserver(self, callback, profile, boxname, signal="NEW_MESSAGE"):
281 """Remove an observer of maildir box changes 282 """Remove an observer of maildir box changes
282 @param callback: method to remove from obervers 283 @param callback: method to remove from obervers
283 @param boxname: name of the box which was observed 284 @param boxname: name of the box which was observed
284 @param signal: which signal was observed by the caller""" 285 @param signal: which signal was observed by the caller"""
285 if not self.__observed.has_key((profile,boxname)): 286 if (profile, boxname) not in self.__observed:
286 err_msg=_("Trying to remove an observer for an inexistant mailbox") 287 err_msg = _("Trying to remove an observer for an inexistant mailbox")
287 error(_("INTERNAL ERROR: ") + err_msg) 288 error(_("INTERNAL ERROR: ") + err_msg)
288 raise MaildirError(err_msg) 289 raise MaildirError(err_msg)
289 if not self.__observed[(profile,boxname)].has_key(signal): 290 if signal not in self.__observed[(profile, boxname)]:
290 err_msg=_("Trying to remove an inexistant observer, no observer for this signal") 291 err_msg = _("Trying to remove an inexistant observer, no observer for this signal")
291 error(_("INTERNAL ERROR: ") + err_msg) 292 error(_("INTERNAL ERROR: ") + err_msg)
292 raise MaildirError(err_msg) 293 raise MaildirError(err_msg)
293 if not callback in self.__observed[(profile,boxname)][signal]: 294 if not callback in self.__observed[(profile, boxname)][signal]:
294 err_msg=_("Trying to remove an inexistant observer") 295 err_msg = _("Trying to remove an inexistant observer")
295 error(_("INTERNAL ERROR: ") + err_msg) 296 error(_("INTERNAL ERROR: ") + err_msg)
296 raise MaildirError(err_msg) 297 raise MaildirError(err_msg)
297 self.__observed[(profile,boxname)][signal].remove(callback) 298 self.__observed[(profile, boxname)][signal].remove(callback)
298 299
299 def emitSignal(self, profile, boxname, signal_name): 300 def emitSignal(self, profile, boxname, signal_name):
300 """Emit the signal to observer""" 301 """Emit the signal to observer"""
301 debug('emitSignal %s %s %s' %(profile, boxname, signal_name)) 302 debug('emitSignal %s %s %s' % (profile, boxname, signal_name))
302 try: 303 try:
303 for observer_cb in self.__observed[(profile, boxname)][signal_name]: 304 for observer_cb in self.__observed[(profile, boxname)][signal_name]:
304 observer_cb() 305 observer_cb()
305 except KeyError: 306 except KeyError:
306 pass 307 pass
323 #TODO: save thread id 324 #TODO: save thread id
324 for e in message.elements(): 325 for e in message.elements():
325 if e.name == "body": 326 if e.name == "body":
326 mail.set_payload(e.children[0].encode('utf-8')) 327 mail.set_payload(e.children[0].encode('utf-8'))
327 elif e.name == "subject": 328 elif e.name == "subject":
328 mail['Subject'] = e.children[0].encode('utf-8') 329 mail['Subject'] = e.children[0].encode('utf-8')
329 return mail.as_string() 330 return mail.as_string()
330 331
331 def __init__(self, _maildir, name, observer=None, profile="@NONE@"): 332 def __init__(self, _maildir, name, observer=None, profile="@NONE@"):
332 """@param _maildir: the main MaildirBox instance 333 """@param _maildir: the main MaildirBox instance
333 @param name: name of the mailbox 334 @param name: name of the mailbox
334 @param profile: real profile (ie not a profile_key) 335 @param profile: real profile (ie not a profile_key)
335 THIS OBJECT MUST NOT BE USED DIRECTLY: use MaildirBox.accessMessageBox instead""" 336 THIS OBJECT MUST NOT BE USED DIRECTLY: use MaildirBox.accessMessageBox instead"""
336 if _maildir._checkBoxReference(name, profile): 337 if _maildir._checkBoxReference(name, profile):
337 error ("INTERNAL ERROR: MailboxUser MUST NOT be instancied directly") 338 error("INTERNAL ERROR: MailboxUser MUST NOT be instancied directly")
338 raise MailboxException('double MailboxUser instanciation') 339 raise MailboxException('double MailboxUser instanciation')
339 if name!="INBOX": 340 if name != "INBOX":
340 raise NotImplementedError 341 raise NotImplementedError
341 self.name=name 342 self.name = name
342 self.profile=profile 343 self.profile = profile
343 self.maildir=_maildir 344 self.maildir = _maildir
344 profile_path = self.maildir._getProfilePath(profile) 345 profile_path = self.maildir._getProfilePath(profile)
345 full_profile_path = os.path.join(self.maildir.host.memory.getConfig('','local_dir'), profile_path) 346 full_profile_path = os.path.join(self.maildir.host.memory.getConfig('', 'local_dir'), profile_path)
346 if not os.path.exists(full_profile_path): 347 if not os.path.exists(full_profile_path):
347 os.makedirs(full_profile_path,0700) 348 os.makedirs(full_profile_path, 0700)
348 mailbox_path = os.path.join(full_profile_path, MAILDIR_PATH) 349 mailbox_path = os.path.join(full_profile_path, MAILDIR_PATH)
349 self.mailbox_path=mailbox_path 350 self.mailbox_path = mailbox_path
350 self.mailbox = maildir.MaildirMailbox(mailbox_path) 351 self.mailbox = maildir.MaildirMailbox(mailbox_path)
351 self.observer=observer 352 self.observer = observer
352 self.__uid_table_update() 353 self.__uid_table_update()
353 354
354 if observer: 355 if observer:
355 debug("adding observer for %s (%s)" % (name,profile)) 356 debug("adding observer for %s (%s)" % (name, profile))
356 self.maildir.addObserver(observer, profile, name, "NEW_MESSAGE") 357 self.maildir.addObserver(observer, profile, name, "NEW_MESSAGE")
357 358
358 def __uid_table_update(self): 359 def __uid_table_update(self):
359 existant_id=[] 360 existant_id = []
360 for mess_idx in range (self.getMessageCount()): 361 for mess_idx in range(self.getMessageCount()):
361 #we update the uid table 362 #we update the uid table
362 existant_id.append(self.getId(mess_idx)) 363 existant_id.append(self.getId(mess_idx))
363 self.getUid(mess_idx) 364 self.getUid(mess_idx)
364 self.maildir.cleanTable(self.name, existant_id, profile=self.profile) 365 self.maildir.cleanTable(self.name, existant_id, profile=self.profile)
365
366 366
367 def __del__(self): 367 def __del__(self):
368 if observer: 368 if observer:
369 debug("removing observer for %s" % self.name) 369 debug("removing observer for %s" % self.name)
370 self._maildir.removeObserver(observer, self.name, "NEW_MESSAGE") 370 self._maildir.removeObserver(observer, self.name, "NEW_MESSAGE")
375 @param message: XMPP XML message""" 375 @param message: XMPP XML message"""
376 self.mailbox.appendMessage(self.xmppMessage2mail(message)).addCallback(self.emitSignal, "NEW_MESSAGE") 376 self.mailbox.appendMessage(self.xmppMessage2mail(message)).addCallback(self.emitSignal, "NEW_MESSAGE")
377 377
378 def emitSignal(self, ignore, signal): 378 def emitSignal(self, ignore, signal):
379 """Emit the signal to the observers""" 379 """Emit the signal to the observers"""
380 if signal=="NEW_MESSAGE": 380 if signal == "NEW_MESSAGE":
381 self.getUid(self.getMessageCount()-1) #XXX: we make an uid for the last message added 381 self.getUid(self.getMessageCount() - 1) # XXX: we make an uid for the last message added
382 self.maildir.emitSignal(self.profile, self.name, signal) 382 self.maildir.emitSignal(self.profile, self.name, signal)
383 383
384 def getId(self, mess_idx): 384 def getId(self, mess_idx):
385 """Return the Unique ID of the message 385 """Return the Unique ID of the message
386 @mess_idx: message index""" 386 @mess_idx: message index"""
387 return self.mailbox.getUidl(mess_idx) 387 return self.mailbox.getUidl(mess_idx)
388 388
389 def getUid(self, mess_idx): 389 def getUid(self, mess_idx):
390 """Return a unique interger id for the message, always ascending""" 390 """Return a unique interger id for the message, always ascending"""
391 mess_id=self.getId(mess_idx) 391 mess_id = self.getId(mess_idx)
392 return self.maildir.getUid(self.name,mess_id, profile=self.profile) 392 return self.maildir.getUid(self.name, mess_id, profile=self.profile)
393 393
394 def getNextUid(self): 394 def getNextUid(self):
395 return self.maildir.getNextUid(self.name, profile=self.profile) 395 return self.maildir.getNextUid(self.name, profile=self.profile)
396 396
397 def getNextExistingUid(self, uid): 397 def getNextExistingUid(self, uid):
411 411
412 def getIdxFromUid(self, mess_uid): 412 def getIdxFromUid(self, mess_uid):
413 """Return the message index from the uid 413 """Return the message index from the uid
414 @param mess_uid: message unique identifier 414 @param mess_uid: message unique identifier
415 @return: message index, as managed by MaildirMailbox""" 415 @return: message index, as managed by MaildirMailbox"""
416 for mess_idx in range (self.getMessageCount()): 416 for mess_idx in range(self.getMessageCount()):
417 if self.getUid(mess_idx) == mess_uid: 417 if self.getUid(mess_idx) == mess_uid:
418 return mess_idx 418 return mess_idx
419 raise IndexError 419 raise IndexError
420 420
421 def getIdxFromId(self, mess_id): 421 def getIdxFromId(self, mess_id):
422 """Return the message index from the unique index 422 """Return the message index from the unique index
423 @param mess_id: message unique index as given by MaildirMailbox 423 @param mess_id: message unique index as given by MaildirMailbox
424 @return: message sequence index""" 424 @return: message sequence index"""
425 for mess_idx in range (self.getMessageCount()): 425 for mess_idx in range(self.getMessageCount()):
426 if self.mailbox.getUidl(mess_idx) == mess_id: 426 if self.mailbox.getUidl(mess_idx) == mess_id:
427 return mess_idx 427 return mess_idx
428 raise IndexError 428 raise IndexError
429 429
430 def getMessage(self, mess_idx): 430 def getMessage(self, mess_idx):
446 446
447 def getFlagsUid(self, mess_uid): 447 def getFlagsUid(self, mess_uid):
448 """Return the flags of the message 448 """Return the flags of the message
449 @param mess_uid: message unique identifier 449 @param mess_uid: message unique identifier
450 @return: list of strings""" 450 @return: list of strings"""
451 id = self.maildir.getIdFromUid(self.name,mess_uid, profile=self.profile) 451 id = self.maildir.getIdFromUid(self.name, mess_uid, profile=self.profile)
452 return self.maildir.getFlags(self.name, id, profile=self.profile) 452 return self.maildir.getFlags(self.name, id, profile=self.profile)
453 453
454 def setFlags(self, mess_idx, flags): 454 def setFlags(self, mess_idx, flags):
455 """Change the flags of the message 455 """Change the flags of the message
456 @param mess_idx: message index 456 @param mess_idx: message index
462 def setFlagsUid(self, mess_uid, flags): 462 def setFlagsUid(self, mess_uid, flags):
463 """Change the flags of the message 463 """Change the flags of the message
464 @param mess_uid: message unique identifier 464 @param mess_uid: message unique identifier
465 @param flags: list of strings 465 @param flags: list of strings
466 """ 466 """
467 id = self.maildir.getIdFromUid(self.name,mess_uid, profile=self.profile) 467 id = self.maildir.getIdFromUid(self.name, mess_uid, profile=self.profile)
468 return self.maildir.setFlags(self.name, id, flags, profile=self.profile) 468 return self.maildir.setFlags(self.name, id, flags, profile=self.profile)
469 469
470 def getMessageIdsWithFlag(self, flag): 470 def getMessageIdsWithFlag(self, flag):
471 """Return ids of messages where a flag is set 471 """Return ids of messages where a flag is set
472 @param flag: flag to check 472 @param flag: flag to check
473 @return: list of id (as given by MaildirMailbox)""" 473 @return: list of id (as given by MaildirMailbox)"""
474 return self.maildir.getMessageIdsWithFlag(self.name,flag, profile=self.profile) 474 return self.maildir.getMessageIdsWithFlag(self.name, flag, profile=self.profile)
475 475
476 def removeDeleted(self): 476 def removeDeleted(self):
477 """Actually delete message flagged "\\Deleted" 477 """Actually delete message flagged "\\Deleted"
478 Also purge the internal data of these messages 478 Also purge the internal data of these messages
479 """ 479 """
480 for mess_id in self.getMessageIdsWithFlag("\\Deleted"): 480 for mess_id in self.getMessageIdsWithFlag("\\Deleted"):
481 print ("Deleting %s" % mess_id) 481 print ("Deleting %s" % mess_id)
482 self.mailbox.deleteMessage(self.getIdxFromId(mess_id)) 482 self.mailbox.deleteMessage(self.getIdxFromId(mess_id))
483 self.mailbox = maildir.MaildirMailbox(self.mailbox_path) #We need to reparse the dir to have coherent indexing 483 self.mailbox = maildir.MaildirMailbox(self.mailbox_path) # We need to reparse the dir to have coherent indexing
484 self.maildir.purgeDeleted(self.name, profile=self.profile) 484 self.maildir.purgeDeleted(self.name, profile=self.profile)
485 485
486 def emptyTrash(self): 486 def emptyTrash(self):
487 """Delete everything in the .Trash dir""" 487 """Delete everything in the .Trash dir"""
488 import shutils 488 import shutils
489 pdb.set_trace() 489 pdb.set_trace()
490