Esempio n. 1
0
    def savemessageflags(self, uid, flags):
        """Change a message's flags to `flags`.

        Note that this function does not check against dryrun settings,
        so you need to ensure that it is never called in a
        dryrun mode."""
        imapobj = self.imapserver.acquireconnection()
        try:
            try:
                imapobj.select(self.getfullname())
            except imapobj.readonly:
                self.ui.flagstoreadonly(self, [uid], flags)
                return
            result = imapobj.uid('store', '%d' % uid, 'FLAGS',
                                 imaputil.flagset2flagstring(flags))
            assert result[0] == 'OK', 'Error with store: ' + '. '.join(
                result[1])
        finally:
            self.imapserver.releaseconnection(imapobj)
        result = result[1][0]
        if not result:
            self.messagelist[uid]['flags'] = flags
        else:
            flags = imaputil.flags2hash(imaputil.imapsplit(result)[1])['FLAGS']
            self.messagelist[uid]['flags'] = imaputil.flagstring2flagset(flags)
Esempio n. 2
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
Esempio n. 3
0
    def cachemessagelist(self):
        if not self.synclabels:
            return super(GmailFolder, self).cachemessagelist()

        self.messagelist = {}

        self.ui.collectingdata(None, self)
        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(imapobj)
            if not msgsToFetch:
                return  # No messages to sync

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

        for messagestr in response:
            # looks like: '1 (FLAGS (\\Seen Old) X-GM-LABELS (\\Inbox \\Favorites) 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'])
                self.messagelist[uid] = self.msglist_item_initializer(uid)
                flags = imaputil.flagsimap2maildir(options['FLAGS'])
                m = re.search('\(([^\)]*)\)', options['X-GM-LABELS'])
                if m:
                    labels = set([
                        imaputil.dequote(lb)
                        for lb in imaputil.imapsplit(m.group(1))
                    ])
                else:
                    labels = set()
                labels = labels - self.ignorelabels
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {
                    'uid': uid,
                    'flags': flags,
                    'labels': labels,
                    'time': rtime
                }
Esempio n. 4
0
    def cachemessagelist(self, min_date=None, min_uid=None):
        if not self.synclabels:
            return super(GmailFolder, self).cachemessagelist(
                min_date=min_date, min_uid=min_uid)

        self.dropmessagelistcache()

        self.ui.collectingdata(None, self)
        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(
                imapobj, min_date=min_date, min_uid=min_uid)
            if not msgsToFetch:
                return # No messages to sync

            # Get the flags and UIDs for these. single-quotes prevent
            # imaplib2 from quoting the sequence.
            #
            # NB: msgsToFetch are sequential numbers, not UID's
            res_type, response = imapobj.fetch("'%s'"% msgsToFetch,
              '(FLAGS X-GM-LABELS UID)')
            if res_type != 'OK':
                six.reraise(OfflineImapError,
                            OfflineImapError(
                                "FETCHING UIDs in folder [%s]%s failed. "%
                                (self.getrepository(), self) +
                                "Server responded '[%s] %s'"%
                                (res_type, response),
                                OfflineImapError.ERROR.FOLDER),
                            exc_info()[2])
        finally:
            self.imapserver.releaseconnection(imapobj)

        for messagestr in response:
            # looks like: '1 (FLAGS (\\Seen Old) X-GM-LABELS (\\Inbox \\Favorites) UID 4807)' or None if no msg
            # Discard initial message number.
            if messagestr == None:
                continue
            messagestr = messagestr.split(' ', 1)[1]
            # e.g.: {'X-GM-LABELS': '("Webserver (RW.net)" "\\Inbox" GInbox)', 'FLAGS': '(\\Seen)', 'UID': '275440'}
            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 = int(options['UID'])
                self.messagelist[uid] = self.msglist_item_initializer(uid)
                flags = imaputil.flagsimap2maildir(options['FLAGS'])
                # e.g.: '("Webserver (RW.net)" "\\Inbox" GInbox)'
                m = re.search('^[(](.*)[)]', options['X-GM-LABELS'])
                if m:
                    labels = set([imaputil.dequote(lb) for lb in imaputil.imapsplit(m.group(1))])
                else:
                    labels = set()
                labels = labels - self.ignorelabels
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {'uid': uid, 'flags': flags, 'labels': labels, 'time': rtime}
Esempio n. 5
0
    def cachemessagelist(self, min_date=None, min_uid=None):
        self.ui.loadmessagelist(self.repository, self)
        self.dropmessagelistcache()

        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(imapobj,
                                              min_date=min_date,
                                              min_uid=min_uid)
            if not msgsToFetch:
                return  # No messages to sync.

            # Get the flags and UIDs for these. single-quotes prevent
            # imaplib2 from quoting the sequence.
            fetch_msg = "%s" % msgsToFetch
            self.ui.debug(
                'imap', "calling imaplib2 fetch command: %s %s" %
                (fetch_msg, '(FLAGS UID INTERNALDATE)'))
            res_type, response = imapobj.fetch(fetch_msg,
                                               '(FLAGS UID INTERNALDATE)')
            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 is None:
                continue
            messagestr = messagestr.decode('utf-8').split(' ', 1)[1]
            options = imaputil.flags2hash(messagestr)
            if 'UID' not in options:
                self.ui.warn('No UID in message with options %s' %
                             str(options),
                             minor=1)
            else:
                uid = int(options['UID'])
                self.messagelist[uid] = self.msglist_item_initializer(uid)
                flags = imaputil.flagsimap2maildir(options['FLAGS'])
                keywords = imaputil.flagsimap2keywords(options['FLAGS'])
                rtime = imaplibutil.Internaldate2epoch(
                    messagestr.encode('utf-8'))
                self.messagelist[uid] = {
                    'uid': uid,
                    'flags': flags,
                    'time': rtime,
                    'keywords': keywords
                }
        self.ui.messagelistloaded(self.repository, self,
                                  self.getmessagecount())
