Skip to content

fix(email): let an explicit config.yaml value win over a bridged env one - #114244

Open
EloquentBrush0x wants to merge 1 commit into
NousResearch:mainfrom
EloquentBrush0x:fix/email-adapter-extra-first-secret-order
Open

EloquentBrush0x wants to merge 1 commit into
NousResearch:mainfrom
EloquentBrush0x:fix/email-adapter-extra-first-secret-order

Conversation

@EloquentBrush0x

Copy link
Copy Markdown
Contributor

Summary

EmailAdapter.__init__ built several settings env-first:

setting = lambda env, key: _get_secret(env, "") or extra.get(key, "")

This is the reversed, more severe variant of this project's extra-vs-env ordering bug (the class already fixed for LINE/Mattermost/IRC elsewhere): a secondary profile's own explicit config.yaml value (platforms.email.address, .smtp_host, .smtp_security, .imap_security, .smtp_tls_verify, .imap_tls_verify) is silently overridden whenever the corresponding EMAIL_* env var resolves truthy — which can happen even outside multiplex, whenever the process environment happens to carry a value (e.g. bridged from another profile, or simply present in a shared environment).

Notably, this same file already gets it right in one place: _standalone_send's address/smtp_host are extra.get(...) or _get_secret(...) (extra-first) — but its smtp_security/smtp_tls_verify, and every setting in __init__'s setting/tls_verify helpers, had the order reversed.

Changes

  • __init__'s setting/tls_verify lambdas now check extra first, falling back to _get_secret (the scoped env reader) only when extra has no value.
  • _standalone_send's smtp_security/smtp_tls_verify flipped to match its own already-correct address/smtp_host lines.

Context on a prior attempt

An older PR (#59076, "honor profile secret scope for email adapter env reads") proposed migrating this file's os.getenv calls to get_secret, but closed with no comment — checking the timeline, it looks superseded rather than rejected: the later #109602 mega-refactor ("one scoped-secret reader... replaces ~40 adapter copies") did that exact migration for this file (and ~40 others) at once. That refactor carried the order of the fallback forward unchanged, though, so the ordering half of the bug survived under the new helper names — this PR is scoped to just that remaining half.

Test plan

  • Added test_explicit_config_yaml_wins_over_bridged_environ (tests/gateway/test_email_secret_scope.py) — sets EMAIL_ADDRESS/EMAIL_SMTP_SECURITY/etc. in os.environ (simulating a bridged/leaked default-profile value) and asserts an explicit extra config wins for every affected field (_address, _imap_host, _smtp_host, _smtp_security, _imap_security, _smtp_tls_verify, _imap_tls_verify).
  • Added test_explicit_smtp_security_wins_over_environ (tests/gateway/test_email.py) — confirms extra['smtp_security']='tls' makes _standalone_send use a direct-SSL connection (SMTP_SSL) instead of plaintext-then-STARTTLS, even with EMAIL_SMTP_SECURITY=starttls in os.environ.
  • Mutation-verify: reverted the production file only, confirmed both new tests fail (wrong address resolved; SMTP_SSL never called) with the exact assertion traps firing; restored the fix, all 70 tests across the five email test files pass.
  • ruff check clean on all three touched files.

🤖 Generated with Claude Code

EmailAdapter's __init__ built _address/_imap_host/_imap_security/
_smtp_host/_smtp_security/_imap_tls_verify/_smtp_tls_verify env-first
(_get_secret(env) or extra.get(key)) — the reversed, more severe variant
of this project's extra-vs-env ordering bug: a secondary profile's own
explicit config.yaml value was silently overridden whenever the
corresponding EMAIL_* var resolved truthy (e.g. bridged from the
default profile's env under multiplex, or simply present in a shared
process environment). _standalone_send's address/smtp_host already
got this right (extra.get(...) or _get_secret(...)); its
smtp_security/smtp_tls_verify did not.

Flipped both the __init__ setting()/tls_verify() helpers and
_standalone_send's two remaining reversed reads to extra-first,
matching the already-correct sites in the same functions.

A prior attempt at this file's os.getenv->get_secret migration
(NousResearch#59076) closed without comment, apparently superseded by the later
NousResearch#109602 mega-refactor that did the migration for ~40 adapters at
once — but that refactor carried the ordering forward as-is rather
than fixing it, so the bug survived under the new helper names.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins platform/email Email (IMAP/SMTP) adapter area/config Config system, migrations, profiles area/profiles Multi-profile isolation, HERMES_HOME scoping labels Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles area/profiles Multi-profile isolation, HERMES_HOME scoping comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have 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.

2 participants