changeset 257:012c38b56cdd

plugin IMAP, plugin Maildir: profile management - IMAP Login/pass is now checked against profile name/jabber pass - Mailboxes are now per-profile - flags are now checked without case sensitiveness
author Goffi <goffi@goffi.org>
date Tue, 18 Jan 2011 00:57:26 +0100
parents f5181f6dd98f
children aac82dee6091
files src/plugins/plugin_misc_imap.py src/plugins/plugin_misc_maildir.py src/sat.tac
diffstat 3 files changed, 159 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/plugin_misc_imap.py	Tue Jan 18 00:51:47 2011 +0100
+++ b/src/plugins/plugin_misc_imap.py	Tue Jan 18 00:57:26 2011 +0100
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 """
-SAT plugin for managing imap server
+SàT plugin for managing imap server
 Copyright (C) 2011  Jérôme Poisson (goffi@goffi.org)
 
 This program is free software: you can redistribute it and/or modify
@@ -21,9 +21,10 @@
 
 from logging import debug, info, error
 import warnings
-from twisted.internet import protocol
+from twisted.internet import protocol,defer
 from twisted.words.protocols.jabber import error as jab_error
-from twisted.cred import portal,checkers
+from twisted.cred import portal,checkers,credentials
+from twisted.cred import error as cred_error
 from twisted.mail import imap4
 from email.parser import Parser
 import email.message
@@ -86,7 +87,6 @@
         """Retrieve the unique identifier associated with this message.
         """
         debug('getUID (message)')
-        debug ('===>%i', self.uid)
         return self.uid
 
     def getFlags(self):
@@ -152,14 +152,13 @@
 class SatMailbox:
     implements(imap4.IMailbox)
 
-    def __init__(self,host,name):
+    def __init__(self,host,name,profile):
         self.host = host
         self.listeners=set()
         debug ('Mailbox init (%s)', name)
         if name!="INBOX":
             raise imap4.MailboxException("Only INBOX is managed for the moment")
-        self.name=name
-        self.mailbox=self.host.plugins["Maildir"].accessMessageBox("INBOX",self.newMessage)
+        self.mailbox=self.host.plugins["Maildir"].accessMessageBox(name,self.newMessage, profile)
 
     def newMessage(self):
         """Called when a new message is in the mailbox"""
@@ -207,7 +206,7 @@
         """Return the number of messages with the 'Unseen' flag.
         """
         debug('getUnseenCount')
-        return self.getMessageCount()-len(self.mailbox.getMessageIdsWithFlag('\\Seen'))
+        return self.getMessageCount()-len(self.mailbox.getMessageIdsWithFlag('\\SEEN'))
 
     def isWriteable(self):
         """Get the read/write status of the mailbox.
@@ -271,7 +270,7 @@
         invoked otherwise.
         """
         debug('addMessage')
-        raise NotImplementedError
+        raise imap4.MailboxException("Client message addition not implemented yet")
 
     def expunge(self):
         """Remove all messages flagged \\Deleted.
@@ -323,6 +322,8 @@
         """
         debug('store')
 
+        flags=[flag.upper() for flag in flags]
+
         def updateFlags(getF,setF):
             ret = {}
             for mess_id in messages:
@@ -335,16 +336,27 @@
                     _flags.update(set(flags))
                 new_flags=list(_flags)
                 setF(mess_id, new_flags)
-                ret[mess_id] = new_flags
+                ret[mess_id] = tuple(new_flags)
             return ret
             
         if uid:
             messages.last = self.mailbox.getMaxUid()
             messages.getnext = self.mailbox.getNextExistingUid
-            return updateFlags(self.mailbox.getFlagsUid,self.mailbox.setFlagsUid)
+            ret = updateFlags(self.mailbox.getFlagsUid,self.mailbox.setFlagsUid)
+            for listener in self.listeners:
+                listener.flagsChanged(ret)
+            return ret
+            
         else:
             messages.last = self.getMessageCount()
-            return updateFlags(self.mailbox.getFlags,self.mailbox.setFlags)
+            ret = updateFlags(self.mailbox.getFlags,self.mailbox.setFlags)
+            newFlags={}
+            for idx in ret:
+                #we have to convert idx to uid for the listeners
+                newFlags[self.mailbox.getUid(idx)] = ret[idx]
+            for listener in self.listeners:
+                listener.flagsChanged(newFlags)
+            return ret
 
     def getFlags(self):
         """Return the flags defined in this mailbox