Esempio n. 6
0
    def processmessagesflags(self, operation, uidlist, flags):
        # XXX: the imapobj.myrights(...) calls dies with an error
        # report from Gmail server stating that IMAP command
        # 'MYRIGHTS' is not implemented.  So, this
        # `processmessagesflags` is just a copy from `IMAPFolder`,
        # with the references to `imapobj.myrights()` deleted This
        # shouldn't hurt, however, Gmail users always have full
        # control over all their mailboxes (apparently).
        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:
            imapobj.select(self.getfullname())
            r = imapobj.uid('store',
                            imaputil.listjoin(uidlist),
                            operation + 'FLAGS',
                            imaputil.flagsmaildir2imap(flags))
            assert r[0] == 'OK', 'Error with store: ' + '. '.join(r[1])
            r = r[1]
        finally:
            self.imapserver.releaseconnection(imapobj)

        needupdate = copy(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
            flags = attributehash['FLAGS']
            uid = long(attributehash['UID'])
            self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flags)
            try:
                needupdate.remove(uid)
            except ValueError:          # Let it slide if it's not in the list
                pass
        for uid in needupdate:
            if operation == '+':
                for flag in flags:
                    if not flag in self.messagelist[uid]['flags']:
                        self.messagelist[uid]['flags'].append(flag)
                    self.messagelist[uid]['flags'].sort()
            elif operation == '-':
                for flag in flags:
                    if flag in self.messagelist[uid]['flags']:
                        self.messagelist[uid]['flags'].remove(flag)
Esempio n. 7
0
    def processmessagesflags(self, operation, uidlist, flags):
        # XXX: the imapobj.myrights(...) calls dies with an error
        # report from Gmail server stating that IMAP command
        # 'MYRIGHTS' is not implemented.  So, this
        # `processmessagesflags` is just a copy from `IMAPFolder`,
        # with the references to `imapobj.myrights()` deleted This
        # shouldn't hurt, however, Gmail users always have full
        # control over all their mailboxes (apparently).
        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:
            imapobj.select(self.getfullname())
            r = imapobj.uid('store',
                            imaputil.listjoin(uidlist),
                            operation + 'FLAGS',
                            imaputil.flagsmaildir2imap(flags))
            assert r[0] == 'OK', 'Error with store: ' + '. '.join(r[1])
            r = r[1]
        finally:
            self.imapserver.releaseconnection(imapobj)

        needupdate = copy(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
            flags = attributehash['FLAGS']
            uid = long(attributehash['UID'])
            self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flags)
            try:
                needupdate.remove(uid)
            except ValueError:          # Let it slide if it's not in the list
                pass
        for uid in needupdate:
            if operation == '+':
                for flag in flags:
                    if not flag in self.messagelist[uid]['flags']:
                        self.messagelist[uid]['flags'].append(flag)
                    self.messagelist[uid]['flags'].sort()
            elif operation == '-':
                for flag in flags:
                    if flag in self.messagelist[uid]['flags']:
                        self.messagelist[uid]['flags'].remove(flag)
