Skip to content

Zoho Mail CLI access — planning doc

Created 2026-04-23
Updated 2026-07-03
Tags infrastructurezohoemailplanning

Planning document for setting up terminal / CLI access to the Zoho Mail archive, matching the gws Google Workspace CLI setup already in place for Gmail. Not yet implemented. Revisit on a future session.

Update 2026-07-03: Revisited and confirmed still needed. The Proto Studio fall-booking session exposed the same gap again: Nicholas’s studio-rate email lived on org@baseworks.com (Zoho) and was invisible to the gws (Google) CLI, so the rate had to be recovered from a screenshot Patrick sent. Patrick also expanded the scope beyond archive search (see Expanded scope 2026-07-03): durable non-expiring credentials, draft-only sending with guardrails, configuring Zoho Mail settings via API, staged deliverability/spam remediation, and migrating Baseworks mail off eM Client into provider-optimized clients. A ready-to-run execution prompt is at the bottom: Ready-to-run prompt for the execution session. Deferred again for time; this doc is the pickup point.

  • Google Workspace hosts the personal mailboxes for Patrick (pat@baseworks.com) and Asia, with aliases (pat@cevaco.co, pat@paraimpacto.com, pat@shaspo.org, po@paraimpacto.com) all routing into those accounts. Handled today via the gws CLI.
  • Zoho Mail hosts every other mailbox across the owned domains. One organization-admin account manages the domain configuration; each domain has its own Zoho login handling its aliases. Historical correspondence (trademarks, accounting, legal, vendor threads) mostly lives here. Thousands of messages across multiple domain mailboxes.
  • DNS routing is a Google-primary configuration with exceptions that route specific mailboxes to Zoho’s MX records. Exact mechanism undocumented; needs to be reverse-engineered from the DNS zone (see open questions below).
  • Today, searching Zoho archives means logging into each domain’s webmail individually. Slow, error-prone, no cross-domain search.
  • Today’s trademark workstream exposed the gap: Shobayashi correspondence was on a Zoho-hosted address and had to be manually forwarded to pat@baseworks.com (Gmail) for Claude to search through gws. That workflow does not scale to other historical lookups (vendor contracts, early Baseworks contracts, accounting).
  • CLI access would let Claude cross-reference any archival thread in seconds during a session, the same way it does with Gmail now.

Option A — IMAP via himalaya (per-account config)

Section titled “Option A — IMAP via himalaya (per-account config)”

What it is: himalaya is a modern IMAP/SMTP CLI. Each Zoho login becomes an account block in its config file. Authenticates with app-specific passwords (not main Zoho password).

Pros:

  • Simplest to set up — 1-2 hours for first account, 15 min per additional
  • Works with any IMAP server, not Zoho-specific
  • Search, read, send, reply, attachments all supported
  • App passwords are revocable per-device (safer than main password)

Cons:

  • N accounts × N configs to maintain
  • IMAP search is slower than API search on large archives (Zoho has millions of indexed messages; IMAP grep is less efficient)
  • Each Zoho login needs its own app password generated manually via Zoho security settings
  • No Zoho-specific features (tags, org-wide admin queries)

Effort estimate: ~2-3 hours to set up for all domains.

Option B — Zoho Mail Admin API (single OAuth app, org-wide access)

Section titled “Option B — Zoho Mail Admin API (single OAuth app, org-wide access)”

What it is: Zoho offers a REST API with admin-level scopes that let a single OAuth app read/send on behalf of any user in the organization. One app registered in Zoho API Console, one OAuth client ID/secret, one refresh token — access to every domain mailbox through admin impersonation.

Pros:

  • Single credential handles all mailboxes — matches Patrick’s “unified access” goal directly
  • API search is fast across large archives (Zoho’s server-side index)
  • Supports Zoho-specific features (tags, threads, org filters)
  • Cleanest long-term — adding a new domain = no new auth, just start querying
  • Admin API lets Claude search Ksenia’s Zoho mailboxes too (when authorized by her) without separate logins

Cons:

  • More initial setup: register OAuth app in Zoho API Console, configure scopes, handle token refresh, pick a credential store
  • Requires building a small wrapper CLI (no gws-equivalent ready to install)
  • Need to pick the right scope tier — ZohoMail.accounts.READ and ZohoMail.messages.ALL at minimum; admin scopes cost more token-refresh complexity

