Permalink
Browse files

Merge pull request #263 from mlorant/feat-unselect-200

#200 - Add UNSELECT command
  • Loading branch information...
mjs committed Aug 15, 2017
2 parents 46d56b2 + 2bf02ec commit 33a3aa368b99b9deeb6777a5e9ad86c8438fc719
Showing with 43 additions and 0 deletions.
  1. +1 −0 doc/src/releases.rst
  2. +17 −0 imapclient/imapclient.py
  3. +16 −0 imapclient/livetest.py
  4. +9 −0 imapclient/test/test_imapclient.py
View
@@ -23,6 +23,7 @@ Added
- Search now supports nested criteria so that more complex criteria
can be expressed. IMAPClient will add parentheses in the right place.
- PLAIN authentication support (via `plain_login` method)
- `unselect_folder()` method, for servers with the UNSELECT capability (#200)
Changed
-------
View
@@ -53,6 +53,10 @@
if 'ID' not in imaplib.Commands:
imaplib.Commands['ID'] = ('NONAUTH', 'AUTH', 'SELECTED')
# ... and UNSELECT. RFC3691 does not specify the state but there is no
# reason to use the command without AUTH state and a mailbox selected.
if 'UNSELECT' not in imaplib.Commands:
imaplib.Commands['UNSELECT'] = ('AUTH', 'SELECTED')
# System flags
DELETED = br'\Deleted'
@@ -472,6 +476,19 @@ def select_folder(self, folder, readonly=False):
self._command_and_check('select', self._normalise_folder(folder), readonly)
return self._process_select_response(self._imap.untagged_responses)
def unselect_folder(self):
"""Unselect the current folder and release associated resources.
Unlike ``close_folder``, the ``UNSELECT`` command does not expunge
the mailbox, keeping messages with \Deleted flag set for example.
Returns the UNSELECT response string returned by the server.
"""
logger.debug('< UNSELECT')
# IMAP4 class has no `unselect` method so we can't use `_command_and_check` there
_typ, data = self._imap._simple_command("UNSELECT")
return data[0]
def _process_select_response(self, resp):
untagged = _dict_bytes_normaliser(resp)
out = {}
View
@@ -234,6 +234,22 @@ def assertNoneOrTuple(val):
self.assertEqual(ns.other, ns[1])
self.assertEqual(ns.shared, ns[2])
def test_unselect_folder(self):
if not self.client.has_capability('UNSELECT'):
return self.skipTest("Server doesn't support UNSELECT")
resp = self.client.select_folder(self.base_folder)
self.assertEqual(resp[b'EXISTS'], 0)
self.client.search(['ALL'])
self.client.unselect_folder()
# To ensure the folder has been selected, check we can't run .search()
with self.assertRaises(IMAPClient.Error):
self.client.search(['ALL'])
# It should not be possible to unselect a folder if none have been selected yet
with self.assertRaises(IMAPClient.Error):
self.client.unselect_folder()
def test_select_and_close(self):
resp = self.client.select_folder(self.base_folder)
self.assertEqual(resp[b'EXISTS'], 0)
@@ -185,6 +185,15 @@ def test_normal(self):
b'OTHER': [b'blah']
})
def test_unselect(self):
self.client._imap._simple_command.return_value = ('OK', ['Unselect completed.'])
#self.client._imap._untagged_response.return_value = (
# b'OK', [b'("name" "GImap" "vendor" "Google, Inc.")'])
result = self.client.unselect_folder()
self.assertEqual(result, 'Unselect completed.')
self.client._imap._simple_command.assert_called_with('UNSELECT')
class TestAppend(IMAPClientTest):

0 comments on commit 33a3aa3

Please sign in to comment.