Do not ignore gmail labels if header appears multiple times

There should be just one header storing gmail labels, but due to a bug,
multiple X-Keywords (or equivalent) headers may be found on the local
messages.

Now we, when extracting the labels from a message, we read all label
headers, instead of just the first one.

This has the consequence that some old labels stored locally in a second
X-Keywords (or third...) header, which effectively was rendered
invisible to offlineimap until now, may pop back up again and be pushed
to gmail. No labels will be removed by the changes in this commit,
though.

Signed-off-by: Abdo Roig-Maranges <abdo.roig@gmail.com>
This commit is contained in:
Abdo Roig-Maranges 2014-11-20 14:03:15 +01:00
parent e51ed80ecc
commit fc4c7549d6
3 changed files with 37 additions and 12 deletions

View File

@ -512,8 +512,8 @@ class BaseFolder(object):
def getmessageheader(self, content, name):
"""
Searches for the given header and returns its value.
Header name is case-insensitive.
Searches for the first occurence of the given header and returns
its value. Header name is case-insensitive.
Arguments:
- contents: message itself
@ -535,6 +535,27 @@ class BaseFolder(object):
return None
def getmessageheaderlist(self, content, name):
"""
Searches for the given header and returns a list of values for
that header.
Arguments:
- contents: message itself
- name: name of the header to be searched
Returns: list of header values or emptylist if no such header was found
"""
self.ui.debug('', 'getmessageheaderlist: called to get %s' % name)
eoh = self.__find_eoh(content)
self.ui.debug('', 'getmessageheaderlist: eoh = %d' % eoh)
headers = content[0:eoh]
self.ui.debug('', 'getmessageheaderlist: headers = %s' % repr(headers))
return re.findall('^%s:(.*)$' % name, headers, flags = re.MULTILINE | re.IGNORECASE)
def deletemessageheaders(self, content, header_list):
"""
Deletes headers in the given list from the message content.

View File

@ -189,8 +189,9 @@ class GmailFolder(IMAPFolder):
if not self.synclabels:
return super(GmailFolder, self).savemessage(uid, content, flags, rtime)
labels = imaputil.labels_from_header(self.labelsheader,
self.getmessageheader(content, self.labelsheader))
labels = set()
for hstr in self.getmessageheaderlist(content, self.labelsheader):
labels.update(imaputil.labels_from_header(self.labelsheader, hstr))
ret = super(GmailFolder, self).savemessage(uid, content, flags, rtime)
self.savemessagelabels(ret, labels)

View File

@ -87,9 +87,10 @@ class GmailMaildirFolder(MaildirFolder):
content = file.read()
file.close()
self.messagelist[uid]['labels'] = \
imaputil.labels_from_header(self.labelsheader,
self.getmessageheader(content, self.labelsheader))
self.messagelist[uid]['labels'] = set()
for hstr in self.getmessageheaderlist(content, self.labelsheader):
self.messagelist[uid]['labels'].update(
imaputil.labels_from_header(self.labelsheader, hstr))
self.messagelist[uid]['labels_cached'] = True
return self.messagelist[uid]['labels']
@ -111,8 +112,10 @@ class GmailMaildirFolder(MaildirFolder):
if not self.synclabels:
return super(GmailMaildirFolder, self).savemessage(uid, content, flags, rtime)
labels = imaputil.labels_from_header(self.labelsheader,
self.getmessageheader(content, self.labelsheader))
labels = set()
for hstr in self.getmessageheaderlist(content, self.labelsheader):
labels.update(imaputil.labels_from_header(self.labelsheader, hstr))
ret = super(GmailMaildirFolder, self).savemessage(uid, content, flags, rtime)
# Update the mtime and labels
@ -135,9 +138,9 @@ class GmailMaildirFolder(MaildirFolder):
content = file.read()
file.close()
oldlabels = imaputil.labels_from_header(self.labelsheader,
self.getmessageheader(content, self.labelsheader))
oldlabels = set()
for hstr in self.getmessageheaderlist(content, self.labelsheader):
oldlabels.update(imaputil.labels_from_header(self.labelsheader, hstr))
labels = labels - ignorelabels
ignoredlabels = oldlabels & ignorelabels