Esempio n. 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:
             UIBase.getglobalui().flagstoreadonly(self, uidlist, flags)
             return
         r = imapobj.uid('store',
                         imaputil.listjoin(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 = copy(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
         lflags = attributehash['FLAGS']
         uid = long(attributehash['UID'])
         self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(lflags)
         try:
             needupdate.remove(uid)
         except ValueError:          # Let it slide if it's not in the list
             pass
     for uid in needupdate:
         if operation == '+':
             for flag in flags:
                 if not flag in self.messagelist[uid]['flags']:
                     self.messagelist[uid]['flags'].append(flag)
                 self.messagelist[uid]['flags'].sort()
         elif operation == '-':
             for flag in flags:
                 if flag in self.messagelist[uid]['flags']:
                     self.messagelist[uid]['flags'].remove(flag)
Esempio n. 9
0
    def cachemessagelist(self):
        if not self.synclabels:
            return super(GmailFolder, self).cachemessagelist()

        self.ui.collectingdata(None, self)
        self.messagelist = {}

        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(imapobj)
            if not msgsToFetch:
                return # No messages to sync

            # Get the flags and UIDs for these. single-quotes prevent
            # imaplib2 from quoting the sequence.
            # Note: msgsToFetch are sequential numbers, not UID's
            res_type, response = imapobj.fetch("'%s'" % msgsToFetch,
                                               '(FLAGS X-GM-LABELS 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.flagsimap2maildir(options['FLAGS'])
                m = re.search('\(([^\)]*)\)', options['X-GM-LABELS'])
                if m:
                    labels = set([imaputil.dequote(lb) for lb in imaputil.imapsplit(m.group(1))])
                else:
                    labels = set()
                labels = labels - self.ignorelabels
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {'uid': uid, 'flags': flags, 'labels': labels, 'time': rtime}
Esempio n. 10
0
    def cachemessagelist(self):
        if not self.synclabels:
            return super(GmailFolder, self).cachemessagelist()

        self.ui.collectingdata(None, self)
        self.messagelist = {}
        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(imapobj)
            if not msgsToFetch:
                return  # No messages to sync

            # Get the flags and UIDs for these. single-quotes prevent
            # imaplib2 from quoting the sequence.
            data = self._fetch_from_imap(imapobj, "'%s'" % msgsToFetch,
                                         '(FLAGS X-GM-LABELS UID)')
        finally:
            self.imapserver.releaseconnection(imapobj)

        for messagestr in data:
            # 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.flagsimap2maildir(options['FLAGS'])
                m = re.search('\(([^\)]*)\)', options['X-GM-LABELS'])
                if m:
                    labels = set([
                        imaputil.dequote(lb)
                        for lb in imaputil.imapsplit(m.group(1))
                    ])
                else:
                    labels = set()
                labels = labels - self.ignorelabels
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {
                    'uid': uid,
                    'flags': flags,
                    'labels': labels,
                    'time': rtime
                }
Esempio n. 11
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
Esempio n. 12
0
    def quickchanged(self, statusfolder):
        # An IMAP folder has definitely changed if the number of
        # messages or the UID of the last message have changed.  Otherwise
        # only flag changes could have occurred.
        imapobj = self.imapserver.acquireconnection()
        try:
            # Primes untagged_responses
            imaptype, imapdata = imapobj.select(self.getfullname(),
                                                readonly=1,
                                                force=1)
            # 1. Some mail servers do not return an EXISTS response
            # if the folder is empty.  2. ZIMBRA servers can return
            # multiple EXISTS replies in the form 500, 1000, 1500,
            # 1623 so check for potentially multiple replies.
            if imapdata == [None]:
                return True
            maxmsgid = 0
            for msgid in imapdata:
                maxmsgid = max(long(msgid), maxmsgid)

            # Different number of messages than last time?
            if maxmsgid != len(statusfolder.getmessagelist()):
                return True

            if maxmsgid < 1:
                # No messages; return
                return False

            # Now, get the UID for the last message.
            response = imapobj.fetch('%d' % maxmsgid, '(UID)')[1]
        finally:
            self.imapserver.releaseconnection(imapobj)

        # Discard the message number.
        messagestr = response[0].split(' ', 1)[1]
        options = imaputil.flags2hash(messagestr)
        if not options.has_key('UID'):
            return True
        uid = long(options['UID'])
        saveduids = statusfolder.getmessagelist().keys()
        saveduids.sort()
        if uid != saveduids[-1]:
            return True

        return False
Esempio n. 13
0
 def savemessageflags(self, uid, flags):
     imapobj = self.imapserver.acquireconnection()
     try:
         try:
             imapobj.select(self.getfullname())
         except imapobj.readonly:
             self.ui.flagstoreadonly(self, [uid], flags)
             return
         result = imapobj.uid("store", "%d" % uid, "FLAGS", imaputil.flagsmaildir2imap(flags))
         assert result[0] == "OK", "Error with store: " + ". ".join(result[1])
     finally:
         self.imapserver.releaseconnection(imapobj)
     result = result[1][0]
     if not result:
         self.messagelist[uid]["flags"] = flags
     else:
         flags = imaputil.flags2hash(imaputil.imapsplit(result)[1])["FLAGS"]
         self.messagelist[uid]["flags"] = imaputil.flagsimap2maildir(flags)
Esempio n. 14
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
Esempio n. 15
0
    def quickchanged(self, statusfolder):
        # An IMAP folder has definitely changed if the number of
        # messages or the UID of the last message have changed.  Otherwise
        # only flag changes could have occurred.
        imapobj = self.imapserver.acquireconnection()
        try:
            # Primes untagged_responses
            imapobj.select(self.getfullname(), readonly = 1, force = 1)
            try:
                # 1. Some mail servers do not return an EXISTS response
                # if the folder is empty.  2. ZIMBRA servers can return
                # multiple EXISTS replies in the form 500, 1000, 1500,
                # 1623 so check for potentially multiple replies.
                maxmsgid = 0
                for msgid in imapobj.untagged_responses['EXISTS']:
                    maxmsgid = max(long(msgid), maxmsgid)
            except KeyError:
                return True

            # Different number of messages than last time?
            if maxmsgid != len(statusfolder.getmessagelist()):
                return True

            if maxmsgid < 1:
                # No messages; return
                return False

            # Now, get the UID for the last message.
            response = imapobj.fetch('%d' % maxmsgid, '(UID)')[1]
        finally:
            self.imapserver.releaseconnection(imapobj)

        # Discard the message number.
        messagestr = string.split(response[0], maxsplit = 1)[1]
        options = imaputil.flags2hash(messagestr)
        if not options.has_key('UID'):
            return True
        uid = long(options['UID'])
        saveduids = statusfolder.getmessagelist().keys()
        saveduids.sort()
        if uid != saveduids[-1]:
            return True

        return False
Esempio n. 16
0
    def cachemessagelist(self, min_date=None, min_uid=None):
        self.ui.loadmessagelist(self.repository, self)
        self.dropmessagelistcache()

        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(
                imapobj, min_date=min_date, min_uid=min_uid)
            if not msgsToFetch:
                return # No messages to sync.

            # Get the flags and UIDs for these. single-quotes prevent
            # imaplib2 from quoting the sequence.
            fetch_msg = "'%s'"% msgsToFetch
            self.ui.debug('imap', "calling imaplib2 fetch command: %s %s"%
                (fetch_msg, '(FLAGS UID INTERNALDATE)'))
            res_type, response = imapobj.fetch(
                fetch_msg, '(FLAGS UID INTERNALDATE)')
            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 is None:
                continue
            messagestr = messagestr.split(' ', 1)[1]
            options = imaputil.flags2hash(messagestr)
            if 'UID' not in options:
                self.ui.warn('No UID in message with options %s'%
                    str(options), minor=1)
            else:
                uid = int(options['UID'])
                self.messagelist[uid] = self.msglist_item_initializer(uid)
                flags = imaputil.flagsimap2maildir(options['FLAGS'])
                keywords = imaputil.flagsimap2keywords(options['FLAGS'])
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {'uid': uid, 'flags': flags, 'time': rtime,
                    'keywords': keywords}
        self.ui.messagelistloaded(self.repository, self, self.getmessagecount())
Esempio n. 17
0
    def cachemessagelist(self):
        self.messagelist = {}

        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(imapobj)
            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'])
                self.messagelist[uid] = self.msglist_item_initializer(uid)
                flags = imaputil.flagsimap2maildir(options['FLAGS'])
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {
                    'uid': uid,
                    'flags': flags,
                    'time': rtime
                }
Esempio n. 18
0
 def savemessageflags(self, uid, flags):
     imapobj = self.imapserver.acquireconnection()
     try:
         try:
             imapobj.select(self.getfullname())
         except imapobj.readonly:
             self.ui.flagstoreadonly(self, [uid], flags)
             return
         result = imapobj.uid('store', '%d' % uid, 'FLAGS',
                              imaputil.flagsmaildir2imap(flags))
         assert result[0] == 'OK', 'Error with store: ' + '. '.join(r[1])
     finally:
         self.imapserver.releaseconnection(imapobj)
     result = result[1][0]
     if not result:
         self.messagelist[uid]['flags'] = flags
     else:
         flags = imaputil.flags2hash(imaputil.imapsplit(result)[1])['FLAGS']
         self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flags)
Esempio n. 19
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
Esempio n. 20
0
 def savemessageflags(self, uid, flags):
     imapobj = self.imapserver.acquireconnection()
     try:
         try:
             imapobj.select(self.getfullname())
         except imapobj.readonly:
             self.ui.flagstoreadonly(self, [uid], flags)
             return
         result = imapobj.uid('store', '%d' % uid, 'FLAGS',
                              imaputil.flagsmaildir2imap(flags))
         assert result[0] == 'OK', 'Error with store: ' + '. '.join(result[1])
     finally:
         self.imapserver.releaseconnection(imapobj)
     result = result[1][0]
     if not result:
         self.messagelist[uid]['flags'] = flags
     else:
         flags = imaputil.flags2hash(imaputil.imapsplit(result)[1])['FLAGS']
         self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flags)
Esempio n. 21
0
    def cachemessagelist(self):
        if not self.synclabels:
            return super(GmailFolder, self).cachemessagelist()

        self.ui.collectingdata(None, self)
        self.messagelist = {}
        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(imapobj)
            if not msgsToFetch:
                return # No messages to sync

            # Get the flags and UIDs for these. single-quotes prevent
            # imaplib2 from quoting the sequence.
            data = self._fetch_from_imap(imapobj, "'%s'" % msgsToFetch,
                                             '(FLAGS X-GM-LABELS UID)')
        finally:
            self.imapserver.releaseconnection(imapobj)

        for messagestr in data:
            # 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.flagsimap2maildir(options['FLAGS'])
                m = re.search('\(([^\)]*)\)', options['X-GM-LABELS'])
                if m:
                    labels = set([imaputil.dequote(lb) for lb in imaputil.imapsplit(m.group(1))])
                else:
                    labels = set()
                labels = labels - self.ignorelabels
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {'uid': uid, 'flags': flags, 'labels': labels, 'time': rtime}
Esempio n. 22
0
    def savemessageflags(self, uid, flags):
        """Change a message's flags to `flags`.

        Note that this function does not check against dryrun settings,
        so you need to ensure that it is never called in a
        dryrun mode."""
        imapobj = self.imapserver.acquireconnection()
        try:
            result = self._store_to_imap(imapobj, str(uid), 'FLAGS',
                imaputil.flagsmaildir2imap(flags))
        except imapobj.readonly:
            self.ui.flagstoreadonly(self, [uid], flags)
            return
        finally:
            self.imapserver.releaseconnection(imapobj)

        if not result:
            self.messagelist[uid]['flags'] = flags
        else:
            flags = imaputil.flags2hash(imaputil.imapsplit(result)[1])['FLAGS']
            self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flags)
Esempio n. 23
0
    def savemessageflags(self, uid, flags):
        """Change a message's flags to `flags`.

        Note that this function does not check against dryrun settings,
        so you need to ensure that it is never called in a
        dryrun mode."""
        imapobj = self.imapserver.acquireconnection()
        try:
            result = self._store_to_imap(imapobj, str(uid), 'FLAGS',
                                         imaputil.flagsmaildir2imap(flags))
        except imapobj.readonly:
            self.ui.flagstoreadonly(self, [uid], flags)
            return
        finally:
            self.imapserver.releaseconnection(imapobj)

        if not result:
            self.messagelist[uid]['flags'] = flags
        else:
            flags = imaputil.flags2hash(imaputil.imapsplit(result)[1])['FLAGS']
            self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flags)
