1jehuang / 1jehuang/jcode

Ambient email should use OAuth (Gmail API), not a raw SMTP/IMAP password

Open
#776 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no enhancement priority: medium triage: needs-decision
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Problem

Ambient mode's email integration ([safety] section) currently only supports raw SMTP/IMAP with a password:

email_enabled
email_smtp_host
email_smtp_port
email_from
email_password   <- plaintext password field, confirmed via `strings` on the jcode binary
email_imap_host
email_imap_port
email_reply_enabled

This is the wrong auth model. jcode already does OAuth for every model provider it talks to (Claude, OpenAI, Gemini, Copilot, Cursor — all confirmed in the binary's credential-handling strings, e.g. ClaudeOAuth, Claude Code (macOS Keychain), OpenCodeAnthropicAuth). Email should follow the same pattern rather than falling back to a raw mailbox password, for two reasons:

  1. Security: SMTP/IMAP app-passwords are long-lived, broad-scope credentials with no built-in expiry/revocation UX. OAuth tokens are scoped, refreshable, and revocable from the provider's own security settings without touching jcode's config at all.
  2. It's redundant work: users who want ambient email almost certainly already have Gmail (or another OAuth-capable provider) wired up somewhere in their toolchain. Re-deriving a plaintext-password flow for jcode specifically, when an OAuth-based flow already exists and is already trusted, is unnecessary extra surface area — both to build and to secure.

Request

Add an OAuth-based email backend for ambient (Gmail first, since it's the most common case), reusing jcode's existing OAuth machinery rather than introducing a new plaintext-secret field:

  • jcode login --provider gmail-ambient (or fold into the existing /login/account picker flow) — standard OAuth device/browser flow, same UX as jcode login google/jcode login gemini already use.
  • Store the resulting OAuth token the same way jcode already stores Claude/OpenAI OAuth tokens (macOS Keychain via security-framework, or jcode's existing multi-account auth.json pattern — whichever the current provider-auth code path already uses, this should just be one more account type in that same system, not new infrastructure).
  • Ambient's email send/receive path calls the Gmail API (gmail.send, gmail.readonly/gmail.modify scopes) using the stored OAuth token, instead of opening a raw SMTP/IMAP socket with a password.
  • Keep the raw SMTP/IMAP path as a fallback for non-Gmail providers that don't support OAuth, but make OAuth the default/first-class path when the user's email is Gmail (detectable from the domain, or just prompt "Gmail (recommended, OAuth) / Other (SMTP/IMAP with app password)" during setup).
Why Gmail specifically

Most users pursuing this (including us) already have a working OAuth-based Gmail integration pattern in their broader toolchain — a token-refresh helper that hands back a valid access token on demand, used for both send and search/read. jcode's ambient email feature could call an equivalent flow directly rather than requiring IMAP/SMTP credentials at all. This also sidesteps the "where do we securely store email_password" problem entirely (see related: encrypted-storage-for-config-secrets, but that's now a secondary concern if OAuth eliminates the password requirement for the common case).

Why this matters

  • Avoids introducing a new plaintext-password credential surface in jcode when a scoped, revocable, already-trusted OAuth pattern is available and jcode already has the infrastructure for it.
  • Matches user expectation: everything else jcode authenticates to (model providers) uses OAuth; email being the one exception via raw password is inconsistent and a downgrade in security posture relative to the rest of the app.
  • Removes the current blocker entirely for Gmail users (which is likely the majority) rather than just making the plaintext password "safer to store" (encrypted-at-rest is still worse than not needing a long-lived password at all).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Begin with the existing jcode login --provider google/gemini and /login account-picker flows, then trace ambient email's send/receive path and its [safety] SMTP/IMAP configuration. Confirm how existing provider OAuth tokens are stored and which Gmail API scopes are needed. Done means Gmail users authenticate through the existing flow and ambient send/receive uses that token, while non-Gmail SMTP/IMAP remains available.

Written by the indexing model from the issue text.

Assessment

Tech stack
google-cloud, rust
Domain
api, authentication, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.