@@ -352,7 +364,7 @@
         @return: A list of the flags that can be set on messages in this mailbox.
         """
         debug('getFlags')
-        return ['\Seen','\Answered','\Flagged','\Deleted','\Draft'] #TODO: add '\Recent'
+        return ['\\SEEN','\\ANSWERED','\\FLAGGED','\\DELETED','\\DRAFT'] #TODO: add '\\RECENT'
 
     def getHierarchicalDelimiter(self):
         """Get the character which delimits namespaces for in this mailbox.
@@ -360,21 +372,19 @@
         debug('getHierarchicalDelimiter')
         return '.'
 
-
-
-class ImapAccount(imap4.MemoryAccount):
+class ImapSatAccount(imap4.MemoryAccount):
     #implements(imap4.IAccount)
-    # Actually implement the interface here
 
-    def __init__(self, host, name):
+    def __init__(self, host, profile):
         debug("ImapAccount init")
         self.host=host
-        imap4.MemoryAccount.__init__(self,name)
+        self.profile=profile
+        imap4.MemoryAccount.__init__(self,profile)
         self.addMailbox("Inbox") #We only manage Inbox for the moment
         debug ('INBOX added')
 
     def _emptyMailbox(self, name, id):
-        return SatMailbox(self.host,name)
+        return SatMailbox(self.host,name,self.profile)
 
 
 class ImapRealm:
@@ -385,9 +395,40 @@
 
     def requestAvatar(self, avatarID, mind, *interfaces):
         debug('requestAvatar')
+        profile=avatarID.decode('utf-8')
         if imap4.IAccount not in interfaces:
             raise NotImplementedError
-        return imap4.IAccount, ImapAccount(self.host,avatarID), lambda:None
+        return imap4.IAccount, ImapSatAccount(self.host,profile), lambda:None
+
+class SatProfileCredentialChecker:
+    """
+    This credential checker check against SàT's profile and associated jabber's password
+    Check if the profile exists, and if the password is OK
+    Return the profile as avatarId
+    """
+    implements(checkers.ICredentialsChecker)
+    credentialInterfaces = (credentials.IUsernamePassword,
+                            credentials.IUsernameHashedPassword)
+
+    
+    def __init__(self, host):
+        self.host = host
+
+    def _cbPasswordMatch(self, matched, profile):
+        if matched:
+            return profile.encode('utf-8')
+        else:
+            return failure.Failure(cred_error.UnauthorizedLogin())
+
+    def requestAvatarId(self, credentials):
+        profiles = self.host.memory.getProfilesList()
+        if not credentials.username in profiles:
+            return defer.fail(cred_error.UnauthorizedLogin())
+        password = self.host.memory.getParamA("Password", "Connection", profile_key=credentials.username)
+        return defer.maybeDeferred(
+            credentials.checkPassword,
+            password).addCallback(
+            self._cbPasswordMatch, credentials.username)
 
 class ImapServerFactory(protocol.ServerFactory):
     protocol = imap4.IMAP4Server
@@ -405,5 +446,5 @@
         debug ("Building protocole")
         prot = protocol.ServerFactory.buildProtocol(self, addr)
         prot.portal = portal.Portal(ImapRealm(self.host))
-        prot.portal.registerChecker(checkers.InMemoryUsernamePasswordDatabaseDontUse(goffi="toto"))
+        prot.portal.registerChecker(SatProfileCredentialChecker(self.host))
         return prot