Esempio n. 24
0
    def quickchanged(self, statusfolder):
        # An IMAP folder has definitely changed if the number of
        # messages or the UID of the last message have changed.  Otherwise
        # only flag changes could have occurred.
        imapobj = self.imapserver.acquireconnection()
        try:
            # Primes untagged_responses
            imapobj.select(self.getfullname(), readonly=1, force=1)
            try:
                # Some mail servers do not return an EXISTS response if
                # the folder is empty.
                maxmsgid = long(imapobj.untagged_responses["EXISTS"][0])
            except KeyError:
                return True

            # Different number of messages than last time?
            if maxmsgid != len(statusfolder.getmessagelist()):
                return True

            if maxmsgid < 1:
                # No messages; return
                return False

            # Now, get the UID for the last message.
            response = imapobj.fetch("%d" % maxmsgid, "(UID)")[1]
        finally:
            self.imapserver.releaseconnection(imapobj)

        # Discard the message number.
        messagestr = string.split(response[0], maxsplit=1)[1]
        options = imaputil.flags2hash(messagestr)
        if not options.has_key("UID"):
            return True
        uid = long(options["UID"])
        saveduids = statusfolder.getmessagelist().keys()
        saveduids.sort()
        if uid != saveduids[-1]:
            return True

        return False