Effort estimate: ~4-6 hours for a first working version; pays off quickly after that.

Option C — Hybrid: start with himalaya, upgrade to Admin API when needed

Section titled “Option C — Hybrid: start with himalaya, upgrade to Admin API when needed”

Pattern: install himalaya for the 2-3 Zoho accounts used most often. Live with it. If it hits a ceiling (too slow on search, missing features, too many accounts to configure), invest in Option B.

Pros:

  • Fastest time to working CLI
  • Avoids over-engineering before use patterns are clear
  • Easy migration path (Option B can coexist with or replace Option A)

Cons:

  • Two setups to maintain short-term
  • Incomplete coverage until upgrade happens

Option C as an entry point, with Option B as the documented target. Install himalaya for the 2-3 highest-value mailboxes this week; use it for a month; if the pattern justifies it, build the Admin API wrapper on that evidence.

If it’s clear up front that cross-domain search across all mailboxes is the primary use case (not occasional per-account lookups), skip straight to Option B — it’s the correct shape for that workload and the extra setup time pays back quickly.

  1. Which Zoho accounts are the highest-value targets? A ranked list would drive the himalaya setup order. Candidates based on what surfaced today: any Baseworks domain addresses that handle vendor/legal/accounting, any address that received Shobayashi correspondence, any address that held early contracts.
  2. DNS mechanism — who decides which addresses route to Zoho vs. Google? Needs a zone-file walkthrough. Likely a mix of MX priority, split-domain configuration with SPF/DKIM records, or Zoho Mail routing rules. Worth documenting in 00-inbox/claude-code-shared-context.md once understood.
  3. Does Asia’s Zoho access need parity with Patrick’s? If yes, Option B becomes more attractive (one credential can serve both). If her use is lighter, himalaya on her own machine is fine.
  4. Credential storage: mac Keychain? ~/.config/baseworks/? pass? Same pattern as gws (encrypted credentials in ~/.config/gws/credentials.enc) is probably the right model.
  5. Retention and compliance: Zoho has per-mailbox retention settings. Any outbound email sent from the CLI needs to be archived the same way Zoho webmail archives it. Confirm before writing a “send” path.
  • Cross-reference any historical thread in seconds during a session (trademarks, contracts, vendor history, Para Impacto correspondence, Shaspo/Ceva business records, etc.)
  • Draft replies to any Zoho-hosted conversation without bouncing through Gmail forwarding
  • Archive-search questions like “what did we agree with X in Y year” become tractable
  • Potential future automation: daily digest of unread Zoho mail into the vault, or auto-capture of specific senders

Patrick flagged this as something to come back to on a separate day. The trademark workstream is the immediate priority and is now closed. This plan is a placeholder to pick up without re-deriving the shape of the problem.