--- a/src/plugins/plugin_misc_maildir.py	Tue Jan 18 00:51:47 2011 +0100
+++ b/src/plugins/plugin_misc_maildir.py	Tue Jan 18 00:57:26 2011 +0100
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 """
-SAT plugin for managing imap server
+SàT plugin for managing Maildir type mail boxes
 Copyright (C) 2011  Jérôme Poisson (goffi@goffi.org)
 
 This program is free software: you can redistribute it and/or modify
@@ -33,6 +33,7 @@
 from cStringIO import StringIO
 from twisted.internet import reactor
 import pdb
+from sat.exceptions import *
 
 
 from zope.interface import implements
@@ -61,8 +62,9 @@
         self.host = host
 
         self.__observed={}
-        self.__mailboxes={}
-        self.data=host.memory.getPrivate("MAILDIR_data") or {"INBOX":{"cur_idx":0}}
+        pList=host.memory.getProfilesList #shorter :)
+        self.__mailboxes=dict(zip(pList(),len(pList())*[{}]))
+        self.data=host.memory.getPrivate("MAILDIR_data") or dict(zip(pList(),len(pList())*[{"INBOX":{"cur_idx":0}}])) #Create empty box for each profile
         #a value in the dictionnary for a mailbox is a dictionnary with the following value
         #    - cur_idx: value of the current unique integer increment (UID)
         #    - message_id (as returned by MaildirMailbox): a tuple of (UID, [flag1, flag2, ...])
@@ -74,18 +76,26 @@
         debug('Destroying MaildirBox')
         self.host.memory.setPrivate('MAILDIR_data',self.data)
 
-    def accessMessageBox(self, boxname, observer=None):
+    def accessMessageBox(self, boxname, observer=None, profile_key='@DEFAULT@'):
         """Create and return a MailboxUser instance
         @param boxname: name of the box
         @param observer: method to call when a NewMessage arrive"""
-        if not self.__mailboxes.has_key(boxname):
-            self.__mailboxes[boxname]=MailboxUser(self, boxname, observer)
+        profile = self.host.memory.getProfileName(profile_key)
+        if not profile:
+            raise ProfileUnknownError
+        if not self.__mailboxes[profile].has_key(boxname):
+            self.__mailboxes[profile][boxname]=MailboxUser(self, boxname, observer, profile=profile)
         else:
             if observer:
-                self.addObserver(observer, boxname)
-        return self.__mailboxes[boxname]
+                self.addObserver(observer, profile, boxname)
+        return self.__mailboxes[profile][boxname]
 
-    def _removeBoxAccess(self, boxname, mailboxUser):
+    def _getProfilePath(self, profile):
+        """Return a unique path for profile's mailbox
+        The path must be unique, usable as a dir name, and bijectional"""
+        return profile.replace('/','_').replace('..','_') #FIXME: this is too naive to work well, must be improved
+
+    def _removeBoxAccess(self, boxname, mailboxUser, profile):
         """Remove a reference to a box
         @param name: name of the box
         @param mailboxUser: MailboxUser instance"""
@@ -93,32 +103,33 @@
             err_msg=_("Trying to remove an mailboxUser not referenced")
             error(_("INTERNAL ERROR: ") + err_msg)
             raise MaildirError(err_msg)
-        assert self.__mailboxes[boxname]==mailboxUser
-        del __mailboxes[boxname]
+        assert self.__mailboxes[profile][boxname]==mailboxUser
+        del __mailboxes[profile][boxname]
 
-    def _checkBoxReference(self, boxname):
+    def _checkBoxReference(self, boxname, profile):
         """Check if there is a reference on a box, and return it
         @param boxname: name of the box to check
         @return: MailboxUser instance or None"""
-        if self.__mailboxes.has_key(boxname):
-            return self.__mailboxes[boxname]
+        if self.__mailboxes.has_key(profile):
+            if self.__mailboxes[profile].has_key(boxname):
+                return self.__mailboxes[profile][boxname]
 
-    def __getBoxData(self, boxname):
+    def __getBoxData(self, boxname, profile):
         """Return the date of a box"""
         try:
-            return self.data[boxname] #the boxname MUST exist in the data
+            return self.data[profile][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):
+    def getUid(self, boxname, message_id, profile):
         """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"""
-        box_data = self.__getBoxData(boxname)
+        box_data = self.__getBoxData(boxname, profile)
         if box_data.has_key(message_id):
             ret = box_data[message_id][0]
         else:
@@ -128,40 +139,40 @@
         self.host.memory.setPrivate('MAILDIR_data',self.data)
         return ret
 
-    def getNextUid(self, boxname):
+    def getNextUid(self, boxname, profile):
         """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"""
-        box_data = self.__getBoxData(boxname)
+        box_data = self.__getBoxData(boxname, profile)
         return box_data['cur_idx']+1
 
-    def getNextExistingUid(self, boxname, uid):
+    def getNextExistingUid(self, boxname, uid, profile):
         """Give the next uid of existing message
         @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"""
-        box_data = self.__getBoxData(boxname)
+        box_data = self.__getBoxData(boxname, profile)
         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, profile) == None: #TODO: this is highly inefficient because getIdfromUid is inefficient, fix this
             idx+=1
             if idx>box_data['cur_idx']:
                 return None
         return idx
     
-    def getMaxUid(self, boxname):
+    def getMaxUid(self, boxname, profile):
         """Give the max existing uid
         @param boxname: name of the box where the message is
         @return: uid"""
-        box_data = self.__getBoxData(boxname)
+        box_data = self.__getBoxData(boxname, profile)
         return box_data['cur_idx']
     
-    def getIdFromUid(self, boxname, message_uid):
+    def getIdFromUid(self, boxname, message_uid, profile):
         """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"""
-        box_data = self.__getBoxData(boxname)
+        box_data = self.__getBoxData(boxname, profile)
         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
@@ -169,36 +180,38 @@
                 return message_id
         return None
 
-    def getFlags(self, boxname, mess_id):
+    def getFlags(self, boxname, mess_id, profile):
         """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)
