Example #1
0
    def rename(self, oldname, newname):
        """
        Renames a mailbox.

        :param oldname: old name of the mailbox
        :type oldname: str

        :param newname: new name of the mailbox
        :type newname: str
        """
        oldname = normalize_mailbox(oldname)
        newname = normalize_mailbox(newname)

        def rename_inferiors((inferiors, mailboxes)):
            rename_deferreds = []
            inferiors = [
                (o, o.replace(oldname, newname, 1)) for o in inferiors]

            for (old, new) in inferiors:
                if new in mailboxes:
                    raise imap4.MailboxCollision(repr(new))

            for (old, new) in inferiors:
                d = self.account.rename_mailbox(old, new)
                rename_deferreds.append(d)

            d1 = defer.gatherResults(rename_deferreds, consumeErrors=True)
            return d1

        d1 = self._inferiorNames(oldname)
        d2 = self.account.list_all_mailbox_names()

        d = defer.gatherResults([d1, d2])
        d.addCallback(rename_inferiors)
        return d
Example #2
0
    def rename(self, oldname, newname):
        """
        Renames a mailbox.

        :param oldname: old name of the mailbox
        :type oldname: str

        :param newname: new name of the mailbox
        :type newname: str
        """
        oldname = normalize_mailbox(oldname)
        newname = normalize_mailbox(newname)

        def rename_inferiors((inferiors, mailboxes)):
            rename_deferreds = []
            inferiors = [
                (o, o.replace(oldname, newname, 1)) for o in inferiors]

            for (old, new) in inferiors:
                if new in mailboxes:
                    raise imap4.MailboxCollision(repr(new))

            for (old, new) in inferiors:
                d = self.account.rename_mailbox(old, new)
                rename_deferreds.append(d)

            d1 = defer.gatherResults(rename_deferreds, consumeErrors=True)
            return d1

        d1 = self._inferiorNames(oldname)
        d2 = self.account.list_all_mailbox_names()

        d = defer.gatherResults([d1, d2])
        d.addCallback(rename_inferiors)
        return d
Example #3
0
    def listMailboxes(self, ref, wildcard):
        """
        List the mailboxes.

        from rfc 3501:
        returns a subset of names from the complete set
        of all names available to the client.  Zero or more untagged LIST
        replies are returned, containing the name attributes, hierarchy
        delimiter, and name.

        :param ref: reference name
        :type ref: str

        :param wildcard: mailbox name with possible wildcards
        :type wildcard: str
        """
        wildcard = imap4.wildcardToRegexp(wildcard, '/')

        def get_list(mboxes, mboxes_names):
            return zip(mboxes_names, mboxes)

        def filter_inferiors(ref):
            mboxes = [mbox for mbox in ref if wildcard.match(mbox)]
            mbox_d = defer.gatherResults([self.getMailbox(m) for m in mboxes])

            mbox_d.addCallback(get_list, mboxes)
            return mbox_d

        d = self._inferiorNames(normalize_mailbox(ref))
        d.addCallback(filter_inferiors)
        return d
Example #4
0
    def select(self, name, readwrite=1):
        """
        Selects a mailbox.

        :param name: the mailbox to select
        :type name: str

        :param readwrite: 1 for readwrite permissions.
        :type readwrite: int

        :rtype: IMAPMailbox
        """
        name = normalize_mailbox(name)

        def check_it_exists(mailboxes):
            if name not in mailboxes:
                logger.warning("SELECT: No such mailbox!")
                return None
            return name

        def set_selected(_):
            self.selected = name

        def get_collection(name):
            if name is None:
                return None
            return self.account.get_collection_by_mailbox(name)

        d = self.account.list_all_mailbox_names()
        d.addCallback(check_it_exists)
        d.addCallback(get_collection)
        d.addCallback(partial(
            self._return_mailbox_from_collection, readwrite=readwrite))
        return d
Example #5
0
    def addMailbox(self, name, creation_ts=None):
        """
        Add a mailbox to the account.

        :param name: the name of the mailbox
        :type name: str

        :param creation_ts: an optional creation timestamp to be used as
                            mailbox id. A timestamp will be used if no
                            one is provided.
        :type creation_ts: int

        :returns: a Deferred that will contain the document if successful.
        :rtype: defer.Deferred
        """
        name = normalize_mailbox(name)

        # FIXME --- return failure instead of AssertionError
        # See AccountTestCase...
        leap_assert(name, "Need a mailbox name to create a mailbox")

        def check_it_does_not_exist(mailboxes):
            if name in mailboxes:
                raise imap4.MailboxCollision, repr(name)
            return mailboxes

        d = self.account.list_all_mailbox_names()
        d.addCallback(check_it_does_not_exist)
        d.addCallback(lambda _: self.account.add_mailbox(
            name, creation_ts=creation_ts))
        d.addCallback(lambda _: self.account.get_collection_by_mailbox(name))
        d.addCallback(self._return_mailbox_from_collection)
        return d
