Пример #1
0
    def _messagelabels_aux(self, arg, uidlist, labels):
        """Common code to savemessagelabels and addmessagelabels"""
        labels = labels - self.ignorelabels
        uidlist = [uid for uid in uidlist if uid > 0]
        if len(uidlist) > 0:
            imapobj = self.imapserver.acquireconnection()
            try:
                labels_str = '(' + ' '.join(
                    [imaputil.quote(lb) for lb in labels]) + ')'
                # Coalesce uid's into ranges
                uid_str = imaputil.uid_sequence(uidlist)
                result = self._store_to_imap(imapobj, uid_str, arg, labels_str)

            except imapobj.readonly:
                self.ui.labelstoreadonly(self, uidlist, labels)
                return None

            finally:
                self.imapserver.releaseconnection(imapobj)

            if result:
                retlabels = imaputil.flags2hash(
                    imaputil.imapsplit(result)[1])['X-GM-LABELS']
                retlabels = set([
                    imaputil.dequote(lb)
                    for lb in imaputil.imapsplit(retlabels)
                ])
                return retlabels
        return None
Пример #2
0
    def _msgs_to_fetch(self, imapobj):
        """Determines sequence numbers of messages to be fetched.

        Message sequence numbers (MSNs) are more easily compacted
        into ranges which makes transactions slightly faster.

        Arguments:
        - imapobj: instance of IMAPlib

        Returns: range(s) for messages or None if no messages
        are to be fetched."""

        res_type, imapdata = imapobj.select(self.getfullname(), True, True)
        if imapdata == [None] or imapdata[0] == '0':
            # Empty folder, no need to populate message list
            return None

        # By default examine all messages in this folder
        msgsToFetch = '1:*'

        maxage = self.config.getdefaultint(
            "Account %s"% self.accountname, "maxage", -1)
        maxsize = self.config.getdefaultint(
            "Account %s"% self.accountname, "maxsize", -1)

        # Build search condition
        if (maxage != -1) | (maxsize != -1):
            search_cond = "(";

            if(maxage != -1):
                #find out what the oldest message is that we should look at
                oldest_struct = time.gmtime(time.time() - (60*60*24*maxage))
                if oldest_struct[0] < 1900:
                    raise OfflineImapError("maxage setting led to year %d. "
                        "Abort syncing."% oldest_struct[0],
                        OfflineImapError.ERROR.REPO)
                search_cond += "SINCE %02d-%s-%d"% (
                    oldest_struct[2],
                    MonthNames[oldest_struct[1]],
                    oldest_struct[0])

            if(maxsize != -1):
                if(maxage != -1): # There are two conditions, add space
                    search_cond += " "
                search_cond += "SMALLER %d"% maxsize

            search_cond += ")"

            res_type, res_data = imapobj.search(None, search_cond)
            if res_type != 'OK':
                raise OfflineImapError("SEARCH in folder [%s]%s failed. "
                    "Search string was '%s'. Server responded '[%s] %s'"% (
                    self.getrepository(), self, search_cond, res_type, res_data),
                    OfflineImapError.ERROR.FOLDER)

            # Resulting MSN are separated by space, coalesce into ranges
            msgsToFetch = imaputil.uid_sequence(res_data[0].split())

        return msgsToFetch
Пример #3
0
    def _msgs_to_fetch(self, imapobj, min_date=None, min_uid=None):
        """Determines sequence numbers of messages to be fetched.

        Message sequence numbers (MSNs) are more easily compacted
        into ranges which makes transactions slightly faster.

        Arguments:
        - imapobj: instance of IMAPlib
        - min_date (optional): a time_struct; only fetch messages newer than this
        - min_uid (optional): only fetch messages with UID >= min_uid

        This function should be called with at MOST one of min_date OR
        min_uid set but not BOTH.

        Returns: range(s) for messages or None if no messages
        are to be fetched."""
        def search(search_conditions):
            """Actually request the server with the specified conditions.

            Returns: range(s) for messages or None if no messages
            are to be fetched."""
            res_type, res_data = imapobj.search(None, search_conditions)
            if res_type != 'OK':
                raise OfflineImapError(
                    "SEARCH in folder [%s]%s failed. "
                    "Search string was '%s'. Server responded '[%s] %s'" %
                    (self.getrepository(), self, search_cond, res_type,
                     res_data), OfflineImapError.ERROR.FOLDER)
            return res_data[0].split()

        res_type, imapdata = imapobj.select(self.getfullname(), True, True)
        if imapdata == [None] or imapdata[0] == '0':
            # Empty folder, no need to populate message list.
            return None

        conditions = []
        # 1. min_uid condition.
        if min_uid != None:
            conditions.append("UID %d:*" % min_uid)
        # 2. date condition.
        elif min_date != None:
            # Find out what the oldest message is that we should look at.
            conditions.append(
                "SINCE %02d-%s-%d" %
                (min_date[2], MonthNames[min_date[1]], min_date[0]))
        # 3. maxsize condition.
        maxsize = self.getmaxsize()
        if maxsize != None:
            conditions.append("SMALLER %d" % maxsize)

        if len(conditions) >= 1:
            # Build SEARCH command.
            search_cond = "(%s)" % ' '.join(conditions)
            search_result = search(search_cond)
            return imaputil.uid_sequence(search_result)

        # By default consider all messages in this folder.
        return '1:*'
