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
|
return None
|
||||||
|
|
||||||
async def mark_seen(self, email_id: int) -> bool:
|
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():
|
if not await self.ensure_connection():
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
if self.use_uid:
|
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:
|
else:
|
||||||
result, _ = await self._mail.store(str(email_id), "+FLAGS", "(\\Seen)")
|
result, _ = await self._mail.store(str(email_id), "+FLAGS", "(\\Seen)")
|
||||||
return result == "OK"
|
return result == "OK"
|
||||||
|
|||||||
Reference in New Issue
Block a user