Ticket #28 (closed defect: fixed)

Opened 3 months ago

Last modified 2 months ago

Mailbox names with escaped chars them aren't returned correctly

Reported by: menno Owned by:
Priority: critical Milestone: 0.5.2
Version: Keywords:
Cc:

Description

'Test "folder"' is returned by list_folders() as 'Test \'

Escaping needs to be handled correctly.

Change History

  Changed 3 months ago by menno

This problem doesn't occur with all IMAP servers. Gmail uses backslash escaping so the problem occurs there. Dovecot returns folders with double quotes in a literal which doesn't trip IMAPClient up.

Example Gmail response:

* LIST (\HasNoChildren) "/" "Test \"folder\""

The new response parser should handle this cleanly. It should be possible to use a temporary fix in the mean time.

follow-up: ↓ 3   Changed 3 months ago by menno

  • milestone changed from 0.6 to 0.5.2

in reply to: ↑ 2   Changed 3 months ago by eichin

Replying to menno:

Possible workaround (with debugging still in)...

  1. use a named backref qqq in re_folder, so that we can use a greedy match on the foldername regardless of whether or not it has quotes (ie. if and only if there's a start quote, match an end one)
  2. use a named ref for the folder name itself
  3. clean up the extra quoting (in list_folders, though list_sub_folders needs both 2 and 3 as well)

With these changes, all of my gmail foldernames round-trip from list_folders back to select_folder, except for [Gmail] itself; I haven't tested this against any other implementation. extract_folder_from_line probably needs to be a common function called by list_folders and list_sub_folders anyway, instead of a shared regexp.

diff -r 5ac3ccadb5fc imapclient/imapclient.py
--- a/imapclient/imapclient.py	Fri Dec 18 17:17:30 2009 +0000
+++ b/imapclient/imapclient.py	Sun Dec 27 01:50:30 2009 -0500
@@ -63,7 +63,7 @@
     ReadOnlyError = imaplib.IMAP4.readonly
 
     re_sep = re.compile('^\(\("[^"]*" "([^"]+)"\)\)')
-    re_folder = re.compile('\([^)]*\) "[^"]+" "?([^"]+)"?')
+    re_folder = re.compile(r'\([^)]*\) "[^"]+" (?P<qqq>"?)(?P<folder>.+)(?P=qqq)')
     re_status = re.compile(r'^\s*"?(?P<folder>[^"]+)"?\s+'
                            r'\((?P<status_items>.*)\)$')
 
@@ -169,7 +169,10 @@
             else:
                 match = self.re_folder.match(line)
                 if match:
-                    folder_text = match.group(1)
+                    folder_text = match.group("folder")
+                    print "matched folder", repr(folder_text), "in", repr(line)
+                    folder_text = folder_text.replace('\\"', '"')
+                    print "  fixed folder", repr(folder_text)
             if folder_text is not None:
                 folders.append(self._decode_folder_name(folder_text))
         return folders

  Changed 2 months ago by menno

  • status changed from new to closed
  • resolution set to fixed

Fixed in r91 thru r95

Note: See TracTickets for help on using tickets.