Пример #4
0
    def _msgs_to_fetch(self, imapobj, min_date=None, min_uid=None):
        """Determines sequence numbers of messages to be fetched.

        Message sequence numbers (MSNs) are more easily compacted
        into ranges which makes transactions slightly faster.

        Arguments:
        - imapobj: instance of IMAPlib
        - min_date (optional): a time_struct; only fetch messages newer than this
        - min_uid (optional): only fetch messages with UID >= min_uid

        This function should be called with at MOST one of min_date OR
        min_uid set but not BOTH.

        Returns: range(s) for messages or None if no messages
        are to be fetched."""

        def search(search_conditions):
            """Actually request the server with the specified conditions.

            Returns: range(s) for messages or None if no messages
            are to be fetched."""
            res_type, res_data = imapobj.search(None, search_conditions)
            if res_type != "OK":
                raise OfflineImapError(
                    "SEARCH in folder [%s]%s failed. "
                    "Search string was '%s'. Server responded '[%s] %s'"
                    % (self.getrepository(), self, search_cond, res_type, res_data),
                    OfflineImapError.ERROR.FOLDER,
                )
            return res_data[0].split()

        res_type, imapdata = imapobj.select(self.getfullname(), True, True)
        if imapdata == [None] or imapdata[0] == "0":
            # Empty folder, no need to populate message list.
            return None

        conditions = []
        # 1. min_uid condition.
        if min_uid != None:
            conditions.append("UID %d:*" % min_uid)
        # 2. date condition.
        elif min_date != None:
            # Find out what the oldest message is that we should look at.
            conditions.append("SINCE %02d-%s-%d" % (min_date[2], MonthNames[min_date[1]], min_date[0]))
        # 3. maxsize condition.
        maxsize = self.getmaxsize()
        if maxsize != None:
            conditions.append("SMALLER %d" % maxsize)

        if len(conditions) >= 1:
            # Build SEARCH command.
            search_cond = "(%s)" % " ".join(conditions)
            search_result = search(search_cond)
            return imaputil.uid_sequence(search_result)

        # By default consider all messages in this folder.
        return "1:*"
Пример #5
0
    def __processmessagesflags(self, operation, uidlist, flags):
        # XXX: should really iterate over batches of 100 UIDs
        if len(uidlist) > 101:
            # Hack for those IMAP servers with a limited line length
            self.__processmessagesflags(operation, uidlist[:100], flags)
            self.__processmessagesflags(operation, uidlist[100:], flags)
            return

        imapobj = self.imapserver.acquireconnection()
        try:
            try:
                imapobj.select(self.getfullname())
            except imapobj.readonly:
                self.ui.flagstoreadonly(self, uidlist, flags)
                return
            r = imapobj.uid('store',
                            imaputil.uid_sequence(uidlist),
                            operation + 'FLAGS',
                            imaputil.flagsmaildir2imap(flags))
            assert r[0] == 'OK', 'Error with store: ' + '. '.join(r[1])
            r = r[1]
        finally:
            self.imapserver.releaseconnection(imapobj)
        # Some IMAP servers do not always return a result.  Therefore,
        # only update the ones that it talks about, and manually fix
        # the others.
        needupdate = list(uidlist)
        for result in r:
            if result == None:
                # Compensate for servers that don't return anything from
                # STORE.
                continue
            attributehash = imaputil.flags2hash(imaputil.imapsplit(result)[1])
            if not ('UID' in attributehash and 'FLAGS' in attributehash):
                # Compensate for servers that don't return a UID attribute.
                continue
            flagstr = attributehash['FLAGS']
            uid = long(attributehash['UID'])
            self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flagstr)
            try:
                needupdate.remove(uid)
            except ValueError:          # Let it slide if it's not in the list
                pass
        for uid in needupdate:
            if operation == '+':
                self.messagelist[uid]['flags'] |= flags
            elif operation == '-':
                self.messagelist[uid]['flags'] -= flags