Esempio n. 25
0
    def quickchanged(self, statusfolder):
        # An IMAP folder has definitely changed if the number of
        # messages or the UID of the last message have changed.  Otherwise
        # only flag changes could have occurred.
        imapobj = self.imapserver.acquireconnection()
        try:
            # Primes untagged_responses
            imapobj.select(self.getfullname(), readonly = 1, force = 1)
            try:
                # Some mail servers do not return an EXISTS response if
                # the folder is empty.
                maxmsgid = long(imapobj.untagged_responses['EXISTS'][0])
            except KeyError:
                return True

            # Different number of messages than last time?
            if maxmsgid != len(statusfolder.getmessagelist()):
                return True

            if maxmsgid < 1:
                # No messages; return
                return False

            # Now, get the UID for the last message.
            response = imapobj.fetch('%d' % maxmsgid, '(UID)')[1]
        finally:
            self.imapserver.releaseconnection(imapobj)

        # Discard the message number.
        messagestr = string.split(response[0], maxsplit = 1)[1]
        options = imaputil.flags2hash(messagestr)
        if not options.has_key('UID'):
            return True
        uid = long(options['UID'])
        saveduids = statusfolder.getmessagelist().keys()
        saveduids.sort()
        if uid != saveduids[-1]:
            return True

        return False
