Skip to content
This repository was archived by the owner on Dec 3, 2020. It is now read-only.

Commit 04a88c6

Browse files
committed
Tests for bad data in folder_status, more robust handling
In the last day we’ve seen this ValueError 249,915 times. It looks like the response can be more than two parts if A) the folder name contains spaces or B) the server decides to send us other data (or IMAPClient rolls it into the response buffer, not clear yet.) Either way, we should be able to handle these scenarios without crashing. Relevant internal logs: https://nylas.loggly.com/search#terms=%22folder_status%20ValueError%22&from=2016-09-02T01%3A57%3A05.585Z&until=2016-09-03T01%3A57%3A05.585Z&source_group=
1 parent d74efd4 commit 04a88c6

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

imapclient/imapclient.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,11 @@ def folder_status(self, folder, what=None):
635635
what = normalise_text_list(what)
636636
what_ = '(%s)' % (' '.join(what))
637637

638-
data = self._command_and_check('status', self._normalise_folder(folder), what_)
638+
fname = self._normalise_folder(folder)
639+
data = self._command_and_check('status', fname, what_)
639640
response = parse_response(data)
640641
try:
641-
_, status_items = response
642+
status_items = response[-1]
642643
except ValueError:
643644
raise Exception('folder_status ValueError: Input ' + str(response))
644645
return dict(as_pairs(status_items))

imapclient/test/test_imapclient.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,27 @@ def test_blanks(self):
146146
self.assertEqual(folders, [((br'\HasNoChildren',), b'/', 'last')])
147147

148148

149+
class TestFolderStatus(IMAPClientTest):
150+
def test_extra_response(self):
151+
# In production, we've seen folder names containing spaces come back
152+
# like this and be broken into two components in the tuple.
153+
server_response = ["My files (UIDNEXT 24369)"]
154+
mock = Mock(return_value=server_response)
155+
self.client._command_and_check = mock
156+
157+
resp = self.client.folder_status('My files', ['UIDNEXT'])
158+
self.assertEqual(resp, {'UIDNEXT': 24369})
159+
160+
# We've also seen the response contain mailboxes we didn't
161+
# ask for. In all known cases, the desired mailbox is last.
162+
server_response = ["sent (UIDNEXT 24369)\nINBOX (UIDNEXT 24369)"]
163+
mock = Mock(return_value=server_response)
164+
self.client._command_and_check = mock
165+
166+
resp = self.client.folder_status('INBOX', ['UIDNEXT'])
167+
self.assertEqual(resp, {'UIDNEXT': 24369})
168+
169+
149170
class TestSelectFolder(IMAPClientTest):
150171

151172
def test_normal(self):

0 commit comments

Comments
 (0)