+        box_data = self.__getBoxData(boxname, profile)
         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):
+    def setFlags(self, boxname, mess_id, flags, profile):
         """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)
+        box_data = self.__getBoxData(boxname, profile)
         assert(type(flags)==list)
+        flags=[flag.upper() for flag in flags] #we store every flag UPPERCASE
         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):
+    def getMessageIdsWithFlag(self, boxname, flag, profile):
         """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)
+        box_data = self.__getBoxData(boxname, profile)
         assert(isinstance(flag,basestring))
+        flag=flag.upper()
         result = []
         for key in box_data:
             if key=='cur_idx':
@@ -207,20 +220,20 @@
                 result.append(key)
         return result
 
-    def purgeDeleted(self, boxname):
+    def purgeDeleted(self, boxname, profile):
         """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"):
+        box_data = self.__getBoxData(boxname, profile)
+        for mess_id in self.getMessageIdsWithFlag(boxname,"\\Deleted", profile):
            del(box_data[mess_id]) 
         self.host.memory.setPrivate('MAILDIR_data',self.data)
     
-    def cleanTable(self, boxname, existant_id):
+    def cleanTable(self, boxname, existant_id, profile):
         """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"""
-        box_data = self.__getBoxData(boxname)
+        box_data = self.__getBoxData(boxname, profile)
         to_remove=[]
         for key in box_data:
             if key not in existant_id and key!="cur_idx":
@@ -229,7 +242,7 @@
             del box_data[key]
         
 
-    def MessageReceivedTrigger(self, message):
+    def MessageReceivedTrigger(self, message, profile):
         """This trigger catch normal message and put the in the Maildir box.
         If the message is not of "normal" type, do nothing
         @param message: message xmlstrem
@@ -239,44 +252,44 @@
                 type = message['type'] if message.hasAttribute('type') else 'chat' #FIXME: check specs
                 if message['type'] != 'normal':
                     return True
-                self.accessMessageBox("INBOX").addMessage(message)
+                self.accessMessageBox("INBOX", profile_key=profile).addMessage(message)
                 return False
 
-    def addObserver(self, callback, boxname, signal="NEW_MESSAGE"):
+    def addObserver(self, callback, profile, boxname, signal="NEW_MESSAGE"):
         """Add an observer for maildir box changes
         @param callback: method to call when the the box is updated
         @param boxname: name of the box to observe
         @param signal: which signal is observed by the caller"""
