This commit is contained in:
Shamil 2025-12-08 06:12:10 +02:00 committed by GitHub
commit 90418f1106
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 27 additions and 13 deletions

View file

@ -166,14 +166,15 @@ class IMAP4:
Errors raise the exception class <instance>.error("<reason>").
IMAP4 server errors raise <instance>.abort("<reason>"),
which is a sub-class of 'error'. Mailbox status changes
from READ-WRITE to READ-ONLY raise the exception class
<instance>.readonly("<reason>"), which is a sub-class of 'abort'.
which is a sub-class of 'error'.
When the server returns a READ-ONLY response code, the is_readonly
attribute is set to True. Applications should check this attribute
to determine mailbox access level.
"error" exceptions imply a program error.
"abort" exceptions imply the connection should be reset, and
the command re-tried.
"readonly" exceptions imply the command should be re-tried.
Note: to use this module, you must read the RFCs pertaining to the
IMAP4 protocol, as the semantics of the arguments to each IMAP4
@ -860,12 +861,8 @@ def select(self, mailbox='INBOX', readonly=False):
self.state = 'AUTH' # Might have been 'SELECTED'
return typ, dat
self.state = 'SELECTED'
if 'READ-ONLY' in self.untagged_responses \
and not readonly:
if __debug__:
if self.debug >= 1:
self._dump_ur(self.untagged_responses)
raise self.readonly('%s is not writable' % mailbox)
if 'READ-ONLY' in self.untagged_responses:
self.is_readonly = True
return typ, self.untagged_responses.get('EXISTS', [None])
@ -1094,9 +1091,8 @@ def _command(self, name, *args):
if typ in self.untagged_responses:
del self.untagged_responses[typ]
if 'READ-ONLY' in self.untagged_responses \
and not self.is_readonly:
raise self.readonly('mailbox status changed to READ-ONLY')
if 'READ-ONLY' in self.untagged_responses:
self.is_readonly = True
tag = self._new_tag()
name = bytes(name, self._encoding)

View file

@ -657,6 +657,21 @@ def test_unselect(self):
self.assertEqual(data[0], b'Returned to authenticated state. (Success)')
self.assertEqual(client.state, 'AUTH')
def test_select_readonly_mailbox(self):
class ReadOnlyHandler(SimpleIMAPHandler):
def cmd_SELECT(self, tag, args):
self.server.is_selected = True
self._send_line(b'* 1 EXISTS')
self._send_line(b'* OK [READ-ONLY] Mailbox is read-only')
self._send_tagged(tag, 'OK', '[READ-ONLY] SELECT completed')
client, _ = self._setup(ReadOnlyHandler)
client.login('user', 'pass')
self.assertFalse(client.is_readonly)
typ, data = client.select('INBOX')
self.assertEqual(typ, 'OK')
self.assertTrue(client.is_readonly)
self.assertEqual(client.state, 'SELECTED')
# property tests
def test_file_property_should_not_be_accessed(self):

View file

@ -0,0 +1,3 @@
Fix :mod:`imaplib` to handle mailboxes with ACL rights like ``lrs`` correctly
by setting ``is_readonly`` flag instead of raising exception. Patched by Shamil
Abdulaev.