Esempio n. 26
0
    def cachemessagelist(self, min_date=None, min_uid=None):
        self.ui.loadmessagelist(self.repository, self)
        self.messagelist = {}

        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(imapobj, min_date=min_date, min_uid=min_uid)
            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 INTERNALDATE)")
            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"])
                self.messagelist[uid] = self.msglist_item_initializer(uid)
                flags = imaputil.flagsimap2maildir(options["FLAGS"])
                keywords = imaputil.flagsimap2keywords(options["FLAGS"])
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {"uid": uid, "flags": flags, "time": rtime, "keywords": keywords}
        self.ui.messagelistloaded(self.repository, self, self.getmessagecount())
Esempio n. 27
0
    def cachemessagelist(self):
        self.messagelist = {}

        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(imapobj)
            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'])
                self.messagelist[uid] = self.msglist_item_initializer(uid)
                flags = imaputil.flagsimap2maildir(options['FLAGS'])
                rtime = imaplibutil.Internaldate2epoch(messagestr)
                self.messagelist[uid] = {'uid': uid, 'flags': flags, 'time': rtime}
Esempio n. 28
0
    def cachemessagelist(self):
        imapobj = self.imapserver.acquireconnection()
        self.messagelist = {}

        try:
            # Primes untagged_responses
            imapobj.select(self.getfullname(), readonly = 1, force = 1)
            try:
                # Some mail servers do not return an EXISTS response if
                # the folder is empty.
                maxmsgid = long(imapobj.untagged_responses['EXISTS'][0])
            except KeyError:
                return
            if maxmsgid < 1:
                # No messages; return
                return

            # Now, get the flags and UIDs for these.
            # We could conceivably get rid of maxmsgid and just say
            # '1:*' here.
            response = imapobj.fetch('1:%d' % maxmsgid, '(FLAGS UID INTERNALDATE)')[1]
        finally:
            self.imapserver.releaseconnection(imapobj)
        for messagestr in response:
            # Discard the message number.
            messagestr = string.split(messagestr, maxsplit = 1)[1]
            options = imaputil.flags2hash(messagestr)
            if not options.has_key('UID'):
                UIBase.getglobalui().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}
Esempio n. 29
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
Esempio n. 30
0
    def savemessageflags(self, uid, flags):
        """Change a message's flags to `flags`.

        Note that this function does not check against dryrun settings,
        so you need to ensure that it is never called in a
        dryrun mode."""
        imapobj = self.imapserver.acquireconnection()
        try:
            try:
                imapobj.select(self.getfullname())
            except imapobj.readonly:
                self.ui.flagstoreadonly(self, [uid], flags)
                return
            result = imapobj.uid('store', '%d' % uid, 'FLAGS',
                                 imaputil.flagsmaildir2imap(flags))
            assert result[0] == 'OK', 'Error with store: ' + '. '.join(result[1])
        finally:
            self.imapserver.releaseconnection(imapobj)
        result = result[1][0]
        if not result:
            self.messagelist[uid]['flags'] = flags
        else:
            flags = imaputil.flags2hash(imaputil.imapsplit(result)[1])['FLAGS']
            self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flags)
 def test_04_flags2hash(self):
     """Test imaputil.flags2hash()"""
     res = imaputil.flags2hash(b'(FLAGS (\\Seen Old) UID 4807)')
     self.assertEqual(res, {b'FLAGS': b'(\\Seen Old)', b'UID': b'4807'})
