fix(email): guard IMAP FETCH response against non-bytes payloads#18146
Open
vominh1919 wants to merge 1 commit into
Open
fix(email): guard IMAP FETCH response against non-bytes payloads#18146vominh1919 wants to merge 1 commit into
vominh1919 wants to merge 1 commit into
Conversation
Some IMAP servers return malformed FETCH responses where the body slot is an int, plain bytes, or None instead of the expected (header, body) tuple. Accessing msg_data[0][1] then either raises IndexError/TypeError, or returns an int (indexing bytes yields an int in Python 3), which only surfaces later as: ERROR [Email] IMAP fetch error: 'int' object has no attribute 'decode' The exception kills the inner loop iteration and is caught by the outer try/except, so the entire polling pass returns empty — no messages are dispatched for that tick. Add a two-stage guard: 1. try/except (IndexError, TypeError) around msg_data[0][1] access 2. isinstance(raw_email, (bytes, bytearray)) check before message_from_bytes In both cases, log a warning with the offending UID and continue to the next message rather than bailing on the entire poll pass. Fixes NousResearch#12498 Fixes NousResearch#18106
Collaborator
Collaborator
1 similar comment
Collaborator
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Fixes #12498
Fixes #18106
Some IMAP servers return malformed
FETCHresponses where the body slot is anint, plainbytes, orNoneinstead of the expected(header, body)tuple. Accessingmsg_data[0][1]then either raisesIndexError/TypeError, or returns an int (indexingbytesyields an int in Python 3), which only surfaces later as:The exception kills the inner loop iteration and is caught by the outer
try/exceptat the bottom of_fetch_new_messages, so the entire polling pass returns empty — no messages are dispatched for that tick.Observed on iCloud (OVH IMAP) and reported independently in two issues.
Fix
Add a two-stage guard around the fetch response, inside the per-UID loop in
_fetch_new_messages:try/except (IndexError, TypeError)aroundmsg_data[0][1]accessisinstance(raw_email, (bytes, bytearray))check beforemessage_from_bytesIn both branches, log a warning with the offending UID and
continueto the next message rather than bailing on the entire poll pass.Before vs After
msg_data[0]is bytes (indexing yields int)'int' object has no attribute 'decode', entire poll failsmsg_data[0]is NoneTypeError, entire poll fails(header, body)tupleTests
tests/gateway/test_email.py— addedTestFetchMalformedResponsewith 2 tests:test_fetch_skips_int_payload:msg_data = [b"abcdef"]→msg_data[0][1]is int → guard skipstest_fetch_skips_none_payload:msg_data = [None]→TypeError→ guard skips