Skip to content

fix(email): send IMAP ID extension to support 163/NetEase mailbox (salvage #22528)#22796

Merged
teknium1 merged 2 commits into
mainfrom
salvage/pr-22528
May 9, 2026
Merged

fix(email): send IMAP ID extension to support 163/NetEase mailbox (salvage #22528)#22796
teknium1 merged 2 commits into
mainfrom
salvage/pr-22528

Conversation

@teknium1

@teknium1 teknium1 commented May 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Salvage of #22528 — Hermes' email gateway sends an RFC 2971 IMAP ID command after LOGIN, unblocking 163.com / NetEase IMAP polling that requires client identification before any UID SEARCH/FETCH.

Root cause

163's IMAP server enforces RFC 2971 ID identification after LOGIN. Without it, the next operation returns BYE Unsafe Login. Please contact kefu@188.com and disconnects. Hermes' email gateway called imap.login() directly into imap.select("INBOX") + imap.uid("search", ...) with no ID handshake → polling failed on every cycle.

Changes (contributor commits)

  • gateway/platforms/email.py: new module-level _send_imap_id(imap) helper issues imap.xatom("ID", '("name" "hermes-agent" "version" "<v>" "vendor" "NousResearch" "support-email" "noreply@nousresearch.com")') after LOGIN. Best-effort try/except so non-supporting servers (Gmail, Outlook, etc.) keep working with debug logging on failure. Called at both login sites: EmailAdapter.connect() and the polling path EmailAdapter._fetch_new_messages().
  • Version pulled from hermes_cli.__version__ (fallback "0" if import fails).
  • tests/gateway/test_email.py: 3 regression tests (post-login ordering check, polling-path coverage, error-tolerance for non-supporting servers).

Validation

  • 3/3 new IMAP ID tests pass.
  • 60/60 in tests/gateway/test_email.py pass overall.

Closes #22271 via salvage.

163/NetEase IMAP servers reject every UID SEARCH/FETCH with `BYE Unsafe
Login` unless the client first identifies itself via the RFC 2971 ID
command after LOGIN.  Without this, the email gateway logs in OK but
then fails on the very first poll and the connection is torn down.

Send the ID payload best-effort after both `imap.login()` sites
(`EmailAdapter.connect` and `_fetch_new_messages`).  Failures are
swallowed at debug level so non-supporting IMAP servers (Gmail,
Outlook, Fastmail, Yahoo, etc.) keep working unchanged.

Closes #22271
@github-actions

github-actions Bot commented May 9, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: salvage/pr-22528 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 7907 on HEAD, 7906 on base (🆕 +1)

🆕 New issues (1):

Rule Count
invalid-assignment 1
First entries
gateway/platforms/email.py:80: [invalid-assignment] invalid-assignment: Object of type `Literal["0"]` is not assignable to `Literal["0.13.0"]`

✅ Fixed issues: none

Unchanged: 4180 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@teknium1 teknium1 merged commit a671d8a into main May 9, 2026
16 of 18 checks passed
@teknium1 teknium1 deleted the salvage/pr-22528 branch May 9, 2026 20:35
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/email Email (IMAP/SMTP) adapter labels May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery 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.

163 mailbox IMAP connection fails - Missing IMAP ID extension support

3 participants