Пример #6
0
    def __processmessagesflags(self, operation, uidlist, flags):
        # XXX: should really iterate over batches of 100 UIDs
        if len(uidlist) > 101:
            # Hack for those IMAP servers with a limited line length
            self.__processmessagesflags(operation, uidlist[:100], flags)
            self.__processmessagesflags(operation, uidlist[100:], flags)
            return

        imapobj = self.imapserver.acquireconnection()
        try:
            try:
                imapobj.select(self.getfullname())
            except imapobj.readonly:
                self.ui.flagstoreadonly(self, uidlist, flags)
                return
            r = imapobj.uid('store', imaputil.uid_sequence(uidlist),
                            operation + 'FLAGS',
                            imaputil.flagsmaildir2imap(flags))
            assert r[0] == 'OK', 'Error with store: ' + '. '.join(r[1])
            r = r[1]
        finally:
            self.imapserver.releaseconnection(imapobj)
        # Some IMAP servers do not always return a result.  Therefore,
        # only update the ones that it talks about, and manually fix
        # the others.
        needupdate = list(uidlist)
        for result in r:
            if result == None:
                # Compensate for servers that don't return anything from
                # STORE.
                continue
            attributehash = imaputil.flags2hash(imaputil.imapsplit(result)[1])
            if not ('UID' in attributehash and 'FLAGS' in attributehash):
                # Compensate for servers that don't return a UID attribute.
                continue
            flagstr = attributehash['FLAGS']
            uid = long(attributehash['UID'])
            self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(
                flagstr)
            try:
                needupdate.remove(uid)
            except ValueError:  # Let it slide if it's not in the list
                pass
        for uid in needupdate:
            if operation == '+':
                self.messagelist[uid]['flags'] |= flags
            elif operation == '-':
                self.messagelist[uid]['flags'] -= flags
Пример #7
0
    def _msgs_to_fetch(self, imapobj):
        maxage = self.config.getdefaultint("Account %s" % self.accountname,
                                           "maxage", -1)
        maxsize = self.config.getdefaultint("Account %s" % self.accountname,
                                            "maxsize", -1)

        res_type, imapdata = imapobj.select(self.getfullname(), True, True)
        if imapdata == [None] or imapdata[0] == '0':
            # Empty folder, no need to populate message list
            return

        # By default examine all UIDs in this folder
        msgsToFetch = '1:*'

        # Build search condition
        if (maxage != -1) | (maxsize != -1):
            search_cond = "(";

            if(maxage != -1):
                #find out what the oldest message is that we should look at
                oldest_struct = time.gmtime(time.time() - (60*60*24*maxage))
                if oldest_struct[0] < 1900:
                    raise OfflineImapError("maxage setting led to year %d. "
                                           "Abort syncing." % oldest_struct[0],
                                           OfflineImapError.ERROR.REPO)
                search_cond += "SINCE %02d-%s-%d" % (
                    oldest_struct[2],
                    MonthNames[oldest_struct[1]],
                    oldest_struct[0])

            if(maxsize != -1):
                if(maxage != -1): # There are two conditions, add space
                    search_cond += " "
                search_cond += "SMALLER %d" % maxsize

            search_cond += ")"

            res_type, res_data = imapobj.search(None, search_cond)
            if res_type != 'OK':
                raise OfflineImapError("SEARCH in folder [%s]%s failed. "
                    "Search string was '%s'. Server responded '[%s] %s'" % (
                    self.getrepository(), self, search_cond, res_type, res_data),
                    OfflineImapError.ERROR.FOLDER)

            # Result UIDs are seperated by space, coalesce into ranges
            msgsToFetch = imaputil.uid_sequence(res_data[0].split())

        return msgsToFetch