-        if not self.__observed.has_key(boxname):
-            self.__observed[boxname]={}
-        if not self.__observed[boxname].has_key(signal):
-            self.__observed[boxname][signal]=set()
-        self.__observed[boxname][signal].add(callback)
+        if not self.__observed.has_key((profile,boxname)):
+            self.__observed[(profile,boxname)]={}
+        if not self.__observed[(profile,boxname)].has_key(signal):
+            self.__observed[(profile,boxname)][signal]=set()
+        self.__observed[(profile,boxname)][signal].add(callback)
 
-    def removeObserver(self, callback, boxname, signal="NEW_MESSAGE"):
+    def removeObserver(self, callback, profile, boxname, signal="NEW_MESSAGE"):
         """Remove an observer of maildir box changes
         @param callback: method to remove from obervers
         @param boxname: name of the box which was observed
         @param signal: which signal was observed by the caller"""
-        if not self.__observed.has_key(boxname):
+        if not self.__observed.has_key((profile,boxname)):
             err_msg=_("Trying to remove an observer for an inexistant mailbox")
             error(_("INTERNAL ERROR: ") + err_msg)
             raise MaildirError(err_msg)
-        if not self.__observed[boxname].has_key(signal):
+        if not self.__observed[(profile,boxname)].has_key(signal):
             err_msg=_("Trying to remove an inexistant observer, no observer for this signal")
             error(_("INTERNAL ERROR: ") + err_msg)
             raise MaildirError(err_msg)
-        if not callback in self.__observed[boxname][signal]:
+        if not callback in self.__observed[(profile,boxname)][signal]:
             err_msg=_("Trying to remove an inexistant observer")
             error(_("INTERNAL ERROR: ") + err_msg)
             raise MaildirError(err_msg)
-        self.__observed[boxname][signal].remove(callback)
+        self.__observed[(profile,boxname)][signal].remove(callback)
 
-    def emitSignal(self, boxname, signal_name):
+    def emitSignal(self, profile, boxname, signal_name):
         """Emit the signal to observer"""
-        debug('emitSignal %s %s' %(boxname, signal_name))
+        debug('emitSignal %s %s %s' %(profile, boxname, signal_name))
         try:
-            for observer_cb in self.__observed[boxname][signal_name]:
+            for observer_cb in self.__observed[(profile, boxname)][signal_name]:
                 observer_cb()
         except KeyError:
             pass
@@ -304,27 +317,32 @@
                 mail['Subject'] =  e.children[0].encode('utf-8')
         return mail.as_string()
     
-    def __init__(self, _maildir, name, observer=None):
+    def __init__(self, _maildir, name, observer=None, profile="@NONE@"):
         """@param _maildir: the main MaildirBox instance
            @param name: name of the mailbox
+           @param profile: real profile (ie not a profile_key)
            THIS OBJECT MUST NOT BE USED DIRECTLY: use MaildirBox.accessMessageBox instead"""
-        if _maildir._checkBoxReference(self):
+        if _maildir._checkBoxReference(name, profile):
             error ("INTERNAL ERROR: MailboxUser MUST NOT be instancied directly")
             raise MailboxException('double MailboxUser instanciation')
         if name!="INBOX":
             raise NotImplementedError
         self.name=name
+        self.profile=profile
         self.maildir=_maildir
-        mailbox_path = os.path.expanduser(os.path.join(self.maildir.host.get_const('local_dir'), MAILDIR_PATH))
+        profile_path = self.maildir._getProfilePath(profile)
+        full_profile_path = os.path.join(os.path.expanduser(self.maildir.host.get_const('local_dir')),profile_path)
+        if not os.path.exists(full_profile_path):
+            os.makedirs(full_profile_path,0700)
+        mailbox_path = os.path.join(full_profile_path, MAILDIR_PATH)
         self.mailbox_path=mailbox_path
         self.mailbox = maildir.MaildirMailbox(mailbox_path)
         self.observer=observer
         self.__uid_table_update()
         
-
         if observer:
-            debug("adding observer for %s" % name)
-            self.maildir.addObserver(observer, name, "NEW_MESSAGE")
+            debug("adding observer for %s (%s)" % (name,profile))
+            self.maildir.addObserver(observer, profile, name, "NEW_MESSAGE")
 
     def __uid_table_update(self):
         existant_id=[]