Beyond the archive-search goal above, Patrick wants the execution session to cover:

  1. Search all Zoho mailboxes (org@, asia@, and any other Zoho baseworks.com addresses) the way gws searches the Google ones. Highest priority.
  2. Durable, non-expiring credentials stored securely on the Mac (not in any git repo, chmod 600, ideally migrated into macOS Keychain like gws). Zoho IMAP app-specific passwords don’t expire; OAuth self-client with offline access yields a non-expiring refresh token. Likely both: IMAP for mail, OAuth for admin/config.
  3. Draft-only sending with hard guardrails. Claude may create drafts in the Zoho Drafts folder but must never auto-send. Sending happens only on Patrick’s explicit instruction, or he sends from Drafts himself. (This resolves open question #5 below: build the “send” path as draft-create only.)
  4. Configuring Zoho Mail settings via API where possible (filters, folders, forwarding) vs what needs the admin console — assess and report.
  5. Deliverability / anti-spam, staged. Baseworks Zoho mail sometimes gets flagged as spam or fails to arrive. Audit SPF / DKIM / DMARC for baseworks.com; diagnose before any change; make no DNS change without walking Patrick through it.
  6. Email-client strategy. Move Baseworks off eM Client (slow/cumbersome): a Google-optimized client for the Google accounts (candidates: Mimestream, Apple Mail, Gmail web) and a plan for the Zoho accounts. Recommend, don’t just list.

Secure credential handoff: do NOT have Patrick paste keys/passwords into chat (they persist in transcripts). Tell him exactly what to create and where to put it (a chmod 600 file at a named path, read once then migrated into Keychain), and walk him through generating the Zoho credential (Self Client in api-console.zoho.com with offline access, or per-mailbox IMAP app passwords) and the required scopes.


Ready-to-run prompt for the execution session

Section titled “Ready-to-run prompt for the execution session”

Paste this into a fresh session to start the work:

# Session goal: Connect me to Zoho Mail across all Baseworks mailboxes, then improve our whole email setup
Read these first for context:
- ~/.claude/CLAUDE.md (global) and ~/Obsidian/baseworks-kb-shared-brain/CLAUDE.md (vault rules)
- The Google Workspace CLI doc: ~/Obsidian/baseworks-kb-shared-brain/03-resources/executed-plans/google-workspace-cli-setup.md
- This plan: ~/Obsidian/baseworks-kb-shared-brain/03-resources/plans/zoho-mail-cli-plan.md (options A/B/C, open questions, expanded scope)
- The most recent changelog entry (2026-07-03) in ~/Documents/baseworks-changelog/CHANGELOG.md — explains why this is needed (a Proto Studio email on Zoho org@baseworks.com was invisible to the Google-only gws CLI).
## Background / current state
- Baseworks email is SPLIT across two providers:
- Google — pat@baseworks.com is on Google Workspace, reachable via the `gws` CLI (OAuth, creds in macOS Keychain). Personal Google accounts p.oancia@gmail.com (`gws-p`) and as.poancia@gmail.com (`gws-asia`) too.
- Zoho — org@baseworks.com, asia@baseworks.com, and likely events@/team@/news@/newsjp@baseworks.com. NOT reachable by any tool right now. This is the gap to close.
- I currently use eM Client on the Mac for everything and find it slow/cumbersome.
## What I want, in priority order
1. Get you able to search all our Zoho mailboxes, the way `gws` already searches the Google ones. Most important outcome.
2. Durable, non-expiring credentials. Don't want to re-auth constantly. Zoho OAuth refresh token with offline access and/or IMAP app-specific passwords. Store secrets securely (not in git, chmod 600, ideally migrated into macOS Keychain like `gws`).
3. Draft-only sending with hard guardrails. You may CREATE drafts in the Zoho Drafts folder but must NEVER auto-send. Sending happens only when I explicitly say so, or I send from Drafts myself.
4. Explore configuring Zoho Mail settings via API (filters, folders, forwarding) — tell me what's possible via the API vs the admin console.
5. Deliverability / anti-spam cleanup, staged. Our Zoho mail sometimes gets flagged as spam or doesn't arrive. Audit SPF / DKIM / DMARC for baseworks.com and guide me in stages. Diagnose before changing anything; no DNS change without walking me through it.
6. Email-client strategy. Help me move Baseworks off eM Client: a Google-optimized client for the Google accounts (Mimestream, Apple Mail, Gmail web) and a plan for the Zoho accounts. Recommend, don't just list.
## Secure credential handoff
Do NOT ask me to paste API keys or passwords into chat (they persist in the transcript). Tell me precisely what to create and where to put it — e.g. a file at a specific path with chmod 600 that you read once and then migrate into Keychain. Walk me through generating whatever Zoho needs (Self Client in api-console.zoho.com for OAuth with offline access, or IMAP app-specific passwords per mailbox), including scopes.
## Resolve these unknowns before building anything
- Which exact baseworks.com addresses are on Zoho vs Google? (Confirm org@, asia@, events@, team@, news@, newsjp@.)
- Which Zoho data center / region are we in (.com / .eu / .in)? API and IMAP endpoints depend on it.
- What Zoho Mail plan are we on, and do I have Zoho admin access (needed for org-wide/eDiscovery search and DNS/DKIM changes)?
- Can one admin credential search all mailboxes, or do we need a credential per mailbox?
Propose a staged plan and check in at each stage. Get read/search access working end-to-end first (goal #1), then drafts (#3), then the rest.

Not yet executed. When executed, move this file to 03-resources/executed-plans/ and add an entry to 00-executed-plans-index.md.