Example #6
0
    def addMailbox(self, name, creation_ts=None):
        """
        Add a mailbox to the account.

        :param name: the name of the mailbox
        :type name: str

        :param creation_ts: an optional creation timestamp to be used as
                            mailbox id. A timestamp will be used if no
                            one is provided.
        :type creation_ts: int

        :returns: a Deferred that will contain the document if successful.
        :rtype: defer.Deferred
        """
        name = normalize_mailbox(name)

        # FIXME --- return failure instead of AssertionError
        # See AccountTestCase...
        leap_assert(name, "Need a mailbox name to create a mailbox")

        def check_it_does_not_exist(mailboxes):
            if name in mailboxes:
                raise imap4.MailboxCollision, repr(name)
            return mailboxes

        d = self.account.list_all_mailbox_names()
        d.addCallback(check_it_does_not_exist)
        d.addCallback(lambda _: self.account.add_mailbox(
            name, creation_ts=creation_ts))
        d.addCallback(lambda _: self.account.get_collection_by_mailbox(name))
        d.addCallback(self._return_mailbox_from_collection)
        return d
Example #7
0
    def select(self, name, readwrite=1):
        """
        Selects a mailbox.

        :param name: the mailbox to select
        :type name: str

        :param readwrite: 1 for readwrite permissions.
        :type readwrite: int

        :rtype: IMAPMailbox
        """
        name = normalize_mailbox(name)

        def check_it_exists(mailboxes):
            if name not in mailboxes:
                logger.warning("SELECT: No such mailbox!")
                return None
            return name

        def set_selected(_):
            self.selected = name

        def get_collection(name):
            if name is None:
                return None
            return self.account.get_collection_by_mailbox(name)

        d = self.account.list_all_mailbox_names()
        d.addCallback(check_it_exists)
        d.addCallback(get_collection)
        d.addCallback(partial(
            self._return_mailbox_from_collection, readwrite=readwrite))
        return d
Example #8
0
    def listMailboxes(self, ref, wildcard):
        """
        List the mailboxes.

        from rfc 3501:
        returns a subset of names from the complete set
        of all names available to the client.  Zero or more untagged LIST
        replies are returned, containing the name attributes, hierarchy
        delimiter, and name.

        :param ref: reference name
        :type ref: str

        :param wildcard: mailbox name with possible wildcards
        :type wildcard: str
        """
        wildcard = imap4.wildcardToRegexp(wildcard, '/')

        def get_list(mboxes, mboxes_names):
            return zip(mboxes_names, mboxes)

        def filter_inferiors(ref):
            mboxes = [mbox for mbox in ref if wildcard.match(mbox)]
            mbox_d = defer.gatherResults([self.getMailbox(m) for m in mboxes])

            mbox_d.addCallback(get_list, mboxes)
            return mbox_d

        d = self._inferiorNames(normalize_mailbox(ref))
        d.addCallback(filter_inferiors)
        return d
Example #9
0
    def get_or_create_mbox(self, store, name):
        """
        Get the mailbox with the given name, or create one if it does not
        exist.

        :param store: instance of Soledad
        :param name: the name of the mailbox
        :type name: str
        """
        index = indexes.TYPE_MBOX_IDX
        mbox = normalize_mailbox(name)
        return MailboxWrapper.get_or_create(store, index, mbox)
Example #10
0
    def get_or_create_mbox(self, store, name):
        """
        Get the mailbox with the given name, or create one if it does not
        exist.

        :param store: instance of Soledad
        :param name: the name of the mailbox
        :type name: str
        """
        index = indexes.TYPE_MBOX_IDX
        mbox = normalize_mailbox(name)
        return MailboxWrapper.get_or_create(store, index, mbox)
