aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolaus Schulz <microschulz@web.de>2007-11-07 16:31:49 +0000
committerNikolaus Schulz <microschulz@web.de>2007-11-07 16:31:49 +0000
commitfbb00e08f4a50aca19cd10ea0c64212cbe86dd94 (patch)
treeedd2b9db20c5196fb12daa028a7cba0583cd32ed
parent1e5cb090e73ccf5e336f6a1eec0e854efa7396fd (diff)
downloadarchivemail-fbb00e08f4a50aca19cd10ea0c64212cbe86dd94.tar.gz
archivemail-fbb00e08f4a50aca19cd10ea0c64212cbe86dd94.tar.bz2
archivemail-fbb00e08f4a50aca19cd10ea0c64212cbe86dd94.zip
IMAP: if selecting the mailbox fails, then detect the server's mailbox hierarchy
delimiter, replace slashes in the mailbox name with the delimiter and try again.
-rwxr-xr-xarchivemail.py54
1 files changed, 48 insertions, 6 deletions
diff --git a/archivemail.py b/archivemail.py
index 06ae75d..bc9d997 100755
--- a/archivemail.py
+++ b/archivemail.py
@@ -1349,12 +1349,27 @@ def _archive_imap(mailbox_name, final_archive_name):
result, response = imap_srv.login(imap_username, imap_password)
vprint("selecting imap folder '%s'" % imap_folder)
- if options.dry_run or options.copy_old_mail:
- result, response = imap_srv.select(imap_folder, readonly=True)
- else:
- result, response = imap_srv.select(imap_folder)
- if result != 'OK': unexpected_error("cannot select imap folder; "
- "server says '%s'" % response[0])
+ # Open mailbox read-only?
+ roflag = options.dry_run or options.copy_old_mail
+ # First try the given folder name, if this doesn't work, try to fix it.
+ result, response = imap_srv.select(imap_folder, roflag)
+ if result != 'OK':
+ errmsg = "cannot select imap folder; server says '%s'" % response[0]
+ if not os.path.sep in imap_folder:
+ unexpected_error(errmsg)
+ vprint("Selecting '%s' failed; server says: '%s'. Trying to "
+ "fix mailbox path..." % (imap_folder, response[0]))
+ delim = get_delim(imap_srv)
+ if not delim:
+ unexpected_error(errmsg)
+ imap_folder = imap_folder.replace(os.path.sep, delim)
+ vprint("Selecting '%s'" % imap_folder)
+ result, response = imap_srv.select(imap_folder, roflag)
+ if result == 'OK':
+ vprint("successfully selected imap folder %s" % imap_folder)
+ else:
+ unexpected_error("cannot select imap folder; "
+ "server says '%s'" % response[0])
# response is e.g. ['1016'] for 1016 messages in folder
total_msg_count = int(response[0])
vprint("folder has %d message(s)" % total_msg_count)
@@ -1532,6 +1547,33 @@ def parse_imap_url(url):
unexpected_error("Invalid IMAP connection string")
return username, password, server, folder
+def get_delim(imap_server):
+ """Return the IMAP server's hierarchy delimiter. Assumes there is only one."""
+ # This function will break if the LIST reply doesn't meet our expectations.
+ # Imaplib and IMAP itself are both little beasts, and I do not know how
+ # fragile this function will be in the wild.
+ try:
+ result, response = imap_server.list(pattern='""')
+ except ValueError:
+ # Stolen from offlineimap:
+ # Some buggy IMAP servers do not respond well to LIST "" ""
+ # Work around them.
+ result, response = imap_server.list(pattern='%')
+ if result != 'OK': unexpected_error("Error listing directory; "
+ "server says '%s'" % response[0])
+ # Response should be a list of strings like
+ # '(\\Noselect \\HasChildren) "." "boxname"'
+ # We parse only the first list item and just grab the delimiter.
+ try:
+ i = response[0].index(')')
+ except (ValueError, AttributeError):
+ unexpected_error("get_delim(): cannot parse %s" % str(response[0]))
+ delim = response[0][i+2:i+5].strip('"')
+ vprint("Found mailbox hierarchy delimiter: '%s'" % delim)
+ if delim == "NIL":
+ return None
+ return delim
+
def get_filename(msg):
"""If the given rfc822.Message can be identified with a file (no mbox),
return the filename, otherwise raise AttributeError."""