Пример #8
0
    def processmessagesflags(self, operation, uidlist, flags):
        if len(uidlist) > 101:
            # Hack for those IMAP ervers with a limited line length
            self.processmessagesflags(operation, uidlist[:100], flags)
            self.processmessagesflags(operation, uidlist[100:], flags)
            return

        imapobj = self.imapserver.acquireconnection()
        try:
            try:
                imapobj.select(self.getfullname())
            except imapobj.readonly:
                self.ui.flagstoreadonly(self, uidlist, flags)
                return
            r = imapobj.uid(
                "store", imaputil.uid_sequence(uidlist), operation + "FLAGS", imaputil.flagsmaildir2imap(flags)
            )
            assert r[0] == "OK", "Error with store: " + ". ".join(r[1])
            r = r[1]
        finally:
            self.imapserver.releaseconnection(imapobj)
        # Some IMAP servers do not always return a result.  Therefore,
        # only update the ones that it talks about, and manually fix
        # the others.
        needupdate = list(uidlist)
        for result in r:
            if result == None:
                # Compensate for servers that don't return anything from
                # STORE.
                continue
            attributehash = imaputil.flags2hash(imaputil.imapsplit(result)[1])
            if not ("UID" in attributehash and "FLAGS" in attributehash):
                # Compensate for servers that don't return a UID attribute.
                continue
            flagstr = attributehash["FLAGS"]
            uid = long(attributehash["UID"])
            self.messagelist[uid]["flags"] = imaputil.flagsimap2maildir(flagstr)
            try:
                needupdate.remove(uid)
            except ValueError:  # Let it slide if it's not in the list
                pass
        for uid in needupdate:
            if operation == "+":
                self.messagelist[uid]["flags"] |= flags
            elif operation == "-":
                self.messagelist[uid]["flags"] -= flags
Пример #9
0
 def __processmessagesflags_real(self, operation, uidlist, flags):
     imapobj = self.imapserver.acquireconnection()
     try:
         try:
             imapobj.select(self.getfullname())
         except imapobj.readonly:
             self.ui.flagstoreadonly(self, uidlist, flags)
             return
         response = imapobj.uid('store', imaputil.uid_sequence(uidlist),
                                operation + 'FLAGS',
                                imaputil.flagsmaildir2imap(flags))
         if response[0] != 'OK':
             raise OfflineImapError(
                 'Error with store: %s' % '. '.join(response[1]),
                 OfflineImapError.ERROR.MESSAGE)
         response = response[1]
     finally:
         self.imapserver.releaseconnection(imapobj)
     # Some IMAP servers do not always return a result.  Therefore,
     # only update the ones that it talks about, and manually fix
     # the others.
     needupdate = list(uidlist)
     for result in response:
         if result is None:
             # Compensate for servers that don't return anything from
             # STORE.
             continue
         attributehash = imaputil.flags2hash(imaputil.imapsplit(result)[1])
         if not ('UID' in attributehash and 'FLAGS' in attributehash):
             # Compensate for servers that don't return a UID attribute.
             continue
         flagstr = attributehash['FLAGS']
         uid = int(attributehash['UID'])
         self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(
             flagstr)
         try:
             needupdate.remove(uid)
         except ValueError:  # Let it slide if it's not in the list.
             pass
     for uid in needupdate:
         if operation == '+':
             self.messagelist[uid]['flags'] |= flags
         elif operation == '-':
             self.messagelist[uid]['flags'] -= flags
Пример #10
0
 def __processmessagesflags_real(self, operation, uidlist, flags):
     imapobj = self.imapserver.acquireconnection()
     try:
         try:
             imapobj.select(self.getfullname())
         except imapobj.readonly:
             self.ui.flagstoreadonly(self, uidlist, flags)
             return
         response = imapobj.uid('store',
             imaputil.uid_sequence(uidlist), operation + 'FLAGS',
                 imaputil.flagsmaildir2imap(flags))
         if response[0] != 'OK':
             raise OfflineImapError(
                 'Error with store: %s'% '. '.join(response[1]),
                 OfflineImapError.ERROR.MESSAGE)
         response = response[1]
     finally:
         self.imapserver.releaseconnection(imapobj)
     # Some IMAP servers do not always return a result.  Therefore,
     # only update the ones that it talks about, and manually fix
     # the others.
     needupdate = list(uidlist)
     for result in response:
         if result is None:
             # Compensate for servers that don't return anything from
             # STORE.
             continue
         attributehash = imaputil.flags2hash(imaputil.imapsplit(result)[1])
         if not ('UID' in attributehash and 'FLAGS' in attributehash):
             # Compensate for servers that don't return a UID attribute.
             continue
         flagstr = attributehash['FLAGS']
         uid = int(attributehash['UID'])
         self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flagstr)
         try:
             needupdate.remove(uid)
         except ValueError:  # Let it slide if it's not in the list.
             pass
     for uid in needupdate:
         if operation == '+':
             self.messagelist[uid]['flags'] |= flags
         elif operation == '-':
             self.messagelist[uid]['flags'] -= flags