Example #11
0
    def delete(self, name, force=False):
        """
        Deletes a mailbox.

        :param name: the mailbox to be deleted
        :type name: str

        :param force:
            if True, it will not check for noselect flag or inferior
            names. use with care.
        :type force: bool
        :rtype: Deferred
        """
        name = normalize_mailbox(name)
        _mboxes = None

        def check_it_exists(mailboxes):
            global _mboxes
            _mboxes = mailboxes
            if name not in mailboxes:
                raise imap4.MailboxException("No such mailbox: %r" % name)

        def get_mailbox(_):
            return self.getMailbox(name)

        def destroy_mailbox(mbox):
            return mbox.destroy()

        def check_can_be_deleted(mbox):
            global _mboxes
            # See if this box is flagged \Noselect
            mbox_flags = mbox.getFlags()
            if MessageFlags.NOSELECT_FLAG in mbox_flags:
                # Check for hierarchically inferior mailboxes with this one
                # as part of their root.
                for others in _mboxes:
                    if others != name and others.startswith(name):
                        raise imap4.MailboxException(
                            "Hierarchically inferior mailboxes "
                            "exist and \\Noselect is set")
            return mbox

        d = self.account.list_all_mailbox_names()
        d.addCallback(check_it_exists)
        d.addCallback(get_mailbox)
        if not force:
            d.addCallback(check_can_be_deleted)
        d.addCallback(destroy_mailbox)
        return d
Example #12
0
    def delete(self, name, force=False):
        """
        Deletes a mailbox.

        :param name: the mailbox to be deleted
        :type name: str

        :param force:
            if True, it will not check for noselect flag or inferior
            names. use with care.
        :type force: bool
        :rtype: Deferred
        """
        name = normalize_mailbox(name)
        _mboxes = None

        def check_it_exists(mailboxes):
            global _mboxes
            _mboxes = mailboxes
            if name not in mailboxes:
                raise imap4.MailboxException("No such mailbox: %r" % name)

        def get_mailbox(_):
            return self.getMailbox(name)

        def destroy_mailbox(mbox):
            return mbox.destroy()

        def check_can_be_deleted(mbox):
            global _mboxes
            # See if this box is flagged \Noselect
            mbox_flags = mbox.getFlags()
            if MessageFlags.NOSELECT_FLAG in mbox_flags:
                # Check for hierarchically inferior mailboxes with this one
                # as part of their root.
                for others in _mboxes:
                    if others != name and others.startswith(name):
                        raise imap4.MailboxException(
                            "Hierarchically inferior mailboxes "
                            "exist and \\Noselect is set")
            return mbox

        d = self.account.list_all_mailbox_names()
        d.addCallback(check_it_exists)
        d.addCallback(get_mailbox)
        if not force:
            d.addCallback(check_can_be_deleted)
        d.addCallback(destroy_mailbox)
        return d
Example #13
0
    def create(self, pathspec):
        """
        Create a new mailbox from the given hierarchical name.

        :param pathspec:
            The full hierarchical name of a new mailbox to create.
            If any of the inferior hierarchical names to this one
            do not exist, they are created as well.
        :type pathspec: str

        :return:
            A deferred that will fire with a true value if the creation
            succeeds. The deferred might fail with a MailboxException
            if the mailbox cannot be added.
        :rtype: Deferred

        """
        def pass_on_collision(failure):
            failure.trap(imap4.MailboxCollision)
            return True

        def handle_collision(failure):
            failure.trap(imap4.MailboxCollision)
            if not pathspec.endswith('/'):
                return defer.succeed(False)
            else:
                return defer.succeed(True)

        def all_good(result):
            return all(result)

        paths = filter(None, normalize_mailbox(pathspec).split('/'))
        subs = []
        sep = '/'

        for accum in range(1, len(paths)):
            partial_path = sep.join(paths[:accum])
            d = self.addMailbox(partial_path)
            d.addErrback(pass_on_collision)
            subs.append(d)

        df = self.addMailbox(sep.join(paths))
        df.addErrback(handle_collision)
        subs.append(df)

        d1 = defer.gatherResults(subs)
        d1.addCallback(all_good)
        return d1
Example #14
0
    def create(self, pathspec):
        """
        Create a new mailbox from the given hierarchical name.

        :param pathspec:
            The full hierarchical name of a new mailbox to create.
            If any of the inferior hierarchical names to this one
            do not exist, they are created as well.
        :type pathspec: str

        :return:
            A deferred that will fire with a true value if the creation
            succeeds. The deferred might fail with a MailboxException
            if the mailbox cannot be added.
        :rtype: Deferred

        """
        def pass_on_collision(failure):
            failure.trap(imap4.MailboxCollision)
            return True

        def handle_collision(failure):
            failure.trap(imap4.MailboxCollision)
            if not pathspec.endswith('/'):
                return defer.succeed(False)
            else:
                return defer.succeed(True)

        def all_good(result):
            return all(result)

        paths = filter(None, normalize_mailbox(pathspec).split('/'))
        subs = []
        sep = '/'

        for accum in range(1, len(paths)):
            partial_path = sep.join(paths[:accum])
            d = self.addMailbox(partial_path)
            d.addErrback(pass_on_collision)
            subs.append(d)

        df = self.addMailbox(sep.join(paths))
        df.addErrback(handle_collision)
        subs.append(df)

        d1 = defer.gatherResults(subs)
        d1.addCallback(all_good)
        return d1
