fix: bound mark_seen's UID STORE with the configured timeout
aioimaplib forwards a timeout into IMAP4.uid(...) but drops it specifically for the STORE command (protocol.uid() calls self.store(*criteria, by_uid=True) without passing timeout through, so the Command never arms its internal timer). Combined with IMAP4_SSL's default conn_lost_cb=None, a connection that goes silent during a use_uid=True mark_seen call can hang the coroutine forever, unlike the non-uid store path which is already wrapped by aioimaplib itself. Wrap the uid-store call in asyncio.wait_for(self.timeout) so a stalled server times out and mark_seen returns False like the rest of this method's contract. Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
@@ -245,12 +245,18 @@ class IMAPClient:
|
||||
return None
|
||||
|
||||
async def mark_seen(self, email_id: int) -> bool:
|
||||
"""flag a message as read without deleting it"""
|
||||
"""flag a message as read without deleting it
|
||||
|
||||
aioimaplib does not apply its own timeout to the UID STORE command path, so the
|
||||
use_uid=True call is wrapped here to bound it the same as the non-uid path.
|
||||
"""
|
||||
if not await self.ensure_connection():
|
||||
return False
|
||||
try:
|
||||
if self.use_uid:
|
||||
result, _ = await self._mail.uid("store", str(email_id), "+FLAGS", "(\\Seen)")
|
||||
result, _ = await asyncio.wait_for(
|
||||
self._mail.uid("store", str(email_id), "+FLAGS", "(\\Seen)"), self.timeout
|
||||
)
|
||||
else:
|
||||
result, _ = await self._mail.store(str(email_id), "+FLAGS", "(\\Seen)")
|
||||
return result == "OK"
|
||||
|
||||
Reference in New Issue
Block a user