Пример #11
0
    def deletemessages_noconvert(self, uidlist):
        uidlist = [uid for uid in uidlist if uid in self.messagelist]
        if not len(uidlist):
            return

        if self.realdelete and not (self.getname() in self.real_delete_folders):
            # IMAP expunge is just "remove label" in this folder,
            # so map the request into a "move into Trash"

            imapobj = self.imapserver.acquireconnection()
            try:
                imapobj.select(self.getfullname())
                result = imapobj.uid('copy',
                                     imaputil.uid_sequence(uidlist),
                                     self.trash_folder)
                assert result[0] == 'OK', \
                       "Bad IMAPlib result: %s" % result[0]
            finally:
                self.imapserver.releaseconnection(imapobj)
            for uid in uidlist:
                del self.messagelist[uid]
        else:
            IMAPFolder.deletemessages_noconvert(self, uidlist)
Пример #12
0
    def _messagelabels_aux(self, arg, uidlist, labels):
        """Common code to savemessagelabels and addmessagelabels"""
        labels = labels - self.ignorelabels
        uidlist = [uid for uid in uidlist if uid > 0]
        if len(uidlist) > 0:
            imapobj = self.imapserver.acquireconnection()
            try:
                labels_str = '(' + ' '.join([imaputil.quote(lb) for lb in labels]) + ')'
                # Coalesce uid's into ranges
                uid_str = imaputil.uid_sequence(uidlist)
                result = self._store_to_imap(imapobj, uid_str, arg, labels_str)

            except imapobj.readonly:
                self.ui.labelstoreadonly(self, uidlist, data)
                return None

            finally:
                self.imapserver.releaseconnection(imapobj)

            if result:
                retlabels = imaputil.flags2hash(imaputil.imapsplit(result)[1])['X-GM-LABELS']
                retlabels = set([imaputil.dequote(lb) for lb in imaputil.imapsplit(retlabels)])
                return retlabels
        return None
