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)
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 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 }
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}
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())
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)
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)
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}
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 }
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 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
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)
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 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
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())
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 }
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)
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 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)
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}
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)
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
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
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())
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}
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}
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 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'})
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 }
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}
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 }
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}
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 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}