Esempio n. 32
0
    def cachemessagelist(self, min_date=None, min_uid=None):
        if not self.synclabels:
            return super(GmailFolder, self).cachemessagelist(min_date=min_date,
                                                             min_uid=min_uid)

        self.dropmessagelistcache()

        self.ui.collectingdata(None, self)
        imapobj = self.imapserver.acquireconnection()
        try:
            msgsToFetch = self._msgs_to_fetch(imapobj,
                                              min_date=min_date,
                                              min_uid=min_uid)
            if not msgsToFetch:
                return  # No messages to sync

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

        for messagestr in response:
            # looks like: '1 (FLAGS (\\Seen Old) X-GM-LABELS (\\Inbox \\Favorites) UID 4807)' or None if no msg
            # Discard initial message number.
            if messagestr is None:
                continue
            messagestr = messagestr.decode('utf-8').split(' ', 1)[1]
            # e.g.: {'X-GM-LABELS': '("Webserver (RW.net)" "\\Inbox" GInbox)', 'FLAGS': '(\\Seen)', 'UID': '275440'}
            options = imaputil.flags2hash(messagestr)
            if 'UID' not in options:
                self.ui.warn('No UID in message with options %s' %
                             str(options),
                             minor=1)
            else:
                uid = int(options['UID'])
                self.messagelist[uid] = self.msglist_item_initializer(uid)
                flags = imaputil.flagsimap2maildir(options['FLAGS'])
                # e.g.: '("Webserver (RW.net)" "\\Inbox" GInbox)'
                m = re.search('^[(](.*)[)]', options['X-GM-LABELS'])
                if m:
                    labels = set([
                        imaputil.dequote(lb)
                        for lb in imaputil.imapsplit(m.group(1))
                    ])
                else:
                    labels = set()
                labels = labels - self.ignorelabels
                rtime = imaplibutil.Internaldate2epoch(messagestr.encode())
                self.messagelist[uid] = {
                    'uid': uid,
                    'flags': flags,
                    'labels': labels,
                    'time': rtime
                }
Esempio n. 33
0
    def cachemessagelist(self):
        imapobj = self.imapserver.acquireconnection()
        self.messagelist = {}

        try:
            # Primes untagged_responses
            imaptype, imapdata = imapobj.select(self.getfullname(), readonly=1, force=1)

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

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

                    if maxage != -1:
                        # find out what the oldest message is that we should look at
                        oldest_time_struct = time.gmtime(time.time() - (60 * 60 * 24 * maxage))

                        # format this manually - otherwise locales could cause problems
                        monthnames_standard = [
                            "Jan",
                            "Feb",
                            "Mar",
                            "Apr",
                            "May",
                            "Jun",
                            "Jul",
                            "Aug",
                            "Sep",
                            "Oct",
                            "Nov",
                            "Dec",
                        ]

                        our_monthname = monthnames_standard[oldest_time_struct[1] - 1]
                        daystr = "%(day)02d" % {"day": oldest_time_struct[2]}
                        date_search_str = "SINCE " + daystr + "-" + our_monthname + "-" + str(oldest_time_struct[0])

                        search_condition += date_search_str

                    if maxsize != -1:
                        if maxage != -1:  # There are two conditions - add a space
                            search_condition += " "

                        search_condition += "SMALLER " + self.config.getdefault(
                            "Account " + self.accountname, "maxsize", -1
                        )

                    search_condition += ")"
                    searchresult = imapobj.search(None, search_condition)

                    # result would come back seperated by space - to change into a fetch
                    # statement we need to change space to comma
                    messagesToFetch = searchresult[1][0].replace(" ", ",")
                except KeyError:
                    return
                if len(messagesToFetch) < 1:
                    # No messages; return
                    return
            else:
                # 1. Some mail servers do not return an EXISTS response
                # if the folder is empty.  2. ZIMBRA servers can return
                # multiple EXISTS replies in the form 500, 1000, 1500,
                # 1623 so check for potentially multiple replies.
                if imapdata == [None]:
                    return

                maxmsgid = 0
                for msgid in imapdata:
                    maxmsgid = max(long(msgid), maxmsgid)
                if maxmsgid < 1:
                    # no messages; return
                    return
                messagesToFetch = "1:%d" % maxmsgid

            # Now, get the flags and UIDs for these.
            # We could conceivably get rid of maxmsgid and just say
            # '1:*' here.
            response = imapobj.fetch(messagesToFetch, "(FLAGS UID)")[1]
        finally:
            self.imapserver.releaseconnection(imapobj)
        for messagestr in response:
            # Discard the message number.
            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}