Пример #13
0
    def _msgs_to_fetch(self, imapobj, min_date=None, min_uid=None):
        """Determines sequence numbers of messages to be fetched.

        Message sequence numbers (MSNs) are more easily compacted
        into ranges which makes transactions slightly faster.

        Arguments:
        - imapobj: instance of IMAPlib
        - min_date (optional): a time_struct; only fetch messages newer
          than this
        - min_uid (optional): only fetch messages with UID >= min_uid

        This function should be called with at MOST one of min_date OR
        min_uid set but not BOTH.

        Returns: range(s) for messages or None if no messages
        are to be fetched."""

        def search(search_conditions):
            """Actually request the server with the specified conditions.

            Returns: range(s) for messages or None if no messages
            are to be fetched."""
            try:
                res_type, res_data = imapobj.search(None, search_conditions)
                if res_type != 'OK':
                    msg = "SEARCH in folder [%s]%s failed. " \
                          "Search string was '%s'. " \
                          "Server responded '[%s] %s'" % \
                          (self.getrepository(), self, search_cond,
                           res_type, res_data)
                    raise OfflineImapError(msg, OfflineImapError.ERROR.FOLDER)
            except Exception as e:
                msg = "SEARCH in folder [%s]%s failed. "\
                      "Search string was '%s'. Error: %s" % \
                      (self.getrepository(), self, search_cond, str(e))
                raise OfflineImapError(msg, OfflineImapError.ERROR.FOLDER)

            """
            In Py2, with IMAP, imaplib2 returned a list of one element string.
              ['1, 2, 3, ...'] -> in Py3 is [b'1 2 3,...']
            In Py2, with Davmail, imaplib2 returned a list of strings.
              ['1', '2', '3', ...] -> in Py3 should be [b'1', b'2', b'3',...]

            In my tests with Py3, I get a list with one element: [b'1 2 3 ...']
            Then I convert the values to string and I get ['1 2 3 ...']

            With Davmail, it should be [b'1', b'2', b'3',...]
            When I convert the values to string, I get ['1', '2', '3',...]
            """
            res_data = [x.decode('utf-8') for x in res_data]

            # Then, I can do the check in the same way than Python 2
            # with string comparison:
            if len(res_data) > 0 and (' ' in res_data[0] or res_data[0] == ''):
                res_data = res_data[0].split()
            # Some servers are broken.
            if 0 in res_data:
                self.ui.warn("server returned UID with 0; ignoring.")
                res_data.remove(0)
            return res_data

        a = self.getfullIMAPname()
        res_type, imapdata = imapobj.select(a, True, True)

        # imaplib2 returns the type as string, like "OK" but
        # returns imapdata as list of bytes, like [b'0'] so we need decode it
        # to use the existing code
        imapdata = [x.decode('utf-8') for x in imapdata]

        if imapdata == [None] or imapdata[0] == '0':
            # Empty folder, no need to populate message list.
            return None

        conditions = []
        # 1. min_uid condition.
        if min_uid is not None:
            conditions.append("UID %d:*" % min_uid)
        # 2. date condition.
        elif min_date is not None:
            # Find out what the oldest message is that we should look at.
            conditions.append("SINCE %02d-%s-%d" % (
                min_date[2], MonthNames[min_date[1]], min_date[0]))
        # 3. maxsize condition.
        maxsize = self.getmaxsize()
        if maxsize is not None:
            conditions.append("SMALLER %d" % maxsize)

        if len(conditions) >= 1:
            # Build SEARCH command.
            search_cond = "(%s)" % ' '.join(conditions)
            search_result = search(search_cond)
            return imaputil.uid_sequence(search_result)

        # By default consider all messages in this folder.
        return '1:*'
