Add decodefoldernames option to decode IMAP folder names using UTF-7.

Signed-off-by: Tommie Gannert <tommie@gannert.se>
This commit is contained in:
Tommie Gannert 2015-08-29 13:53:20 +01:00
parent eeb7e89ca6
commit a6e7b6627b
4 changed files with 52 additions and 0 deletions

View File

@ -762,6 +762,20 @@ remoteuser = username
#reference = Mail #reference = Mail
# This option stands in the [Repository RemoteExample] section.
#
# IMAP defines an encoding for non-ASCII ("international") characters. Enable
# this option if you want to decode them to the nowadays ubiquitous UTF-8.
#
# Note that the IMAP 4rev1 specification (RFC 3501) allows both UTF-8 and
# modified UTF-7 folder names.
#
# This option is disabled by default to retain compatibility with older versions
# of offlineimap.
#
#decodefoldernames = no
# This option stands in the [Repository RemoteExample] section. # This option stands in the [Repository RemoteExample] section.
# #
# In between synchronisations, OfflineIMAP can monitor mailboxes for new # In between synchronisations, OfflineIMAP can monitor mailboxes for new

View File

@ -258,6 +258,13 @@ class IMAPFolder(BaseFolder):
def dropmessagelistcache(self): def dropmessagelistcache(self):
self.messagelist = {} self.messagelist = {}
# Interface from BaseFolder
def getvisiblename(self):
vname = super(IMAPFolder, self).getvisiblename()
if self.repository.getdecodefoldernames():
return imaputil.decode_mailbox_name(vname)
return vname
# Interface from BaseFolder # Interface from BaseFolder
def getmessagelist(self): def getmessagelist(self):
return self.messagelist return self.messagelist

View File

@ -25,6 +25,9 @@ from offlineimap.ui import getglobalui
# Message headers that use space as the separator (for label storage) # Message headers that use space as the separator (for label storage)
SPACE_SEPARATED_LABEL_HEADERS = ('X-Label', 'Keywords') SPACE_SEPARATED_LABEL_HEADERS = ('X-Label', 'Keywords')
# Find the modified UTF-7 shifts of an international mailbox name.
MUTF7_SHIFT_RE = re.compile(r'&[^-]*-|\+')
def __debug(*args): def __debug(*args):
msg = [] msg = []
@ -328,3 +331,28 @@ def labels_from_header(header_name, header_value):
return labels return labels
def decode_mailbox_name(name):
"""Decodes a modified UTF-7 mailbox name.
If the string cannot be decoded, it is returned unmodified.
See RFC 3501, sec. 5.1.3.
Arguments:
- name: string, possibly encoded with modified UTF-7
Returns: decoded UTF-8 string.
"""
def demodify(m):
s = m.group()
if s == '+':
return '+-'
return '+' + s[1:-1].replace(',', '/') + '-'
ret = MUTF7_SHIFT_RE.sub(demodify, name)
try:
return ret.decode('utf-7').encode('utf-8')
except UnicodeEncodeError:
return name

View File

@ -261,6 +261,9 @@ class IMAPRepository(BaseRepository):
def getreference(self): def getreference(self):
return self.getconf('reference', '') return self.getconf('reference', '')
def getdecodefoldernames(self):
return self.getconfboolean('decodefoldernames', 0)
def getidlefolders(self): def getidlefolders(self):
localeval = self.localeval localeval = self.localeval
return localeval.eval(self.getconf('idlefolders', '[]')) return localeval.eval(self.getconf('idlefolders', '[]'))