Esempio n. 34
0
    def cachemessagelist(self):
        imapobj = self.imapserver.acquireconnection()
        self.messagelist = {}

        try:
            # Primes untagged_responses
            imaptype, imapdata = imapobj.select(self.getfullname(),
                                                readonly=1,
                                                force=1)

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

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

                    if (maxage != -1):
                        #find out what the oldest message is that we should look at
                        oldest_time_struct = time.gmtime(time.time() -
                                                         (60 * 60 * 24 *
                                                          maxage))

                        #format this manually - otherwise locales could cause problems
                        monthnames_standard = ["Jan", "Feb", "Mar", "Apr", "May", \
                            "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"]

                        our_monthname = monthnames_standard[
                            oldest_time_struct[1] - 1]
                        daystr = "%(day)02d" % {'day': oldest_time_struct[2]}
                        date_search_str = "SINCE " + daystr + "-" + our_monthname \
                            + "-" + str(oldest_time_struct[0])

                        search_condition += date_search_str

                    if (maxsize != -1):
                        if (maxage !=
                                1):  #There are two conditions - add a space
                            search_condition += " "

                        search_condition += "SMALLER " + self.config.getdefault(
                            "Account " + self.accountname, "maxsize", -1)

                    search_condition += ")"
                    searchresult = imapobj.search(None, search_condition)

                    #result would come back seperated by space - to change into a fetch
                    #statement we need to change space to comma
                    messagesToFetch = searchresult[1][0].replace(" ", ",")
                except KeyError:
                    return
                if len(messagesToFetch) < 1:
                    # No messages; return
                    return
            else:
                # 1. Some mail servers do not return an EXISTS response
                # if the folder is empty.  2. ZIMBRA servers can return
                # multiple EXISTS replies in the form 500, 1000, 1500,
                # 1623 so check for potentially multiple replies.
                if imapdata == [None]:
                    return

                maxmsgid = 0
                for msgid in imapdata:
                    maxmsgid = max(long(msgid), maxmsgid)

                maxmsgid = long(imapdata[0])
                messagesToFetch = '1:%d' % maxmsgid

                if maxmsgid < 1:
                    #no messages; return
                    return
            # Now, get the flags and UIDs for these.
            # We could conceivably get rid of maxmsgid and just say
            # '1:*' here.
            response = imapobj.fetch(messagesToFetch, '(FLAGS UID)')[1]
        finally:
            self.imapserver.releaseconnection(imapobj)
        for messagestr in response:
            # Discard the message number.
            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
                }
Esempio n. 35
0
    def cachemessagelist(self):
        imapobj = self.imapserver.acquireconnection()
        self.messagelist = {}

        try:
            # Primes untagged_responses
            imapobj.select(self.getfullname(), readonly = 1, force = 1)

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

            if (maxage != -1) | (maxsize != -1):
                try:
                    search_condition = "(";

                    if(maxage != -1):
                        #find out what the oldest message is that we should look at
                        oldest_time_struct = time.gmtime(time.time() - (60*60*24*maxage))

                        #format this manually - otherwise locales could cause problems
                        monthnames_standard = ["Jan", "Feb", "Mar", "Apr", "May", \
                            "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"]

                        our_monthname = monthnames_standard[oldest_time_struct[1]-1]
                        daystr = "%(day)02d" % {'day' : oldest_time_struct[2]}
                        date_search_str = "SINCE " + daystr + "-" + our_monthname \
                            + "-" + str(oldest_time_struct[0])

                        search_condition += date_search_str

                    if(maxsize != -1):
                        if(maxage != 1): #There are two conditions - add a space
                            search_condition += " "

                        search_condition += "SMALLER " + self.config.getdefault("Account " + self.accountname, "maxsize", -1)

                    search_condition += ")"
                    searchresult = imapobj.search(None, search_condition)

                    #result would come back seperated by space - to change into a fetch
                    #statement we need to change space to comma
                    messagesToFetch = searchresult[1][0].replace(" ", ",")
                except KeyError:
                    return
                if len(messagesToFetch) < 1:
                    # No messages; return
                    return
            else:
                try:
                    # Some mail servers do not return an EXISTS response if
                    # the folder is empty.

                    maxmsgid = long(imapobj.untagged_responses['EXISTS'][0])
                    messagesToFetch = '1:%d' % maxmsgid;
                except KeyError:
                    return
                if maxmsgid < 1:
                    #no messages; return
                    return
            # Now, get the flags and UIDs for these.
            # We could conceivably get rid of maxmsgid and just say
            # '1:*' here.
            response = imapobj.fetch(messagesToFetch, '(FLAGS UID)')[1]
        finally:
            self.imapserver.releaseconnection(imapobj)
        for messagestr in response:
            # Discard the message number.
            messagestr = string.split(messagestr, maxsplit = 1)[1]
            options = imaputil.flags2hash(messagestr)
            if not options.has_key('UID'):
                UIBase.getglobalui().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}
Esempio n. 36
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
                }
Esempio n. 37
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}
Esempio n. 38
0
 def test_04_flags2hash(self):
     """Test imaputil.flags2hash()"""
     res = imaputil.flags2hash(b'(FLAGS (\\Seen Old) UID 4807)')
     self.assertEqual(res, {b'FLAGS': b'(\\Seen Old)', b'UID': b'4807'})