Пример #14
0
    def cachemessagelist(self):
        maxage = self.config.getdefaultint("Account %s" % self.accountname, "maxage", -1)
        maxsize = self.config.getdefaultint("Account %s" % self.accountname, "maxsize", -1)
        self.messagelist = {}

        imapobj = self.imapserver.acquireconnection()
        try:
            res_type, imapdata = imapobj.select(self.getfullname(), True)
            if imapdata == [None] or imapdata[0] == "0":
                # Empty folder, no need to populate message list
                return
            # By default examine all UIDs in this folder
            msgsToFetch = "1:*"

            if (maxage != -1) | (maxsize != -1):
                search_cond = "("

                if maxage != -1:
                    # find out what the oldest message is that we should look at
                    oldest_struct = time.gmtime(time.time() - (60 * 60 * 24 * maxage))
                    if oldest_struct[0] < 1900:
                        raise OfflineImapError(
                            "maxage setting led to year %d. " "Abort syncing." % oldest_struct[0],
                            OfflineImapError.ERROR.REPO,
                        )
                    search_cond += "SINCE %02d-%s-%d" % (
                        oldest_struct[2],
                        MonthNames[oldest_struct[1]],
                        oldest_struct[0],
                    )

                if maxsize != -1:
                    if maxage != -1:  # There are two conditions, add space
                        search_cond += " "
                    search_cond += "SMALLER %d" % maxsize

                search_cond += ")"

                res_type, res_data = imapobj.search(None, search_cond)
                if res_type != "OK":
                    raise OfflineImapError(
                        "SEARCH in folder [%s]%s failed. "
                        "Search string was '%s'. Server responded '[%s] %s'"
                        % (self.getrepository(), self, search_cond, res_type, res_data),
                        OfflineImapError.ERROR.FOLDER,
                    )

                # Result UIDs are seperated by space, coalesce into ranges
                msgsToFetch = imaputil.uid_sequence(res_data[0].split())
                if not msgsToFetch:
                    return  # No messages to sync

            # Get the flags and UIDs for these. single-quotes prevent
            # imaplib2 from quoting the sequence.
            res_type, response = imapobj.fetch("'%s'" % msgsToFetch, "(FLAGS UID)")
            if res_type != "OK":
                raise OfflineImapError(
                    "FETCHING UIDs in folder [%s]%s failed. "
                    "Server responded '[%s] %s'" % (self.getrepository(), self, res_type, response),
                    OfflineImapError.ERROR.FOLDER,
                )
        finally:
            self.imapserver.releaseconnection(imapobj)

        for messagestr in response:
            # looks like: '1 (FLAGS (\\Seen Old) UID 4807)' or None if no msg
            # Discard initial message number.
            if messagestr == None:
                continue
            messagestr = messagestr.split(" ", 1)[1]
            options = imaputil.flags2hash(messagestr)
            if not options.has_key("UID"):
                self.ui.warn("No UID in message with options %s" % str(options), minor=1)
            else:
                uid = long(options["UID"])
                flags = imaputil.flagsimap2maildir(options["FLAGS"])
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {"uid": uid, "flags": flags, "time": rtime}
Пример #15
0
    def cachemessagelist(self):
        maxage = self.config.getdefaultint("Account %s" % self.accountname,
                                           "maxage", -1)
        maxsize = self.config.getdefaultint("Account %s" % self.accountname,
                                            "maxsize", -1)
        self.messagelist = {}

        imapobj = self.imapserver.acquireconnection()
        try:
            res_type, imapdata = imapobj.select(self.getfullname(), True, True)
            if imapdata == [None] or imapdata[0] == '0':
                # Empty folder, no need to populate message list
                return
            # By default examine all UIDs in this folder
            msgsToFetch = '1:*'

            if (maxage != -1) | (maxsize != -1):
                search_cond = "("

                if (maxage != -1):
                    #find out what the oldest message is that we should look at
                    oldest_struct = time.gmtime(time.time() -
                                                (60 * 60 * 24 * maxage))
                    if oldest_struct[0] < 1900:
                        raise OfflineImapError(
                            "maxage setting led to year %d. "
                            "Abort syncing." % oldest_struct[0],
                            OfflineImapError.ERROR.REPO)
                    search_cond += "SINCE %02d-%s-%d" % (
                        oldest_struct[2], MonthNames[oldest_struct[1]],
                        oldest_struct[0])

                if (maxsize != -1):
                    if (maxage != -1):  # There are two conditions, add space
                        search_cond += " "
                    search_cond += "SMALLER %d" % maxsize

                search_cond += ")"

                res_type, res_data = imapobj.search(None, search_cond)
                if res_type != 'OK':
                    raise OfflineImapError(
                        "SEARCH in folder [%s]%s failed. "
                        "Search string was '%s'. Server responded '[%s] %s'" %
                        (self.getrepository(), self, search_cond, res_type,
                         res_data), OfflineImapError.ERROR.FOLDER)

                # Result UIDs are seperated by space, coalesce into ranges
                msgsToFetch = imaputil.uid_sequence(res_data[0].split())
                if not msgsToFetch:
                    return  # No messages to sync

            # Get the flags and UIDs for these. single-quotes prevent
            # imaplib2 from quoting the sequence.
            res_type, response = imapobj.fetch("'%s'" % msgsToFetch,
                                               '(FLAGS UID)')
            if res_type != 'OK':
                raise OfflineImapError(
                    "FETCHING UIDs in folder [%s]%s failed. "
                    "Server responded '[%s] %s'" %
                    (self.getrepository(), self, res_type, response),
                    OfflineImapError.ERROR.FOLDER)
        finally:
            self.imapserver.releaseconnection(imapobj)

        for messagestr in response:
            # looks like: '1 (FLAGS (\\Seen Old) UID 4807)' or None if no msg
            # Discard initial message number.
            if messagestr == None:
                continue
            messagestr = messagestr.split(' ', 1)[1]
            options = imaputil.flags2hash(messagestr)
            if not 'UID' in options:
                self.ui.warn('No UID in message with options %s' %\
                                          str(options),
                                          minor = 1)
            else:
                uid = long(options['UID'])
                flags = imaputil.flagstring2flagset(options['FLAGS'])
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {
                    'uid': uid,
                    'flags': flags,
                    'time': rtime
                }
Пример #16
0
 def test_07_uid_sequence(self):
     """Test imaputil.uid_sequence()"""
     res = imaputil.uid_sequence([1,2,3,4,5,10,12,13])
     self.assertEqual(res, b'1:5,10,12:13')
Пример #17
0
 def test_07_uid_sequence(self):
     """Test imaputil.uid_sequence()"""
     res = imaputil.uid_sequence([1,2,3,4,5,10,12,13])
     self.assertEqual(res, b'1:5,10,12:13')