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
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
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:*'
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:*"
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
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
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
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
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
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
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)
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
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:*'
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}
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 }
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')