From 1f04bbd8bf14cdc19c4ea2b23ff711d2e89a40fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 17 May 2026 11:22:35 +0200 Subject: [PATCH] folder/IMAP, repository/IMAP: make encoding conditional on utf_8_support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When utf_8_support is False (the default, standard RFC 3501 mode), folder names received from the server are in Modified UTF-7 and must be kept in that encoding internally. When utf_8_support is True, names are decoded to UTF-8 for internal use. Previous code decoded unconditionally in IMAPFolder.__init__, which would corrupt non-ASCII names received as Modified UTF-7 when utf_8_support is False. The inverse problem existed in getfullIMAPname() and the three encode_mailbox_name() call sites in IMAPRepository: they always converted UTF-8 → Modified UTF-7 before sending to the server, which is wrong when utf_8_support is False (names are already in Modified UTF-7 and must not be double-encoded). Fix by applying the same conditional pattern consistently: if account.utf_8_support: name = imaputil.utf8_IMAP(name) # UTF-8 → Modified UTF-7 return imaputil.foldername_to_imapname(name) This is applied in: - IMAPFolder.__init__ (decode on receive) - IMAPFolder.getfullIMAPname (encode before SELECT) - IMAPRepository.getfolders (folderincludes SELECT) - IMAPRepository.deletefolder - IMAPRepository.makefolder_single encode_mailbox_name() (which always assumed UTF-8 input) is removed as it is no longer used anywhere. Based on patch by Etienne Buira --- offlineimap/folder/IMAP.py | 7 +++++-- offlineimap/imaputil.py | 4 ---- offlineimap/repository/IMAP.py | 13 ++++++++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/offlineimap/folder/IMAP.py b/offlineimap/folder/IMAP.py index 67592cc..c34d4c0 100644 --- a/offlineimap/folder/IMAP.py +++ b/offlineimap/folder/IMAP.py @@ -41,7 +41,7 @@ class IMAPFolder(BaseFolder): # a folder object from a locally available utf_8 name) # In any case the given name is first dequoted. name = imaputil.dequote(name) - if decode: + if decode and repository.account.utf_8_support: name = imaputil.IMAP_utf8(name) self.sep = imapserver.delim super(IMAPFolder, self).__init__(name, repository) @@ -82,7 +82,10 @@ class IMAPFolder(BaseFolder): imapobj.select(self.getfullIMAPname(), readonly=True, force=force) def getfullIMAPname(self): - return imaputil.encode_mailbox_name(self.getfullname()) + name = self.getfullname() + if self.repository.account.utf_8_support: + name = imaputil.utf8_IMAP(name) + return imaputil.foldername_to_imapname(name) # Interface from BaseFolder def suggeststhreads(self): diff --git a/offlineimap/imaputil.py b/offlineimap/imaputil.py index 343295b..cde45b1 100644 --- a/offlineimap/imaputil.py +++ b/offlineimap/imaputil.py @@ -449,10 +449,6 @@ def utf7m_search_function(name): codecs.register(utf7m_search_function) -def encode_mailbox_name(mbox_name): - return foldername_to_imapname(utf8_IMAP(mbox_name)) - - def foldername_to_imapname(folder_name): """ This function returns the folder_name ready to send to the diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 62b7370..372f003 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -752,7 +752,10 @@ class IMAPRepository(BaseRepository): try: for foldername in self.folderincludes: try: - imapobj.select(imaputil.encode_mailbox_name(foldername), + imap_name = foldername + if self.account.utf_8_support: + imap_name = imaputil.utf8_IMAP(foldername) + imapobj.select(imaputil.foldername_to_imapname(imap_name), readonly=True) except OfflineImapError as exc: # couldn't select this folderinclude, so ignore folder. @@ -816,7 +819,9 @@ class IMAPRepository(BaseRepository): def deletefolder(self, foldername): """Delete a folder on the IMAP server.""" - foldername = imaputil.encode_mailbox_name(foldername) + if self.account.utf_8_support: + foldername = imaputil.utf8_IMAP(foldername) + foldername = imaputil.foldername_to_imapname(foldername) imapobj = self.imapserver.acquireconnection() try: result = imapobj.delete(foldername) @@ -877,7 +882,9 @@ class IMAPRepository(BaseRepository): return imapobj = self.imapserver.acquireconnection() try: - foldername = imaputil.encode_mailbox_name(foldername) + if self.account.utf_8_support: + foldername = imaputil.utf8_IMAP(foldername) + foldername = imaputil.foldername_to_imapname(foldername) result = imapobj.create(foldername) if result[0] != 'OK':