Example #15
0
    def subscribe(self, name):
        """
        Subscribe to this mailbox if not already subscribed.

        :param name: name of the mailbox
        :type name: str
        :rtype: Deferred
        """
        name = normalize_mailbox(name)

        def set_subscribed(mbox):
            return mbox.collection.set_mbox_attr("subscribed", True)

        d = self.getMailbox(name)
        d.addCallback(set_subscribed)
        return d
Example #16
0
    def subscribe(self, name):
        """
        Subscribe to this mailbox if not already subscribed.

        :param name: name of the mailbox
        :type name: str
        :rtype: Deferred
        """
        name = normalize_mailbox(name)

        def set_subscribed(mbox):
            return mbox.collection.set_mbox_attr("subscribed", True)

        d = self.getMailbox(name)
        d.addCallback(set_subscribed)
        return d
Example #17
0
    def isSubscribed(self, name):
        """
        Returns True if user is subscribed to this mailbox.

        :param name: the mailbox to be checked.
        :type name: str

        :rtype: Deferred (will fire with bool)
        """
        name = normalize_mailbox(name)

        def get_subscribed(mbox):
            return mbox.collection.get_mbox_attr("subscribed")

        d = self.getMailbox(name)
        d.addCallback(get_subscribed)
        return d
Example #18
0
    def isSubscribed(self, name):
        """
        Returns True if user is subscribed to this mailbox.

        :param name: the mailbox to be checked.
        :type name: str

        :rtype: Deferred (will fire with bool)
        """
        name = normalize_mailbox(name)

        def get_subscribed(mbox):
            return mbox.collection.get_mbox_attr("subscribed")

        d = self.getMailbox(name)
        d.addCallback(get_subscribed)
        return d
Example #19
0
    def unsubscribe(self, name):
        """
        Unsubscribe from this mailbox

        :param name: name of the mailbox
        :type name: str
        :rtype: Deferred
        """
        # TODO should raise MailboxException if attempted to unsubscribe
        # from a mailbox that is not currently subscribed.
        # TODO factor out with subscribe method.
        name = normalize_mailbox(name)

        def set_unsubscribed(mbox):
            return mbox.collection.set_mbox_attr("subscribed", False)

        d = self.getMailbox(name)
        d.addCallback(set_unsubscribed)
        return d
Example #20
0
    def unsubscribe(self, name):
        """
        Unsubscribe from this mailbox

        :param name: name of the mailbox
        :type name: str
        :rtype: Deferred
        """
        # TODO should raise MailboxException if attempted to unsubscribe
        # from a mailbox that is not currently subscribed.
        # TODO factor out with subscribe method.
        name = normalize_mailbox(name)

        def set_unsubscribed(mbox):
            return mbox.collection.set_mbox_attr("subscribed", False)

        d = self.getMailbox(name)
        d.addCallback(set_unsubscribed)
        return d
Example #21
0
    def getMailbox(self, name):
        """
        Return a Mailbox with that name, without selecting it.

        :param name: name of the mailbox
        :type name: str

        :returns: an IMAPMailbox instance
        :rtype: IMAPMailbox
        """
        name = normalize_mailbox(name)

        def check_it_exists(mailboxes):
            if name not in mailboxes:
                raise imap4.MailboxException("No such mailbox: %r" % name)
            return True

        d = self.account.list_all_mailbox_names()
        d.addCallback(check_it_exists)
        d.addCallback(lambda _: self.account.get_collection_by_mailbox(name))
        d.addCallback(self._return_mailbox_from_collection)
        return d
Example #22
0
    def getMailbox(self, name):
        """
        Return a Mailbox with that name, without selecting it.

        :param name: name of the mailbox
        :type name: str

        :returns: an IMAPMailbox instance
        :rtype: IMAPMailbox
        """
        name = normalize_mailbox(name)

        def check_it_exists(mailboxes):
            if name not in mailboxes:
                raise imap4.MailboxException("No such mailbox: %r" % name)
            return True

        d = self.account.list_all_mailbox_names()
        d.addCallback(check_it_exists)
        d.addCallback(lambda _: self.account.get_collection_by_mailbox(name))
        d.addCallback(self._return_mailbox_from_collection)
        return d