@@ -332,14 +350,14 @@
             #we update the uid table
             existant_id.append(self.getId(mess_idx))
             self.getUid(mess_idx)
-        self.maildir.cleanTable(self.name, existant_id)
+        self.maildir.cleanTable(self.name, existant_id, profile=self.profile)
     
 
     def __del__(self):
         if observer:
             debug("removing observer for %s" % self.name)
             self._maildir.removeObserver(observer, self.name, "NEW_MESSAGE")
-        self._maildir._removeBoxAccess(self.name, self)
+        self.maildir._removeBoxAccess(self.name, self, profile=self.profile)
 
     def addMessage(self, message):
         """Add a message to the box
@@ -348,8 +366,9 @@
 
     def emitSignal(self, ignore, signal):
         """Emit the signal to the observers"""
-        self.getUid(self.getMessageCount()-1) #we make an uid for the last message added
-        self.maildir.emitSignal(self.name, signal)
+        if signal=="NEW_MESSAGE":
+            self.getUid(self.getMessageCount()-1) #XXX: we make an uid for the last message added
+        self.maildir.emitSignal(self.profile, self.name, signal)
 
     def getId(self, mess_idx):
         """Return the Unique ID of the message
@@ -359,16 +378,16 @@
     def getUid(self, mess_idx):
         """Return a unique interger id for the message, always ascending"""
         mess_id=self.getId(mess_idx)
-        return self.maildir.getUid(self.name,mess_id)
+        return self.maildir.getUid(self.name,mess_id, profile=self.profile)
 
     def getNextUid(self):
-        return self.maildir.getNextUid(self.name)
+        return self.maildir.getNextUid(self.name, profile=self.profile)
 
     def getNextExistingUid(self, uid):
-        return self.maildir.getNextExistingUid(self.name, uid)
+        return self.maildir.getNextExistingUid(self.name, uid, profile=self.profile)
 
     def getMaxUid(self):
-        return self.maildir.getMaxUid(self.name)
+        return self.maildir.getMaxUid(self.name, profile=self.profile)
 
     def getMessageCount(self):
         """Return number of mails present in this box"""
@@ -412,14 +431,14 @@
         @param mess_idx: message index
         @return: list of strings"""
         id = self.getId(mess_idx)
-        return self.maildir.getFlags(self.name, id)
+        return self.maildir.getFlags(self.name, id, profile=self.profile)
     
     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)
+        id = self.maildir.getIdFromUid(self.name,mess_uid, profile=self.profile)
+        return self.maildir.getFlags(self.name, id, profile=self.profile)
 
     def setFlags(self, mess_idx, flags):
         """Change the flags of the message
@@ -427,21 +446,21 @@
         @param flags: list of strings
         """
         id = self.getId(mess_idx)
-        return self.maildir.setFlags(self.name, id, flags)
+        self.maildir.setFlags(self.name, id, flags, profile=self.profile)
 
     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)
+        id = self.maildir.getIdFromUid(self.name,mess_uid, profile=self.profile)
+        return self.maildir.setFlags(self.name, id, flags, profile=self.profile)
 
     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)
+        return self.maildir.getMessageIdsWithFlag(self.name,flag, profile=self.profile)
 
     def removeDeleted(self):
         """Actually delete message flagged "\\Deleted"
@@ -451,7 +470,7 @@
             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)
+        self.maildir.purgeDeleted(self.name, profile=self.profile)
 
     def emptyTrash(self):
         """Delete everything in the .Trash dir"""
--- a/src/sat.tac	Tue Jan 18 00:51:47 2011 +0100
+++ b/src/sat.tac	Tue Jan 18 00:57:26 2011 +0100
@@ -127,7 +127,7 @@
 
     def onMessage(self, message):
       debug (_(u"got message from: %s"), message["from"])
-      if not self.host.trigger.point("MessageReceived",message):
+      if not self.host.trigger.point("MessageReceived",message, profile=self.parent.profile):
         return
       for e in message.elements():
         if e.name == "body":