fixed race condition, added systemctl integration

This commit is contained in:
Thomas Faour
2026-02-12 20:30:10 -05:00
parent 98e440459b
commit 5e53d0de86
3 changed files with 84 additions and 14 deletions
+23 -14
View File
@@ -10,8 +10,9 @@ from .config import ImapConfig
log = logging.getLogger(__name__)
IDLE_TIMEOUT = 300 # 5 minutes, per RFC 2177
MAX_BACKOFF = 300 # 5 minutes max backoff
IDLE_TIMEOUT = 300 # 5 minutes total IDLE before re-idle (RFC 2177)
IDLE_POLL = 30 # check shutdown every 30 seconds within an IDLE
MAX_BACKOFF = 300 # 5 minutes max backoff
def run_idle_loop(
@@ -60,23 +61,31 @@ def _idle_session(
while not (shutdown_event and shutdown_event.is_set()):
client.idle()
try:
responses = client.idle_check(timeout=IDLE_TIMEOUT)
# Poll in short intervals so we can check shutdown_event
# between iterations, rather than blocking for the full
# IDLE_TIMEOUT (which causes a hang on Ctrl-C).
responses = []
deadline = time.monotonic() + IDLE_TIMEOUT
while time.monotonic() < deadline:
if shutdown_event and shutdown_event.is_set():
break
chunk = client.idle_check(timeout=IDLE_POLL)
if chunk:
responses.extend(chunk)
break # got activity, exit IDLE to process
finally:
client.idle_done()
done_result = client.idle_done()
if done_result and done_result[0]:
responses.extend(done_result[0])
if shutdown_event and shutdown_event.is_set():
break
# Check if any EXISTS response indicates new mail
has_new = any(
isinstance(resp, tuple) and len(resp) >= 2 and resp[1] == b"EXISTS"
for resp in responses
)
if not has_new:
continue
# Fetch new messages since last_uid
# Always search for new UIDs, not just when we see EXISTS.
# A message can arrive between idle_done() and the next idle()
# call — the server already sent EXISTS while we weren't
# listening, so we'd never see it. The UID SEARCH is cheap
# and eliminates this race condition entirely.
new_uids = _fetch_new_uids(client, last_uid)
if not new_uids:
continue