Skip to content

fix(email): guard IMAP FETCH response against non-bytes payloads#18146

Open
vominh1919 wants to merge 1 commit into
NousResearch:mainfrom
vominh1919:fix/18106-imap-decode-guard
Open

fix(email): guard IMAP FETCH response against non-bytes payloads#18146
vominh1919 wants to merge 1 commit into
NousResearch:mainfrom
vominh1919:fix/18106-imap-decode-guard

Conversation

@vominh1919

Copy link
Copy Markdown
Contributor

Problem

Fixes #12498
Fixes #18106

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 gateway.platforms.email: [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 at 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:

  1. try/except (IndexError, TypeError) around msg_data[0][1] access
  2. isinstance(raw_email, (bytes, bytearray)) check before message_from_bytes

In both branches, log a warning with the offending UID and continue to the next message rather than bailing on the entire poll pass.

Before vs After

Scenario Before After
msg_data[0] is bytes (indexing yields int) 'int' object has no attribute 'decode', entire poll fails Warning logged, message skipped, rest of inbox processed
msg_data[0] is None TypeError, entire poll fails Warning logged, message skipped, rest of inbox processed
Normal (header, body) tuple Parses OK Unchanged

Tests

  • tests/gateway/test_email.py — added TestFetchMalformedResponse with 2 tests:
    • test_fetch_skips_int_payload: msg_data = [b"abcdef"]msg_data[0][1] is int → guard skips
    • test_fetch_skips_none_payload: msg_data = [None]TypeError → guard skips

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
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists platform/email Email (IMAP/SMTP) adapter duplicate This issue or pull request already exists labels May 1, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #12498 — same IMAP FETCH non-bytes guard fix. Also closes #18106.

@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #12498 - same IMAP FETCH non-bytes guard fix. Also closes #18106.

1 similar comment
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #12498 - same IMAP FETCH non-bytes guard fix. Also closes #18106.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists platform/email Email (IMAP/SMTP) adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: [Email] IMAP fetch error: 'int' object has no attribute 'decode'

2 participants