hypermail-mcp 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/cli.js +73 -1
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/server.ts","../src/store/account-store.ts","../src/store/crypto.ts","../src/store/agent-store.ts","../src/providers/outlook/index.ts","../src/providers/shared/inline-images.ts","../src/providers/outlook/client.ts","../src/providers/outlook/auth.ts","../src/providers/imap/client.ts","../src/providers/imap/read-ops.ts","../src/providers/imap/helpers.ts","../src/providers/imap/write-ops.ts","../src/providers/imap/index.ts","../src/providers/gmail/index.ts","../src/providers/gmail/auth.ts","../src/providers/gmail/client.ts","../src/providers/gmail/read-ops.ts","../src/providers/gmail/helpers.ts","../src/providers/gmail/write-ops.ts","../src/providers/registry.ts","../src/tools/shared.ts","../src/markdown-to-html.ts","../src/tools/accounts.ts","../src/tools/agent-context.ts","../src/tools/browse.ts","../src/html-to-markdown.ts","../src/tools/folders.ts","../src/tools/organize.ts","../src/tools/compose.ts","../src/tools/notifications.ts","../src/tools/index.ts","../src/version.ts","../src/config.ts","../src/watcher/manager.ts","../src/config/agents-config.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\n\nimport { startServer } from \"./server.js\";\nimport { loadConfig } from \"./config.js\";\n\ntype ParsedArgs = {\n http: boolean;\n port: number;\n host: string;\n dataDir?: string;\n config?: string;\n agentsConfig?: string;\n help: boolean;\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = {\n http: false,\n port: 3000,\n host: \"127.0.0.1\",\n help: false,\n };\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n switch (a) {\n case \"--http\":\n out.http = true;\n break;\n case \"--port\":\n out.port = Number(argv[++i] ?? \"3000\");\n break;\n case \"--host\":\n out.host = String(argv[++i] ?? \"127.0.0.1\");\n break;\n case \"--data-dir\":\n out.dataDir = String(argv[++i] ?? \"\");\n break;\n case \"--config\":\n out.config = String(argv[++i] ?? \"\");\n break;\n case \"--agents-config\":\n out.agentsConfig = String(argv[++i] ?? \"\");\n break;\n case \"-h\":\n case \"--help\":\n out.help = true;\n break;\n default:\n if (a && a.startsWith(\"--\")) {\n // ignore unknown flags rather than crashing — keeps the CLI forgiving\n // when embedded in MCP host configs.\n }\n }\n }\n return out;\n}\n\nfunction printHelp(): void {\n const msg = `hypermail-mcp — unified email MCP server\n\nUsage:\n hypermail-mcp [options]\n\nOptions:\n --http Run as Streamable HTTP server (default: stdio)\n --port <n> HTTP port (default: 3000)\n --host <addr> HTTP bind address (default: 127.0.0.1)\n --data-dir <path> Where to store the encrypted accounts file\n (default: $HYPERMAIL_MCP_DATA_DIR or ~/.hypermail-mcp)\n --config <path> Path to hypermail-config.json\n -h, --help Show this help\n\nConfiguration:\n All server settings (data dir, HTTP, tool filtering, provider credentials)\n live in hypermail-config.json. Pass it via --config.\n\nExample hypermail-config.json:\n {\n \"dataDir\": \"/path/to/data\",\n \"http\": { \"enabled\": false },\n \"tools\": { \"disabled\": [\"send_email\"] },\n \"providers\": {\n \"outlook\": { \"clientId\": \"\\${MS_CLIENT_ID}\", \"tenantId\": \"\\${MS_TENANT_ID}\" },\n \"gmail\": { \"clientId\": \"\\${GOOGLE_CLIENT_ID}\", \"clientSecret\": \"\\${GOOGLE_CLIENT_SECRET}\" }\n }\n }\n`;\n process.stdout.write(msg);\n}\n\nasync function main(): Promise<void> {\n const rawArgs = process.argv.slice(2);\n\n // Subcommand: generate-key\n if (rawArgs[0] === \"generate-key\") {\n const key = `hm_sk_${randomBytes(32).toString(\"hex\")}`;\n process.stdout.write(key + \"\\n\");\n return;\n }\n\n const opts = parseArgs(rawArgs);\n if (opts.help) {\n printHelp();\n return;\n }\n\n const config = loadConfig(opts.config, {\n http: opts.http,\n port: opts.port,\n host: opts.host,\n dataDir: opts.dataDir,\n agentsConfig: opts.agentsConfig,\n });\n\n await startServer({ config });\n}\n\nmain().catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] fatal:\", err);\n process.exit(1);\n});\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { randomUUID } from \"node:crypto\";\nimport { createServer as createHttpServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport path from \"node:path\";\n\nimport { AccountStore } from \"./store/account-store.js\";\nimport { AgentStore } from \"./store/agent-store.js\";\nimport { buildRegistry } from \"./providers/registry.js\";\nimport { registerTools } from \"./tools/index.js\";\nimport { VERSION } from \"./version.js\";\nimport type { AppConfig, ResolvedTools } from \"./config.js\";\nimport { resolveTools } from \"./config.js\";\nimport { WatcherManager } from \"./watcher/index.js\";\nimport type { WatchNotification } from \"./watcher/index.js\";\nimport {\n loadAgentsConfig,\n watchAgentsConfig,\n} from \"./config/agents-config.js\";\nimport type { AgentContext } from \"./tools/agent-context.js\";\n\nexport interface ServerOptions {\n /** Fully resolved application config from hypermail-config.json. */\n config: AppConfig;\n}\n\nexport async function startServer(opts: ServerOptions): Promise<void> {\n const { config } = opts;\n const store = await AccountStore.open({ dataDir: config.dataDir });\n const registry = buildRegistry({ store, providers: config.providers });\n const tools: ResolvedTools = resolveTools(config);\n\n // Shared notification buffer: the watcher pushes, the check_notifications\n // tool drains. Only created when both HTTP and watch are enabled.\n const watchEnabled = config.http.enabled && config.watch?.enabled !== false;\n const notificationBuffer: WatchNotification[] | undefined = watchEnabled\n ? []\n : undefined;\n\n // Factory: creates a fresh McpServer with all tools registered.\n // HTTP mode creates one per session; stdio mode uses a single instance.\n let agentStoreForFactory: AgentStore | undefined;\n const createServer = (agentContext: AgentContext | null = null): McpServer => {\n const s = new McpServer(\n { name: \"hypermail-mcp\", version: VERSION },\n { capabilities: { tools: {}, logging: {} } },\n );\n registerTools(s, { store, registry, tools, notificationBuffer, agentContext, agentStore: agentStoreForFactory });\n return s;\n };\n\n if (config.http.enabled) {\n // Open AgentStore and load agents.yaml (HTTP mode only).\n let liveReloadHandle: { close(): void } | undefined;\n if (config.agentsConfigPath) {\n agentStoreForFactory = await AgentStore.open({ dataDir: config.dataDir });\n liveReloadHandle = watchAgentsConfig(\n path.resolve(config.agentsConfigPath),\n agentStoreForFactory!,\n (_removedIds) => {\n // Sessions use the same agentStore instance — they'll pick up\n // updated agents on next lookup. Removed agents' existing sessions\n // remain valid until they disconnect (local-trust model).\n },\n (err) => {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] agents.yaml reload error:\", err.message);\n },\n );\n }\n\n // Per-session notification targets — the watcher pushes to all of them.\n const notifyTargets = new Set<(n: WatchNotification) => void>();\n\n // Compute account filter from all agents' authorized accounts.\n // When no agents are configured, poll all stored accounts (legacy).\n const accountFilter: string[] | undefined = agentStoreForFactory\n ? (() => {\n const all = new Set<string>();\n for (const agent of agentStoreForFactory.listAgents()) {\n for (const email of agent.accounts) {\n all.add(email.toLowerCase());\n }\n }\n return all.size > 0 ? [...all] : undefined;\n })()\n : undefined;\n\n if (watchEnabled) {\n const watcher = new WatcherManager({\n registry,\n store,\n pollIntervalSeconds: config.watch?.pollIntervalSeconds ?? 60,\n accountFilter,\n onNotification: (notification) => {\n for (const fn of notifyTargets) {\n fn(notification);\n }\n },\n buffer: notificationBuffer!,\n });\n watcher.start();\n }\n\n await startHttp(\n createServer,\n config.http.host,\n config.http.port,\n notifyTargets,\n agentStoreForFactory,\n );\n\n // Cleanup on shutdown\n if (liveReloadHandle) {\n process.on(\"SIGINT\", () => liveReloadHandle!.close());\n process.on(\"SIGTERM\", () => liveReloadHandle!.close());\n }\n } else {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n }\n}\n\ninterface HttpSession {\n transport: StreamableHTTPServerTransport;\n server: McpServer;\n agentContext: AgentContext | null;\n}\n\nasync function startHttp(\n createServer: (agentContext: AgentContext | null) => McpServer,\n host: string,\n port: number,\n notifyTargets: Set<(n: WatchNotification) => void>,\n agentStore?: AgentStore,\n): Promise<void> {\n // One McpServer + transport per session, keyed by Mcp-Session-Id header.\n const sessions = new Map<string, HttpSession>();\n\n const http = createHttpServer(async (req: IncomingMessage, res: ServerResponse) => {\n try {\n if (!req.url || !req.url.startsWith(\"/mcp\")) {\n res.statusCode = 404;\n res.end(\"not found\");\n return;\n }\n const sessionId = (req.headers[\"mcp-session-id\"] as string | undefined) ?? undefined;\n let session = sessionId ? sessions.get(sessionId) : undefined;\n\n if (!session) {\n // ── Session-init API key validation ──\n let agentContext: AgentContext | null = null;\n if (agentStore) {\n const apiKey = (req.headers[\"x-api-key\"] as string | undefined)?.trim();\n if (!apiKey) {\n res.statusCode = 401;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(JSON.stringify({ error: \"Missing x-api-key header\" }));\n return;\n }\n const agent = agentStore.findAgentByApiKey(apiKey);\n if (!agent) {\n res.statusCode = 401;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(JSON.stringify({ error: \"Invalid API key\" }));\n return;\n }\n agentContext = {\n agentId: agent.id,\n accounts: agent.accounts,\n provisioning: agent.provisioning,\n };\n }\n\n const server = createServer(agentContext);\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (sid: string) => {\n sessions.set(sid, { transport, server, agentContext });\n\n // Register push notification target for this session.\n // Scope to this agent's accounts only.\n const agentAccounts = agentContext\n ? new Set(agentContext.accounts.map((a) => a.toLowerCase()))\n : null;\n const notifyFn = (n: WatchNotification) => {\n // Only deliver notifications for accounts this agent can access.\n if (agentAccounts && !agentAccounts.has(n.account.toLowerCase())) {\n return;\n }\n server.server\n .notification({\n method: \"notifications/message\",\n params: {\n level: n.type === \"new_emails\" ? \"notice\" : \"warning\",\n logger: \"hypermail-watch\",\n data: n,\n },\n })\n .catch(() => {\n /* SSE not connected — fallback via check_notifications */\n });\n };\n notifyTargets.add(notifyFn);\n transport.onclose = () => {\n if (transport.sessionId) sessions.delete(transport.sessionId);\n notifyTargets.delete(notifyFn);\n };\n },\n });\n await server.connect(transport);\n session = { transport, server, agentContext };\n }\n\n // Buffer body for POST / DELETE\n let body: unknown = undefined;\n if (req.method === \"POST\" || req.method === \"DELETE\") {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n const raw = Buffer.concat(chunks).toString(\"utf8\");\n body = raw ? JSON.parse(raw) : undefined;\n }\n await session.transport.handleRequest(req, res, body);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] http error:\", err);\n if (!res.headersSent) {\n res.statusCode = 500;\n res.end(\"internal error\");\n }\n }\n });\n\n await new Promise<void>((resolve) => http.listen(port, host, resolve));\n // eslint-disable-next-line no-console\n console.error(`[hypermail-mcp] listening on http://${host}:${port}/mcp`);\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\n\nimport {\n encrypt,\n decrypt,\n resolveDataDir,\n resolveKey,\n writeAtomic,\n} from \"./crypto.js\";\n\n/**\n * One stored account. `tokens` is provider-specific (e.g. serialized MSAL cache\n * for Outlook, host/port/password blob for IMAP) — the store is opaque to it.\n */\nexport interface AccountRecord {\n email: string;\n provider: \"outlook\" | \"imap\" | \"gmail\";\n displayName?: string;\n tokens: Record<string, unknown>;\n addedAt: string;\n /** HTML snippet — may contain formatting, images, links. Injected at end of outgoing emails. */\n signature?: string;\n /** Font/style preferences applied to outgoing HTML emails. */\n style?: { fontFamily?: string; fontSize?: string; fontColor?: string };\n /** ISO timestamp of the newest email the watcher has already seen.\n * Used by the email-watcher to detect new mail since last poll. */\n lastSeenAt?: string;\n /** Email IDs the watcher has already seen (most recent first, capped at 200).\n * Used for ID-based dedup — emails whose ID is in this list are skipped\n * during polling, preventing duplicate/lost notifications from timestamp\n * collisions. */\n lastSeenIds?: string[];\n}\n\ninterface StoreFile {\n version: 1;\n accounts: AccountRecord[];\n}\n\nexport interface OpenOptions {\n dataDir?: string;\n /** Inject the encryption key directly (mostly for tests). Otherwise resolved\n * from `HYPERMAIL_MCP_KEY` env, then OS keychain, then auto-generated. */\n key?: Buffer;\n}\n\nconst FILE_NAME = \"accounts.json.enc\";\n\nexport class AccountStore {\n private constructor(\n private readonly filePath: string,\n private readonly key: Buffer,\n private data: StoreFile,\n ) {}\n\n static async open(opts: OpenOptions = {}): Promise<AccountStore> {\n const dataDir = resolveDataDir(opts.dataDir);\n await fs.mkdir(dataDir, { recursive: true, mode: 0o700 });\n const filePath = path.join(dataDir, FILE_NAME);\n const key = opts.key ?? (await resolveKey(dataDir));\n\n let data: StoreFile;\n try {\n const buf = await fs.readFile(filePath);\n data = decrypt(buf, key);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n data = { version: 1, accounts: [] };\n } else {\n throw err;\n }\n }\n return new AccountStore(filePath, key, data);\n }\n\n listAccounts(): AccountRecord[] {\n // Return shallow clones without tokens leaking out unintentionally is the\n // caller's job; here we expose the full record for provider use.\n return this.data.accounts.map((a) => ({ ...a }));\n }\n\n getAccount(email: string): AccountRecord | undefined {\n const norm = email.trim().toLowerCase();\n const rec = this.data.accounts.find((a) => a.email.toLowerCase() === norm);\n return rec ? { ...rec } : undefined;\n }\n\n async upsertAccount(rec: AccountRecord): Promise<AccountRecord> {\n const norm = rec.email.trim().toLowerCase();\n const next: AccountRecord = { ...rec, email: norm };\n const idx = this.data.accounts.findIndex((a) => a.email.toLowerCase() === norm);\n if (idx >= 0) this.data.accounts[idx] = next;\n else this.data.accounts.push(next);\n await this.flush();\n return { ...next };\n }\n\n async removeAccount(email: string): Promise<boolean> {\n const norm = email.trim().toLowerCase();\n const before = this.data.accounts.length;\n this.data.accounts = this.data.accounts.filter((a) => a.email.toLowerCase() !== norm);\n if (this.data.accounts.length === before) return false;\n await this.flush();\n return true;\n }\n\n private async flush(): Promise<void> {\n const buf = encrypt(this.data, this.key);\n await writeAtomic(this.filePath, buf);\n }\n}\n","import {\n createCipheriv,\n createDecipheriv,\n randomBytes,\n createHash,\n scryptSync,\n timingSafeEqual,\n} from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\n\nexport const ALGO = \"aes-256-gcm\";\nexport const KEY_LEN = 32;\n\n// ── AES-256-GCM encrypt / decrypt ──\n\n/** Encrypt JSON-serializable data with AES-256-GCM. Returns [1-byte version=1][12 iv][16 tag][ct...]. */\nexport function encrypt(data: unknown, key: Buffer): Buffer {\n if (key.length !== KEY_LEN) throw new Error(`key must be ${KEY_LEN} bytes`);\n const iv = randomBytes(12);\n const cipher = createCipheriv(ALGO, key, iv);\n const plaintext = Buffer.from(JSON.stringify(data), \"utf8\");\n const ct = Buffer.concat([cipher.update(plaintext), cipher.final()]);\n const tag = cipher.getAuthTag();\n return Buffer.concat([Buffer.from([1]), iv, tag, ct]);\n}\n\n/** Decrypt a buffer produced by {@link encrypt}. Returns the parsed JSON value. */\nexport function decrypt<T = unknown>(buf: Buffer, key: Buffer): T {\n if (key.length !== KEY_LEN) throw new Error(`key must be ${KEY_LEN} bytes`);\n if (buf.length < 1 + 12 + 16 + 1) throw new Error(\"encrypted data truncated\");\n const v = buf[0];\n if (v !== 1) throw new Error(`unsupported data version: ${v}`);\n const iv = buf.subarray(1, 13);\n const tag = buf.subarray(13, 29);\n const ct = buf.subarray(29);\n const decipher = createDecipheriv(ALGO, key, iv);\n decipher.setAuthTag(tag);\n const pt = Buffer.concat([decipher.update(ct), decipher.final()]);\n return JSON.parse(pt.toString(\"utf8\")) as T;\n}\n\n// ── key + path resolution ──\n\nexport function resolveDataDir(explicit?: string): string {\n if (explicit && explicit.length > 0) return path.resolve(explicit);\n const env = process.env.HYPERMAIL_MCP_DATA_DIR;\n if (env && env.length > 0) return path.resolve(env);\n return path.join(homedir(), \".hypermail-mcp\");\n}\n\nexport function parseEnvKey(raw: string): Buffer | undefined {\n const s = raw.trim();\n // hex (64 chars)\n if (/^[0-9a-fA-F]{64}$/.test(s)) return Buffer.from(s, \"hex\");\n // base64 — accept any length, then check\n try {\n const buf = Buffer.from(s, \"base64\");\n if (buf.length === KEY_LEN) return buf;\n } catch {\n /* ignore */\n }\n // last-resort: derive 32 bytes via SHA-256 over the raw string\n return createHash(\"sha256\").update(s, \"utf8\").digest();\n}\n\nexport async function resolveKey(dataDir: string): Promise<Buffer> {\n const env = process.env.HYPERMAIL_MCP_KEY;\n if (env && env.length > 0) {\n const k = parseEnvKey(env);\n if (k) return k;\n }\n\n // Try OS keychain via keytar (optional dep).\n const fromKeytar = await tryKeytarGet();\n if (fromKeytar) return fromKeytar;\n\n // Local-dev fallback: persist a generated key to a 0600 file.\n const keyFile = path.join(dataDir, \"master.key\");\n try {\n const existing = await fs.readFile(keyFile);\n if (existing.length === KEY_LEN) return existing;\n } catch {\n /* fall through to generate */\n }\n const gen = randomBytes(KEY_LEN);\n await fs.writeFile(keyFile, gen, { mode: 0o600 });\n await tryKeytarSet(gen);\n return gen;\n}\n\n// ── API key hashing (scrypt — built into Node, no native deps) ──\n\n/**\n * Hash an API key with scrypt. Returns \"salt:hash\" (both hex-encoded) for\n * storage. Suitable for <10 agents — scrypt is purpose-built for password\n * hashing and runs in-process with no native compilation.\n */\nexport function hashApiKey(apiKey: string): string {\n const salt = randomBytes(16).toString(\"hex\");\n const hash = scryptSync(apiKey, salt, 32).toString(\"hex\");\n return `${salt}:${hash}`;\n}\n\n/**\n * Verify a plaintext API key against a stored \"salt:hash\" string produced by\n * {@link hashApiKey}. Uses constant-time comparison.\n */\nexport function verifyApiKey(apiKey: string, stored: string): boolean {\n const [salt, hash] = stored.split(\":\");\n if (!salt || !hash) return false;\n try {\n const computed = scryptSync(apiKey, salt, 32);\n const expected = Buffer.from(hash, \"hex\");\n if (computed.length !== expected.length) return false;\n return timingSafeEqual(computed, expected);\n } catch {\n return false;\n }\n}\n\n// ── atomic file write ──\n\n/** Write `data` to `filePath` atomically (tmp + rename). */\nexport async function writeAtomic(filePath: string, data: Buffer): Promise<void> {\n const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, data, { mode: 0o600 });\n await fs.rename(tmp, filePath);\n}\n\n// ── keytar helpers (private) ──\n\nasync function tryKeytarGet(): Promise<Buffer | undefined> {\n try {\n const mod = (await import(\"keytar\")) as typeof import(\"keytar\");\n const val = await mod.getPassword(\"hypermail-mcp\", \"master\");\n if (val) {\n const buf = Buffer.from(val, \"base64\");\n if (buf.length === KEY_LEN) return buf;\n }\n } catch {\n /* keytar not installed or unsupported platform */\n }\n return undefined;\n}\n\nasync function tryKeytarSet(key: Buffer): Promise<void> {\n try {\n const mod = (await import(\"keytar\")) as typeof import(\"keytar\");\n await mod.setPassword(\"hypermail-mcp\", \"master\", key.toString(\"base64\"));\n } catch {\n /* ignore */\n }\n}\n","import path from \"node:path\";\nimport { promises as fs } from \"node:fs\";\n\nimport {\n encrypt,\n decrypt,\n resolveDataDir,\n resolveKey,\n writeAtomic,\n hashApiKey,\n verifyApiKey,\n} from \"./crypto.js\";\n\n/**\n * One stored agent. API keys are hashed at rest (scrypt) — the plaintext key\n * is never stored. The `id` is a human-readable slug; `accounts` lists the\n * email addresses this agent is authorized to operate on.\n */\nexport interface AgentRecord {\n id: string;\n /** scrypt hash of the agent's API key (format: \"salt:hash\", both hex). */\n apiKeyHash: string;\n name: string;\n /** Email addresses assigned to this agent. */\n accounts: string[];\n /** Whether this agent can provision/remove accounts. */\n provisioning: boolean;\n createdAt: string;\n}\n\ninterface AgentStoreFile {\n version: 1;\n agents: AgentRecord[];\n}\n\nexport interface AgentStoreOpenOptions {\n dataDir?: string;\n /** Inject the encryption key directly (mostly for tests). */\n key?: Buffer;\n}\n\nconst FILE_NAME = \"agents.json.enc\";\n\nexport class AgentStore {\n private constructor(\n private readonly filePath: string,\n private readonly key: Buffer,\n private data: AgentStoreFile,\n ) {}\n\n static async open(opts: AgentStoreOpenOptions = {}): Promise<AgentStore> {\n const dataDir = resolveDataDir(opts.dataDir);\n await fs.mkdir(dataDir, { recursive: true, mode: 0o700 });\n const filePath = path.join(dataDir, FILE_NAME);\n const key = opts.key ?? (await resolveKey(dataDir));\n\n let data: AgentStoreFile;\n try {\n const buf = await fs.readFile(filePath);\n data = decrypt<AgentStoreFile>(buf, key);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n data = { version: 1, agents: [] };\n } else {\n throw err;\n }\n }\n return new AgentStore(filePath, key, data);\n }\n\n // ── queries ──\n\n listAgents(): AgentRecord[] {\n return this.data.agents.map((a) => ({ ...a }));\n }\n\n getAgent(id: string): AgentRecord | undefined {\n const rec = this.data.agents.find((a) => a.id === id);\n return rec ? { ...rec } : undefined;\n }\n\n /**\n * Look up an agent by plaintext API key. Hashes the incoming key and\n * compares against stored hashes with constant-time comparison.\n * Returns undefined if no agent matches.\n */\n findAgentByApiKey(apiKey: string): AgentRecord | undefined {\n for (const agent of this.data.agents) {\n if (verifyApiKey(apiKey, agent.apiKeyHash)) {\n return { ...agent };\n }\n }\n return undefined;\n }\n\n // ── mutations ──\n\n /**\n * Add or update an agent. If `plaintextApiKey` is provided, it is hashed\n * and stored; if omitted, the existing hash is preserved (useful for\n * updates that don't change the key).\n */\n async upsertAgent(\n rec: Omit<AgentRecord, \"apiKeyHash\" | \"createdAt\"> & {\n plaintextApiKey?: string;\n },\n ): Promise<AgentRecord> {\n const idx = this.data.agents.findIndex((a) => a.id === rec.id);\n const existing = idx >= 0 ? this.data.agents[idx] : undefined;\n const apiKeyHash = rec.plaintextApiKey\n ? hashApiKey(rec.plaintextApiKey)\n : existing?.apiKeyHash;\n if (!apiKeyHash) {\n throw new Error(\n `agent ${rec.id}: must provide plaintextApiKey for new agents`,\n );\n }\n\n const next: AgentRecord = {\n id: rec.id,\n apiKeyHash,\n name: rec.name,\n accounts: [...(rec.accounts ?? [])],\n provisioning: rec.provisioning ?? false,\n createdAt: existing?.createdAt ?? new Date().toISOString(),\n };\n\n if (idx >= 0) {\n this.data.agents[idx] = next;\n } else {\n this.data.agents.push(next);\n }\n await this.flush();\n return { ...next };\n }\n\n async removeAgent(id: string): Promise<boolean> {\n const before = this.data.agents.length;\n this.data.agents = this.data.agents.filter((a) => a.id !== id);\n if (this.data.agents.length === before) return false;\n await this.flush();\n return true;\n }\n\n /**\n * Assign an email account to an agent. Idempotent — no error if already\n * assigned. Auto-assignment from `add_account` in HTTP mode calls this.\n */\n async assignAccount(agentId: string, email: string): Promise<AgentRecord> {\n const norm = email.trim().toLowerCase();\n const agent = this.data.agents.find((a) => a.id === agentId);\n if (!agent) throw new Error(`agent ${agentId} not found`);\n if (!agent.accounts.includes(norm)) {\n agent.accounts.push(norm);\n await this.flush();\n }\n return { ...agent };\n }\n\n /**\n * Remove an email account from an agent's assignments. Idempotent.\n */\n async unassignAccount(agentId: string, email: string): Promise<AgentRecord> {\n const norm = email.trim().toLowerCase();\n const agent = this.data.agents.find((a) => a.id === agentId);\n if (!agent) throw new Error(`agent ${agentId} not found`);\n agent.accounts = agent.accounts.filter((a) => a !== norm);\n await this.flush();\n return { ...agent };\n }\n\n // ── persistence ──\n\n private async flush(): Promise<void> {\n const buf = encrypt(this.data, this.key);\n await writeAtomic(this.filePath, buf);\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\n\nimport { ResponseType, type Client } from \"@microsoft/microsoft-graph-client\";\n\nimport { parseInlineImages } from \"../shared/inline-images.js\";\n\nimport type { AccountRecord, AccountStore } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n EmailFull,\n EmailProvider,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n SendInput,\n EmailAddress,\n} from \"../types.js\";\nimport { OutlookClientFactory } from \"./client.js\";\nimport {\n awaitDeviceCodeReady,\n beginDeviceCode,\n type DeviceCodeBegin,\n type SerializedTokens,\n} from \"./auth.js\";\n\n// ---------- inline image conversion ----------\n\ninterface InlineAttachment {\n \"@odata.type\": string;\n name: string;\n contentType: string;\n contentId: string;\n contentBytes: string;\n isInline: boolean;\n}\n\n/**\n * Scans HTML for data:image/...;base64,... URIs, extracts the raw base64\n * data, assigns unique contentIds, and returns the transformed body\n * (with src=\"cid:...\" references) plus an array of inline fileAttachment\n * objects ready for the Graph API.\n *\n * Delegates the HTML parsing to the shared {@link parseInlineImages} and\n * then wraps each image in an Outlook-specific `@odata.type` attachment.\n *\n * Pass-through when there are no matches — returns the original body with\n * an empty attachments array.\n */\nexport function convertInlineImages(body: string): {\n body: string;\n attachments: InlineAttachment[];\n} {\n const { body: transformed, images } = parseInlineImages(body);\n const attachments: InlineAttachment[] = images.map((img) => ({\n \"@odata.type\": \"#microsoft.graph.fileAttachment\",\n name: img.filename,\n contentType: img.contentType,\n contentId: img.cid,\n contentBytes: img.contentBytes,\n isInline: true,\n }));\n return { body: transformed, attachments };\n}\n\ninterface PendingFlow {\n begin: DeviceCodeBegin;\n emailHint?: string;\n startedAt: number;\n settled: \"pending\" | \"ready\" | \"error\" | \"expired\";\n account?: AccountRecord;\n error?: string;\n}\n\nexport interface OutlookProviderOptions {\n store: AccountStore;\n clientId?: string;\n tenantId?: string;\n}\n\nexport class OutlookProvider implements EmailProvider {\n readonly id = \"outlook\" as const;\n private readonly clients: OutlookClientFactory;\n private readonly pending = new Map<string, PendingFlow>();\n private readonly clientId?: string;\n private readonly tenantId?: string;\n\n constructor(private readonly opts: OutlookProviderOptions) {\n this.clientId = opts.clientId;\n this.tenantId = opts.tenantId;\n this.clients = new OutlookClientFactory(opts.store, opts.clientId, opts.tenantId);\n }\n\n // ---------- account lifecycle ----------\n\n async addAccount(input: AddAccountInput): Promise<AddAccountResult> {\n const begin = beginDeviceCode(undefined, this.clientId, this.tenantId);\n await awaitDeviceCodeReady(begin);\n\n const handle = randomUUID();\n const flow: PendingFlow = {\n begin,\n emailHint: input.email,\n startedAt: Date.now(),\n settled: \"pending\",\n };\n this.pending.set(handle, flow);\n\n // Fire-and-forget: when the user finishes, persist and update flow.\n begin.result\n .then(async ({ tokens, account }) => {\n const email = (account.username || input.email || \"\").toLowerCase();\n if (!email) {\n flow.settled = \"error\";\n flow.error = \"no email returned from Microsoft account\";\n return;\n }\n const rec: AccountRecord = {\n email,\n provider: \"outlook\",\n displayName: account.name ?? undefined,\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n };\n const saved = await this.opts.store.upsertAccount(rec);\n flow.account = saved;\n flow.settled = \"ready\";\n })\n .catch((err: unknown) => {\n flow.settled = \"error\";\n flow.error = err instanceof Error ? err.message : String(err);\n });\n\n return {\n status: \"pending\",\n handle,\n verification: {\n userCode: begin.userCode,\n verificationUri: begin.verificationUri,\n expiresAt: begin.expiresAt,\n message: begin.message,\n },\n };\n }\n\n async completeAddAccount(handle: string): Promise<CompleteAddAccountResult> {\n const flow = this.pending.get(handle);\n if (!flow) return { status: \"error\", error: \"unknown handle\" };\n // expire after 20 minutes regardless\n if (Date.now() - flow.startedAt > 20 * 60_000 && flow.settled === \"pending\") {\n flow.settled = \"expired\";\n flow.begin.cancel();\n }\n if (flow.settled === \"ready\" && flow.account) {\n this.pending.delete(handle);\n return { status: \"ready\", account: flow.account };\n }\n if (flow.settled === \"error\") {\n this.pending.delete(handle);\n return { status: \"error\", error: flow.error ?? \"unknown error\" };\n }\n if (flow.settled === \"expired\") {\n this.pending.delete(handle);\n return { status: \"expired\" };\n }\n return { status: \"pending\" };\n }\n\n // ---------- email ops ----------\n\n async listEmails(\n account: AccountRecord,\n opts: ListEmailsOptions,\n ): Promise<ListEmailsResult> {\n const client = this.clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n const folder = opts.folder ?? \"inbox\";\n const filterParts: string[] = [];\n if (opts.unreadOnly) filterParts.push(\"isRead eq false\");\n\n let req = client\n .api(`/me/mailFolders/${encodeURIComponent(folder)}/messages`)\n .top(limit)\n .skip(opts.skip ?? 0)\n .select([\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n ].join(\",\"))\n .orderby(\"receivedDateTime DESC\");\n\n if (filterParts.length > 0) req = req.filter(filterParts.join(\" and \"));\n\n const res = (await req.get()) as { value: GraphMessage[]; \"@odata.nextLink\"?: string };\n return {\n items: res.value.map((m) => mapSummary(m, folder)),\n hasMore: !!res[\"@odata.nextLink\"],\n };\n }\n\n async searchEmails(\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n ): Promise<EmailSummary[]> {\n const client = this.clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n // $search requires the ConsistencyLevel: eventual header\n const res = (await client\n .api(\"/me/messages\")\n .header(\"ConsistencyLevel\", \"eventual\")\n .top(limit)\n .search(`\"${query.replace(/\"/g, '\\\\\"')}\"`)\n .select(\n [\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n ].join(\",\"),\n )\n .get()) as { value: GraphMessage[] };\n return res.value.map((m) => mapSummary(m));\n }\n\n async readEmail(account: AccountRecord, id: string): Promise<EmailFull> {\n const client = this.clients.get(account);\n const m = (await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .select(\n [\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"ccRecipients\",\n \"bccRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n \"body\",\n ].join(\",\"),\n )\n .get()) as GraphMessage;\n\n let attachments: EmailFull[\"attachments\"] = undefined;\n if (m.hasAttachments) {\n try {\n const attRes = (await client\n .api(`/me/messages/${encodeURIComponent(id)}/attachments`)\n .select(\"id,name,contentType,size\")\n .get()) as { value: GraphAttachment[] };\n attachments = attRes.value.map((a) => ({\n id: a.id,\n name: a.name,\n contentType: a.contentType,\n size: a.size,\n }));\n } catch {\n /* ignore attachment listing failure */\n }\n }\n\n const summary = mapSummary(m);\n const body = m.body;\n return {\n ...summary,\n cc: (m.ccRecipients ?? []).map(mapRecipient),\n bcc: (m.bccRecipients ?? []).map(mapRecipient),\n bodyText: body?.contentType === \"text\" ? body.content : undefined,\n bodyHtml: body?.contentType === \"html\" ? body.content : undefined,\n attachments,\n };\n }\n\n async readAttachment(\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n ): Promise<AttachmentContent> {\n const client = this.clients.get(account);\n // First, get the attachment metadata to know the filename\n const att = (await client\n .api(`/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`)\n .select(\"name,contentType\")\n .get()) as { name: string; contentType?: string };\n\n // Download the raw content as ArrayBuffer\n const data = (await client\n .api(`/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}/$value`)\n .responseType(ResponseType.ARRAYBUFFER)\n .get()) as ArrayBuffer;\n\n // Write to temp file with original name\n const outPath = pathJoin(tmpdir(), att.name);\n writeFileSync(outPath, Buffer.from(data));\n\n return {\n name: att.name,\n contentType: att.contentType,\n path: outPath,\n };\n }\n\n // Shared helper — creates a draft from a reference message (forward or\n // reply), prepends our composed body before the existing content, and\n // attaches inline images. Returns the draft message ID.\n private async buildDraftFromReference(\n client: Client,\n createEndpoint: string,\n createPayload: Record<string, unknown>,\n converted: { body: string; attachments: InlineAttachment[] },\n ): Promise<string> {\n const draft: { id: string } = await client\n .api(createEndpoint)\n .post(createPayload);\n\n const draftMsg: { body?: { content?: string; contentType?: string } } =\n await client.api(`/me/messages/${draft.id}`).select(\"body\").get();\n\n const draftBody = draftMsg.body?.content ?? \"\";\n const draftContentType = draftMsg.body?.contentType ?? \"HTML\";\n const spacer = '<div style=\"line-height:12px\"><br></div>';\n const prepend = converted.body + spacer;\n const finalBody = draftBody.includes(\"<body\")\n ? draftBody.replace(/(<body[^>]*>)/i, `$1${prepend}`)\n : prepend + draftBody;\n\n await client.api(`/me/messages/${draft.id}`).patch({\n body: { contentType: draftContentType, content: finalBody },\n });\n\n for (const att of converted.attachments) {\n await client.api(`/me/messages/${draft.id}/attachments`).post(att);\n }\n\n return draft.id;\n }\n\n // Shared backend for sendEmail and saveDraft — handles forward, reply, and\n // new-message paths. The `mode` controls whether the message is sent\n // immediately or saved as a draft.\n private async sendOrSave(\n account: AccountRecord,\n msg: SendInput,\n mode: \"send\" | \"draft\",\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n const converted = convertInlineImages(msg.body);\n\n const toRecipients = msg.to.map(toRecipient);\n const ccRecipients = (msg.cc ?? []).map(toRecipient);\n const bccRecipients = (msg.bcc ?? []).map(toRecipient);\n\n // Forward — build a forward draft, then send if mode is \"send\".\n if (msg.forwardMessageId) {\n const draftId = await this.buildDraftFromReference(\n client,\n `/me/messages/${encodeURIComponent(msg.forwardMessageId)}/createForward`,\n { message: { toRecipients, ccRecipients, bccRecipients }, comment: \"\" },\n converted,\n );\n if (mode === \"send\") {\n await client.api(`/me/messages/${draftId}/send`).post({});\n }\n return { id: draftId };\n }\n\n // Reply — build a reply draft, then send if mode is \"send\".\n if (msg.inReplyTo) {\n const createEndpoint = msg.replyAll\n ? `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReplyAll`\n : `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReply`;\n const draftId = await this.buildDraftFromReference(\n client, createEndpoint, {}, converted,\n );\n if (mode === \"send\") {\n await client.api(`/me/messages/${draftId}/send`).post({});\n }\n return { id: draftId };\n }\n\n // New email — sendMail (mode=send) or POST /me/messages (mode=draft).\n const messagePayload: Record<string, unknown> = {\n subject: msg.subject,\n body: {\n contentType: msg.isHtml ? \"HTML\" : \"Text\",\n content: converted.body,\n },\n toRecipients,\n ccRecipients,\n bccRecipients,\n };\n if (converted.attachments.length > 0) {\n messagePayload.attachments = converted.attachments;\n }\n\n if (mode === \"send\") {\n await client.api(\"/me/sendMail\").post({\n message: messagePayload,\n saveToSentItems: true,\n });\n // Graph's sendMail returns 202 with no body; we don't have an id back.\n return { id: \"\" };\n }\n\n const draft: { id: string } = await client\n .api(\"/me/messages\")\n .post(messagePayload);\n return { id: draft.id };\n }\n\n async sendEmail(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n return this.sendOrSave(account, msg, \"send\");\n }\n\n async saveDraft(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n return this.sendOrSave(account, msg, \"draft\");\n }\n\n async updateDraft(\n account: AccountRecord,\n id: string,\n update: DraftUpdateInput,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n const payload: Record<string, unknown> = {};\n\n if (update.subject !== undefined) {\n payload.subject = update.subject;\n }\n if (update.to !== undefined) {\n payload.toRecipients = update.to.map(toRecipient);\n }\n if (update.cc !== undefined) {\n payload.ccRecipients = update.cc.map(toRecipient);\n }\n if (update.bcc !== undefined) {\n payload.bccRecipients = update.bcc.map(toRecipient);\n }\n if (update.body !== undefined) {\n const converted = convertInlineImages(update.body);\n payload.body = {\n contentType: update.isHtml ? \"HTML\" : \"Text\",\n content: converted.body,\n };\n if (converted.attachments.length > 0) {\n // Patch existing inline attachments: Graph will replace all\n // attachments on the message. We send only the new ones.\n payload.attachments = converted.attachments;\n }\n }\n\n await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .patch(payload);\n\n return { id };\n }\n\n async moveEmail(\n account: AccountRecord,\n id: string,\n destinationId: string,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/messages/${encodeURIComponent(id)}/move`)\n .post({ destinationId });\n }\n\n async sendDraft(\n account: AccountRecord,\n id: string,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n await client.api(`/me/messages/${encodeURIComponent(id)}/send`).post({});\n return { id };\n }\n\n async addAttachmentToDraft(\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n ): Promise<{ id: string; attachment: { id: string; name: string; contentType?: string } }> {\n const client = this.clients.get(account);\n const att = (await client\n .api(`/me/messages/${encodeURIComponent(draftId)}/attachments`)\n .post({\n \"@odata.type\": \"#microsoft.graph.fileAttachment\",\n name,\n contentType: contentType ?? \"application/octet-stream\",\n contentBytes,\n })) as { id: string; name: string; contentType?: string };\n return {\n id: draftId,\n attachment: { id: att.id, name: att.name, contentType: att.contentType },\n };\n }\n\n async markRead(\n account: AccountRecord,\n id: string,\n isRead: boolean,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .patch({ isRead });\n }\n\n async listFolders(\n account: AccountRecord,\n opts: ListFoldersOptions,\n ): Promise<FolderInfo[]> {\n const client = this.clients.get(account);\n const endpoint = opts.parentFolderId\n ? `/me/mailFolders/${encodeURIComponent(opts.parentFolderId)}/childFolders`\n : \"/me/mailFolders\";\n const res = (await client\n .api(endpoint)\n .select([\n \"id\",\n \"displayName\",\n \"parentFolderId\",\n \"childFolderCount\",\n \"totalItemCount\",\n \"unreadItemCount\",\n ].join(\",\"))\n .get()) as { value: GraphFolder[] };\n return (res.value ?? []).map(mapFolder);\n }\n\n async createFolder(\n account: AccountRecord,\n input: CreateFolderInput,\n ): Promise<FolderInfo> {\n const client = this.clients.get(account);\n const parentId = input.parentFolderId ?? \"msgfolderroot\";\n const created = (await client\n .api(`/me/mailFolders/${encodeURIComponent(parentId)}/childFolders`)\n .post({ displayName: input.displayName })) as GraphFolder;\n return mapFolder(created);\n }\n\n async renameFolder(\n account: AccountRecord,\n folderId: string,\n newName: string,\n ): Promise<FolderInfo> {\n const client = this.clients.get(account);\n const updated = (await client\n .api(`/me/mailFolders/${encodeURIComponent(folderId)}`)\n .patch({ displayName: newName })) as GraphFolder;\n return mapFolder(updated);\n }\n\n async deleteFolder(\n account: AccountRecord,\n folderId: string,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/mailFolders/${encodeURIComponent(folderId)}`)\n .delete();\n }\n}\n\n// ---------- mapping helpers ----------\n\ninterface GraphRecipient {\n emailAddress?: { name?: string; address?: string };\n}\ninterface GraphMessage {\n id: string;\n subject?: string;\n from?: GraphRecipient;\n toRecipients?: GraphRecipient[];\n ccRecipients?: GraphRecipient[];\n bccRecipients?: GraphRecipient[];\n receivedDateTime?: string;\n bodyPreview?: string;\n isRead?: boolean;\n hasAttachments?: boolean;\n body?: { contentType?: \"text\" | \"html\"; content?: string };\n}\ninterface GraphAttachment {\n id: string;\n name: string;\n contentType?: string;\n size?: number;\n}\ninterface GraphFolder {\n id: string;\n displayName: string;\n parentFolderId?: string;\n childFolderCount: number;\n totalItemCount: number;\n unreadItemCount: number;\n}\n\nfunction mapFolder(f: GraphFolder): FolderInfo {\n return {\n id: f.id,\n displayName: f.displayName,\n parentFolderId: f.parentFolderId,\n childFolderCount: f.childFolderCount,\n totalItemCount: f.totalItemCount,\n unreadItemCount: f.unreadItemCount,\n };\n}\n\nfunction mapRecipient(r: GraphRecipient): EmailAddress {\n return {\n name: r.emailAddress?.name,\n address: r.emailAddress?.address ?? \"\",\n };\n}\n\nfunction mapSummary(m: GraphMessage, folder?: string): EmailSummary {\n return {\n id: m.id,\n subject: m.subject ?? \"\",\n from: m.from ? mapRecipient(m.from) : undefined,\n to: (m.toRecipients ?? []).map(mapRecipient),\n receivedAt: m.receivedDateTime,\n preview: m.bodyPreview,\n isRead: m.isRead,\n hasAttachments: m.hasAttachments,\n folder,\n };\n}\n\nfunction toRecipient(a: EmailAddress): GraphRecipient {\n return { emailAddress: { name: a.name, address: a.address } };\n}\n\nfunction clampLimit(v: number | undefined, dflt: number, max: number): number {\n if (!v || v <= 0) return dflt;\n return Math.min(v, max);\n}\n","import { randomUUID } from \"node:crypto\";\n\n/** A generic inline image extracted from an HTML body. */\nexport interface InlineImage {\n /** The generated Content-ID (without \"cid:\" prefix). */\n cid: string;\n /** Raw base64 content bytes (without the data:image/...;base64, prefix). */\n contentBytes: string;\n /** Full MIME type, e.g. \"image/png\". */\n contentType: string;\n /** Suggested filename, e.g. \"signature-image.png\". */\n filename: string;\n}\n\n/**\n * Parse an HTML body for `data:image/<subtype>;base64,<payload>` URIs inside\n * `src=\"...\"` attributes. Each match is replaced with a `cid:<uuid>` reference,\n * and the extracted base64 data is collected into a flat image array.\n *\n * This is provider-agnostic — each provider wraps the result into its own\n * attachment format (e.g. Outlook `@odata.type` objects or nodemailer\n * `cid` attachments).\n */\nexport function parseInlineImages(html: string): {\n body: string;\n images: InlineImage[];\n} {\n const images: InlineImage[] = [];\n // Match src=\"data:image/<subtype>;base64,<payload>\"\n // Supports png, jpg, jpeg, gif, svg+xml, webp, bmp, etc.\n const re = /src=\"data:image\\/([\\w+]+);base64,([^\"]+)\"/gi;\n\n const transformed = html.replace(re, (_fullMatch, mimeSubtype, b64) => {\n const contentId = `sig-img-${randomUUID()}`;\n const ext =\n mimeSubtype.toLowerCase().replace(/\\+/g, \"-\") === \"svg-xml\"\n ? \"svg\"\n : mimeSubtype.toLowerCase().replace(/\\+/g, \"-\");\n images.push({\n cid: contentId,\n contentBytes: b64,\n contentType: `image/${mimeSubtype}`,\n filename: `signature-image.${ext}`,\n });\n return `src=\"cid:${contentId}\"`;\n });\n\n return { body: transformed, images };\n}\n","import \"isomorphic-fetch\";\nimport {\n Client,\n type AuthenticationProvider,\n} from \"@microsoft/microsoft-graph-client\";\n\nimport type { AccountStore, AccountRecord } from \"../../store/account-store.js\";\nimport { acquireAccessToken, isSerializedTokens, type SerializedTokens } from \"./auth.js\";\n\n/**\n * Builds a Graph `Client` bound to a stored account. The client uses an\n * `AuthenticationProvider` that calls msal silently on every request, and\n * writes the (possibly-refreshed) cache back into the AccountStore.\n *\n * Clients are cached per email since the underlying SDK reuses connections.\n */\nexport class OutlookClientFactory {\n private readonly cache = new Map<string, Client>();\n /** Serialize token refreshes per email to prevent concurrent-refresh races. */\n private readonly refreshLocks = new Map<string, Promise<string>>();\n\n constructor(\n private readonly store: AccountStore,\n private readonly clientId?: string,\n private readonly tenantId?: string,\n ) {}\n\n get(account: AccountRecord): Client {\n const key = account.email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) return existing;\n\n const store = this.store;\n const refreshLocks = this.refreshLocks;\n const provider: AuthenticationProvider = {\n getAccessToken: async () => {\n const existing = refreshLocks.get(key);\n if (existing) {\n try {\n return await existing;\n } catch {\n // previous refresh failed — fall through to retry\n }\n }\n const promise = (async (): Promise<string> => {\n const fresh = store.getAccount(account.email) ?? account;\n if (!isSerializedTokens(fresh.tokens)) {\n throw new Error(\n \"Outlook account tokens are missing or corrupted — re-run add_account\",\n );\n }\n const tokens: SerializedTokens = fresh.tokens;\n const { accessToken, tokens: nextTokens } = await acquireAccessToken(\n tokens,\n undefined,\n this.clientId,\n this.tenantId,\n );\n if (nextTokens.msalCache !== tokens.msalCache) {\n store\n .upsertAccount({\n ...fresh,\n tokens: nextTokens as unknown as Record<string, unknown>,\n })\n .catch(() => {\n /* swallow — next call will refresh again */\n });\n }\n return accessToken;\n })();\n refreshLocks.set(key, promise);\n try {\n return await promise;\n } finally {\n refreshLocks.delete(key);\n }\n },\n };\n\n const client = Client.initWithMiddleware({ authProvider: provider });\n this.cache.set(key, client);\n return client;\n }\n\n /** Drop a cached client (e.g. after removeAccount). */\n invalidate(email: string): void {\n this.cache.delete(email.toLowerCase());\n }\n}\n","import {\n PublicClientApplication,\n type Configuration,\n type AuthenticationResult,\n type AccountInfo,\n} from \"@azure/msal-node\";\n\n/**\n * Public client app id. Default is the well-known `ms-365` client id used by\n * the softeria/ms-365-mcp-server project — it's a public client registered\n * for personal MSA + multi-tenant work/school. Users can override via\n * MS_CLIENT_ID for their own Entra app registrations.\n */\nconst DEFAULT_CLIENT_ID = \"084a3e9f-a9f4-43f7-89f9-d229cf97853e\";\n// ^ Pre-registered public client app (same one used by softeria/ms-365-mcp-server).\n// Supports personal MSA + multi-tenant work/school via device-code flow.\n// Operators should set MS_CLIENT_ID to a client they control for production.\n\nconst DEFAULT_SCOPES = [\n \"offline_access\",\n \"User.Read\",\n \"Mail.ReadWrite\",\n \"Mail.Send\",\n];\n\nexport interface DeviceCodeBegin {\n userCode: string;\n verificationUri: string;\n message: string;\n expiresAt: string; // ISO\n /** Resolves with the auth result once the user completes the flow. */\n result: Promise<{ tokens: SerializedTokens; account: AccountInfo }>;\n /** Aborts the in-flight polling promise. */\n cancel(): void;\n}\n\nexport interface SerializedTokens {\n /** MSAL cache JSON, encrypted at rest by the account store. */\n msalCache: string;\n /** Home account id used to look up the account in the rehydrated cache. */\n homeAccountId: string;\n /** Tenant id captured at sign-in. */\n tenantId: string;\n /** Username captured at sign-in (typically the primary email). */\n username: string;\n scopes: string[];\n}\n\n/** Type guard — validates that an unknown value has the shape of SerializedTokens. */\nexport function isSerializedTokens(obj: unknown): obj is SerializedTokens {\n if (typeof obj !== \"object\" || obj === null) return false;\n const o = obj as Record<string, unknown>;\n return (\n typeof o.msalCache === \"string\" &&\n typeof o.homeAccountId === \"string\" &&\n typeof o.tenantId === \"string\" &&\n typeof o.username === \"string\" &&\n Array.isArray(o.scopes)\n );\n}\n\nfunction makeConfig(prevCacheJson?: string, clientIdOverride?: string, tenantOverride?: string): Configuration {\n const clientId = clientIdOverride || process.env.MS_CLIENT_ID || DEFAULT_CLIENT_ID;\n const tenant = tenantOverride || process.env.MS_TENANT_ID || \"common\";\n return {\n auth: {\n clientId,\n authority: `https://login.microsoftonline.com/${tenant}`,\n },\n cache: prevCacheJson\n ? {\n // msal-node supports an in-memory cache plugin; we hydrate manually\n // below via deserialize after construction.\n }\n : undefined,\n };\n}\n\nexport function buildPca(prevCacheJson?: string, clientIdOverride?: string, tenantOverride?: string): PublicClientApplication {\n const pca = new PublicClientApplication(makeConfig(prevCacheJson, clientIdOverride, tenantOverride));\n if (prevCacheJson) {\n pca.getTokenCache().deserialize(prevCacheJson);\n }\n return pca;\n}\n\n/**\n * Start a device-code flow. The returned `result` promise resolves once the\n * user has entered the code and consented; callers should poll it (or await it)\n * via `complete_add_account`.\n */\nexport function beginDeviceCode(\n scopes: string[] = DEFAULT_SCOPES,\n clientIdOverride?: string,\n tenantOverride?: string,\n): DeviceCodeBegin {\n const pca = buildPca(undefined, clientIdOverride, tenantOverride);\n let resolve!: (v: { tokens: SerializedTokens; account: AccountInfo }) => void;\n let reject!: (err: unknown) => void;\n const result = new Promise<{ tokens: SerializedTokens; account: AccountInfo }>(\n (res, rej) => {\n resolve = res;\n reject = rej;\n },\n );\n\n // We capture the deviceCodeCallback synchronously to surface the user-facing\n // info back out via this object before awaiting the long-running poll.\n let userCode = \"\";\n let verificationUri = \"\";\n let message = \"\";\n let expiresAt = new Date(Date.now() + 15 * 60_000).toISOString();\n let aborted = false;\n\n const ready = new Promise<void>((r) => {\n pca\n .acquireTokenByDeviceCode({\n scopes,\n deviceCodeCallback: (info) => {\n if (!info.userCode || !info.verificationUri) {\n // MSAL may fire the callback with an empty object if the\n // downstream HTTP request fails — reject so the caller\n // gets a clear error instead of silent empty strings.\n reject(\n new Error(\n \"Microsoft device-code endpoint returned no code. \" +\n \"Check MS_CLIENT_ID is a valid Azure Entra public-client application.\",\n ),\n );\n return;\n }\n userCode = info.userCode;\n verificationUri = info.verificationUri;\n message = info.message;\n if (info.expiresIn) {\n expiresAt = new Date(Date.now() + info.expiresIn * 1000).toISOString();\n }\n r();\n },\n })\n .then((authResult: AuthenticationResult | null) => {\n if (aborted) return;\n if (!authResult || !authResult.account) {\n reject(new Error(\"device-code flow returned no account\"));\n return;\n }\n const cache = pca.getTokenCache().serialize();\n const tokens: SerializedTokens = {\n msalCache: cache,\n homeAccountId: authResult.account.homeAccountId,\n tenantId: authResult.account.tenantId,\n username: authResult.account.username,\n scopes,\n };\n resolve({ tokens, account: authResult.account });\n })\n .catch((err) => {\n if (!aborted) reject(err);\n });\n });\n\n // Surface device-code info synchronously via a wrapper Promise:\n // we return the object but its strings are populated once `ready` settles.\n // To keep the API simple, we attach a getter that callers must `await` on.\n // Instead of getters, we wait for `ready` inside the begin helper:\n return {\n // these are placeholders until ready resolves\n get userCode() {\n return userCode;\n },\n get verificationUri() {\n return verificationUri;\n },\n get message() {\n return message;\n },\n get expiresAt() {\n return expiresAt;\n },\n result,\n cancel() {\n aborted = true;\n },\n // hidden helper for the caller to await initial code\n // (typed via a cast below where used)\n ...({ _ready: ready } as Record<string, unknown>),\n } as DeviceCodeBegin;\n}\n\n/** Await `_ready` so the user-code fields are populated. */\nexport async function awaitDeviceCodeReady(b: DeviceCodeBegin): Promise<void> {\n const r = (b as unknown as { _ready: Promise<void> })._ready;\n await r;\n}\n\n/**\n * Acquire a fresh access token for a stored account, refreshing silently from\n * the persisted MSAL cache. Returns the (possibly-updated) cache so the caller\n * can write it back to the store.\n */\nexport async function acquireAccessToken(\n tokens: SerializedTokens,\n scopes: string[] = DEFAULT_SCOPES,\n clientIdOverride?: string,\n tenantOverride?: string,\n): Promise<{ accessToken: string; tokens: SerializedTokens }> {\n const pca = buildPca(tokens.msalCache, clientIdOverride, tenantOverride);\n const cache = pca.getTokenCache();\n const account =\n (await cache.getAccountByHomeId(tokens.homeAccountId)) ??\n (await cache.getAllAccounts()).find((a) => a.username === tokens.username);\n if (!account) {\n throw new Error(\"no MSAL account in cache — re-run add_account\");\n }\n const res = await pca.acquireTokenSilent({ account, scopes });\n if (!res?.accessToken) {\n throw new Error(\"acquireTokenSilent returned no access token\");\n }\n const next: SerializedTokens = {\n ...tokens,\n msalCache: cache.serialize(),\n scopes,\n };\n return { accessToken: res.accessToken, tokens: next };\n}\n","import { ImapFlow } from \"imapflow\";\nimport type { Readable } from \"node:stream\";\nimport nodemailer from \"nodemailer\";\nimport type { Transporter } from \"nodemailer\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\n\n// ---------- token shape ----------\n\nexport interface ImapTokens {\n host: string;\n port: number;\n secure: boolean;\n user: string;\n password: string;\n smtpHost: string;\n smtpPort: number;\n smtpSecure: boolean;\n}\n\n/** Type guard — validates that an unknown value has the shape of ImapTokens. */\nexport function isImapTokens(obj: unknown): obj is ImapTokens {\n if (typeof obj !== \"object\" || obj === null) return false;\n const o = obj as Record<string, unknown>;\n return (\n typeof o.host === \"string\" &&\n typeof o.port === \"number\" &&\n typeof o.user === \"string\" &&\n typeof o.password === \"string\" &&\n typeof o.smtpHost === \"string\" &&\n typeof o.smtpPort === \"number\"\n );\n}\n\n/** Extract IMAP tokens from an account record, throwing if malformed. */\nexport function extractTokens(account: AccountRecord): ImapTokens {\n if (!isImapTokens(account.tokens)) {\n throw new Error(\n \"IMAP account tokens are missing or corrupted — re-run add_account\",\n );\n }\n return account.tokens as ImapTokens;\n}\n\n// ---------- client ----------\n\n/**\n * Per-account IMAP+SMTP client. Wraps an {@link ImapFlow} connection and a\n * {@link Transporter} from nodemailer. The factory caches instances so a\n * single account reuses its connection across calls.\n */\nexport class ImapClient {\n private imap: ImapFlow | null = null;\n private transporter: Transporter | null = null;\n private connecting: Promise<void> | null = null;\n\n constructor(private readonly tokens: ImapTokens) {}\n\n /** Get (or create) the ImapFlow instance. */\n async getImap(): Promise<ImapFlow> {\n if (this.imap) return this.imap;\n\n this.imap = new ImapFlow({\n host: this.tokens.host,\n port: this.tokens.port,\n secure: this.tokens.secure,\n auth: {\n user: this.tokens.user,\n pass: this.tokens.password,\n },\n logger: false,\n });\n\n // Connect on first use and serialise concurrent callers.\n if (!this.connecting) {\n this.connecting = this.imap\n .connect()\n .catch((err) => {\n // Clear state so next caller retries\n this.imap = null;\n this.connecting = null;\n throw err;\n });\n }\n await this.connecting;\n return this.imap;\n }\n\n /** Get (or create) a nodemailer SMTP transporter. */\n getTransporter(): Transporter {\n if (this.transporter) return this.transporter;\n this.transporter = nodemailer.createTransport({\n host: this.tokens.smtpHost,\n port: this.tokens.smtpPort,\n secure: this.tokens.smtpSecure,\n auth: {\n user: this.tokens.user,\n pass: this.tokens.password,\n },\n });\n return this.transporter;\n }\n\n /**\n * Acquire a mailbox lock and run `fn` with the mailbox selected.\n * Releases the lock automatically after `fn` completes.\n */\n async withMailbox<T>(mailbox: string, fn: (imap: ImapFlow) => Promise<T>): Promise<T> {\n const imap = await this.getImap();\n const lock = await imap.getMailboxLock(mailbox);\n try {\n return await fn(imap);\n } finally {\n lock.release();\n }\n }\n\n /** Disconnect IMAP and close the SMTP pool. */\n async disconnect(): Promise<void> {\n if (this.imap) {\n try {\n await this.imap.logout();\n } catch {\n /* ignore */\n }\n this.imap = null;\n this.connecting = null;\n }\n if (this.transporter) {\n this.transporter.close();\n this.transporter = null;\n }\n }\n}\n\n// ---------- factory ----------\n\n/**\n * Caches {@link ImapClient} instances per account email so connections are\n * reused across calls. Analogous to {@link OutlookClientFactory}.\n */\nexport class ImapClientFactory {\n private readonly cache = new Map<string, ImapClient>();\n\n get(account: AccountRecord): ImapClient {\n const key = account.email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) return existing;\n\n const tokens = extractTokens(account);\n const client = new ImapClient(tokens);\n this.cache.set(key, client);\n return client;\n }\n\n /** Drop a cached client (e.g. after removeAccount). */\n invalidate(email: string): void {\n const key = email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) {\n existing.disconnect().catch(() => {});\n this.cache.delete(key);\n }\n }\n}\n","import { createWriteStream } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { Readable } from \"node:stream\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AttachmentContent,\n EmailFull,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n} from \"../types.js\";\nimport { ImapClientFactory } from \"./client.js\";\nimport {\n BodyNode,\n clampLimit,\n decodeId,\n findAttachments,\n findPartByType,\n ImapEnvelope,\n mapSummary,\n mapEnvelopeAddr,\n mapMailboxToListEntry,\n ImapMailboxEntry,\n resolveFolder,\n} from \"./helpers.js\";\n\n/**\n * Browse operations for IMAP — list, search, read emails, attachments,\n * and folders. All functions are pure and take the client factory as\n * the first argument so the ImapProvider class can delegate to them.\n */\n\nexport async function listEmails(\n clients: ImapClientFactory,\n account: AccountRecord,\n opts: ListEmailsOptions,\n): Promise<ListEmailsResult> {\n const client = clients.get(account);\n const folder = resolveFolder(opts.folder ?? \"INBOX\");\n const limit = clampLimit(opts.limit, 25, 100);\n const skip = opts.skip ?? 0;\n\n return client.withMailbox(folder, async (imap) => {\n const searchCriteria: Record<string, unknown> = {};\n if (opts.unreadOnly) searchCriteria.seen = false;\n\n const allUids = (\n Object.keys(searchCriteria).length > 0\n ? await imap.search(searchCriteria, { uid: true })\n : await imap.search({ all: true }, { uid: true })\n ) as number[];\n\n allUids.sort((a, b) => b - a);\n const pageUids = allUids.slice(skip, skip + limit);\n const hasMore = skip + limit < allUids.length;\n\n if (pageUids.length === 0) {\n return { items: [], hasMore };\n }\n\n const messages = await imap.fetchAll(\n pageUids,\n { envelope: true, flags: true },\n { uid: true },\n );\n\n const items: EmailSummary[] = [];\n for (const msg of messages) {\n items.push(\n mapSummary(\n msg.uid as number,\n folder,\n msg.envelope as ImapEnvelope,\n msg.flags as Set<string>,\n ),\n );\n }\n return { items, hasMore };\n });\n}\n\nexport async function searchEmails(\n clients: ImapClientFactory,\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n): Promise<EmailSummary[]> {\n const client = clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n\n return client.withMailbox(\"INBOX\", async (imap) => {\n const uids = (await imap.search({ text: query }, { uid: true })) as number[];\n uids.sort((a, b) => b - a);\n const pageUids = uids.slice(0, limit);\n\n if (pageUids.length === 0) return [];\n\n const messages = await imap.fetchAll(\n pageUids,\n { envelope: true, flags: true },\n { uid: true },\n );\n\n return messages.map((msg) =>\n mapSummary(\n msg.uid as number,\n \"INBOX\",\n msg.envelope as ImapEnvelope,\n msg.flags as Set<string>,\n ),\n );\n });\n}\n\nexport async function readEmail(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n): Promise<EmailFull> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n\n return client.withMailbox(folder, async (imap) => {\n const msg = await imap.fetchOne(\n uid,\n { bodyStructure: true, envelope: true, flags: true },\n { uid: true },\n );\n\n if (!msg || !msg.envelope) {\n throw new Error(`message not found: ${id}`);\n }\n\n const envelope = msg.envelope as ImapEnvelope;\n const structure = msg.bodyStructure as BodyNode;\n const flags = (msg.flags as Set<string>) ?? new Set<string>();\n\n let bodyText: string | undefined;\n let bodyHtml: string | undefined;\n\n const textPart = findPartByType(structure, \"text/plain\");\n const htmlPart = findPartByType(structure, \"text/html\");\n\n if (textPart) {\n const { content } = await imap.download(uid, textPart, { uid: true });\n const chunks: Buffer[] = [];\n for await (const chunk of content as Readable) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n bodyText = Buffer.concat(chunks).toString(\"utf-8\");\n }\n\n if (htmlPart) {\n const { content } = await imap.download(uid, htmlPart, { uid: true });\n const chunks: Buffer[] = [];\n for await (const chunk of content as Readable) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n bodyHtml = Buffer.concat(chunks).toString(\"utf-8\");\n }\n\n const attachments: EmailFull[\"attachments\"] = findAttachments(\n structure,\n ).map((a) => ({\n id: a.part,\n name: a.name,\n contentType: a.contentType,\n size: a.size,\n }));\n\n const summary = mapSummary(uid, folder, envelope, flags);\n\n return {\n ...summary,\n cc: (envelope.cc ?? []).map(mapEnvelopeAddr),\n bcc: (envelope.bcc ?? []).map(mapEnvelopeAddr),\n bodyText,\n bodyHtml,\n attachments: attachments.length > 0 ? attachments : undefined,\n hasAttachments: attachments.length > 0,\n };\n });\n}\n\nexport async function readAttachment(\n clients: ImapClientFactory,\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n): Promise<AttachmentContent> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(messageId);\n\n return client.withMailbox(folder, async (imap) => {\n const msg = (await imap.fetchOne(\n uid,\n { bodyStructure: true },\n { uid: true },\n )) as { bodyStructure?: BodyNode } | false;\n\n let name = \"attachment\";\n let contentType: string | undefined;\n if (msg && msg.bodyStructure) {\n const attachments = findAttachments(msg.bodyStructure);\n const match = attachments.find((a) => a.part === attachmentId);\n if (match) {\n name = match.name;\n contentType = match.contentType;\n }\n }\n\n const { meta, content } = await imap.download(uid, attachmentId, {\n uid: true,\n });\n\n const outPath = pathJoin(tmpdir(), name);\n await pipeline(\n content as unknown as Readable,\n createWriteStream(outPath),\n );\n\n return {\n name,\n contentType: contentType ?? (meta as { contentType?: string }).contentType,\n path: outPath,\n };\n });\n}\n\nexport async function listFolders(\n clients: ImapClientFactory,\n account: AccountRecord,\n opts: ListFoldersOptions,\n): Promise<FolderInfo[]> {\n const client = clients.get(account);\n const imap = await client.getImap();\n\n const mailboxes = await imap.list({\n statusQuery: { messages: true, unseen: true, uidNext: true },\n } as never);\n\n let results: FolderInfo[] = (\n mailboxes as unknown as ImapMailboxEntry[]\n ).map(mapMailboxToListEntry);\n\n if (opts.parentFolderId) {\n const parentPath = opts.parentFolderId;\n results = results.filter(\n (f) =>\n f.parentFolderId === parentPath ||\n (parentPath === \"INBOX\" && f.displayName === \"INBOX\"),\n );\n } else {\n // Top-level: filter out children of other folders\n const allPaths = new Set(results.map((f) => f.displayName));\n results = results.filter((f) => {\n const lastSep = f.displayName.lastIndexOf(\"/\");\n if (lastSep === -1) return true;\n const parent = f.displayName.slice(0, lastSep);\n return !allPaths.has(parent);\n });\n }\n\n return results;\n}\n","import type { EmailAddress, EmailSummary, FolderInfo } from \"../types.js\";\nimport type { AccountRecord } from \"../../store/account-store.js\";\n\n// ---------- well-known folder mapping ----------\n\nconst WELL_KNOWN_TO_IMAP: Record<string, string> = {\n archive: \"Archive\",\n deleteditems: \"Trash\",\n inbox: \"INBOX\",\n drafts: \"Drafts\",\n sentitems: \"Sent\",\n junkemail: \"Junk\",\n outbox: \"Outbox\",\n};\n\nexport function resolveFolder(wellKnownOrPath: string): string {\n return WELL_KNOWN_TO_IMAP[wellKnownOrPath.toLowerCase()] ?? wellKnownOrPath;\n}\n\n// ---------- generic ----------\n\nexport function clampLimit(v: number | undefined, dflt: number, max: number): number {\n if (!v || v <= 0) return dflt;\n return Math.min(v, max);\n}\n\n// ---------- ID encoding ----------\n\n/** Encode a folder path + numeric UID into a composite message ID. */\nexport function encodeId(folder: string, uid: number): string {\n return `${folder}/${uid}`;\n}\n\n/** Decode a composite message ID back into folder + numeric UID. */\nexport function decodeId(id: string): { folder: string; uid: number } {\n const idx = id.lastIndexOf(\"/\");\n if (idx === -1) throw new Error(`invalid message ID: ${id}`);\n const folder = id.slice(0, idx);\n const uid = Number(id.slice(idx + 1));\n if (!Number.isFinite(uid) || uid <= 0) {\n throw new Error(`invalid message UID in ID: ${id}`);\n }\n return { folder, uid };\n}\n\n// ---------- body structure helpers ----------\n\nexport interface BodyNode {\n type?: string;\n part?: string;\n encoding?: string;\n size?: number;\n disposition?: string;\n dispositionParameters?: Record<string, string>;\n parameters?: Record<string, string>;\n childNodes?: BodyNode[];\n}\n\nexport interface ImapAttachmentMeta {\n part: string;\n name: string;\n contentType?: string;\n size?: number;\n}\n\n/** Recursively collect attachment metadata from a bodyStructure node. */\nexport function findAttachments(node: BodyNode): ImapAttachmentMeta[] {\n const attachments: ImapAttachmentMeta[] = [];\n const topType = (node.type ?? \"\").split(\"/\")[0];\n\n const isAttachment =\n node.disposition === \"attachment\" ||\n (!!node.type &&\n topType !== \"text\" &&\n topType !== \"multipart\" &&\n !node.disposition);\n\n if (isAttachment) {\n attachments.push({\n part: node.part ?? \"1\",\n name:\n node.dispositionParameters?.filename ??\n node.parameters?.name ??\n \"attachment\",\n contentType: node.type,\n size: node.size,\n });\n }\n\n if (node.childNodes) {\n for (const child of node.childNodes) {\n attachments.push(...findAttachments(child));\n }\n }\n\n return attachments;\n}\n\n/**\n * Find the part number for a specific content type (e.g. \"text/plain\",\n * \"text/html\") in the body structure tree.\n */\nexport function findPartByType(\n node: BodyNode,\n contentType: string,\n): string | undefined {\n if (node.type === contentType) return node.part ?? \"1\";\n if (node.childNodes) {\n for (const child of node.childNodes) {\n const found = findPartByType(child, contentType);\n if (found) return found;\n }\n }\n return undefined;\n}\n\n// ---------- envelope mapping ----------\n\nexport interface ImapEnvelopeAddr {\n name?: string;\n address?: string;\n}\n\nexport interface ImapEnvelope {\n subject?: string;\n date?: Date;\n messageId?: string;\n inReplyTo?: string;\n from?: ImapEnvelopeAddr[];\n to?: ImapEnvelopeAddr[];\n cc?: ImapEnvelopeAddr[];\n bcc?: ImapEnvelopeAddr[];\n}\n\nexport function mapEnvelopeAddr(a: ImapEnvelopeAddr): EmailAddress {\n return { name: a.name, address: a.address ?? \"\" };\n}\n\nexport function mapSummary(\n uid: number,\n folder: string,\n envelope: ImapEnvelope,\n flags: Set<string> = new Set(),\n): EmailSummary {\n const fromAddr =\n envelope.from && envelope.from.length > 0 && envelope.from[0]\n ? mapEnvelopeAddr(envelope.from[0])\n : undefined;\n return {\n id: encodeId(folder, uid),\n subject: envelope.subject ?? \"\",\n from: fromAddr,\n to: (envelope.to ?? []).map(mapEnvelopeAddr),\n receivedAt: envelope.date ? envelope.date.toISOString() : undefined,\n isRead: flags.has(\"\\\\Seen\"),\n folder,\n };\n}\n\n// ---------- mailbox mapping ----------\n\nexport interface ImapMailboxEntry {\n path: string;\n name?: string;\n specialUse?: string;\n delimiter?: string;\n listed?: boolean;\n subscribed?: boolean;\n status?: {\n messages?: number;\n unseen?: number;\n };\n}\n\nexport function mapMailboxToListEntry(m: ImapMailboxEntry): FolderInfo {\n const lastSep = m.path.lastIndexOf(\"/\");\n const parentFolderId =\n lastSep === -1 ? undefined : m.path.slice(0, lastSep);\n return {\n id: m.path,\n displayName: m.path,\n parentFolderId,\n childFolderCount: 0,\n totalItemCount: m.status?.messages ?? 0,\n unreadItemCount: m.status?.unseen ?? 0,\n };\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport MailComposer from \"nodemailer/lib/mail-composer/index.js\";\n\nimport type {\n AddAccountInput,\n AddAccountResult,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n FolderInfo,\n SendInput,\n} from \"../types.js\";\nimport { ImapClientFactory, ImapTokens, isImapTokens } from \"./client.js\";\nimport {\n decodeId,\n encodeId,\n ImapEnvelope,\n resolveFolder,\n} from \"./helpers.js\";\n\n/** Write operations for IMAP — send, draft, move, mark, folders. */\n\nexport async function addAccount(\n clients: ImapClientFactory,\n store: { upsertAccount(rec: AccountRecord): Promise<AccountRecord> },\n input: AddAccountInput,\n): Promise<AddAccountResult> {\n const cfg = input.config ?? {};\n const host = String(cfg.host ?? \"\");\n const port = Number(cfg.port ?? 993);\n const secure = cfg.secure !== false;\n const user = String(cfg.user ?? input.email ?? \"\");\n const password = String(cfg.password ?? \"\");\n const smtpHost = String(cfg.smtpHost ?? host);\n const smtpPort = Number(cfg.smtpPort ?? 587);\n const smtpSecure = cfg.smtpSecure === true;\n\n if (!host || !user || !password) {\n throw new Error(\n \"IMAP requires config: { host, port?, secure?, user, password, smtpHost?, smtpPort?, smtpSecure? }\",\n );\n }\n\n const tokens: ImapTokens = {\n host,\n port,\n secure,\n user,\n password,\n smtpHost: smtpHost || host,\n smtpPort: smtpPort || 587,\n smtpSecure,\n };\n\n // Validate by connecting briefly.\n const client = clients.get({\n email: user.toLowerCase(),\n provider: \"imap\",\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n } as AccountRecord);\n\n try {\n await client.getImap();\n } finally {\n clients.invalidate(user.toLowerCase());\n }\n\n // Optionally validate SMTP — best-effort.\n try {\n const t = client.getTransporter();\n await t.verify();\n } catch {\n /* SMTP verification is optional */\n }\n\n const email = user.toLowerCase();\n const rec: AccountRecord = {\n email,\n provider: \"imap\",\n displayName: input.email ?? user,\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n };\n const saved = await store.upsertAccount(rec);\n return { status: \"ready\", account: saved };\n}\n\nexport function completeAddAccount(): CompleteAddAccountResult {\n return {\n status: \"error\",\n error:\n \"IMAP accounts are set up synchronously — no polling needed. \" +\n \"Call add_account with IMAP config to create the account directly.\",\n };\n}\n\nexport async function sendEmail(\n clients: ImapClientFactory,\n account: AccountRecord,\n msg: SendInput,\n): Promise<{ id: string }> {\n const client = clients.get(account);\n const transporter = client.getTransporter();\n\n const mailOptions: import(\"nodemailer\").SendMailOptions = {\n from: `${account.displayName ?? \"\"} <${account.email}>`,\n to: msg.to\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \"),\n subject: msg.subject,\n };\n\n if (msg.isHtml) {\n mailOptions.html = msg.body;\n } else {\n mailOptions.text = msg.body;\n }\n (mailOptions as Record<string, unknown>).attachDataUrls = true;\n\n if (msg.cc && msg.cc.length > 0) {\n mailOptions.cc = msg.cc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n if (msg.bcc && msg.bcc.length > 0) {\n mailOptions.bcc = msg.bcc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n\n // Handle reply and forward threading\n if (msg.inReplyTo || msg.forwardMessageId) {\n const refId = msg.inReplyTo ?? msg.forwardMessageId;\n if (refId) {\n try {\n const { folder: refFolder, uid: refUid } = decodeId(refId);\n const refMsg = (await client.withMailbox(refFolder, async (imap) => {\n return imap.fetchOne(\n refUid,\n { envelope: true, source: true },\n { uid: true },\n );\n })) as { envelope?: ImapEnvelope; source?: string | ArrayBuffer };\n\n if (refMsg?.envelope) {\n const env = refMsg.envelope as ImapEnvelope;\n if (msg.inReplyTo && env.messageId && !msg.forwardMessageId) {\n mailOptions.inReplyTo = env.messageId;\n (mailOptions as Record<string, unknown>).references =\n env.messageId;\n }\n }\n\n // Embed forwarded message\n if (msg.forwardMessageId && refMsg?.source) {\n const sourceStr =\n typeof refMsg.source === \"string\"\n ? refMsg.source\n : Buffer.from(refMsg.source as ArrayBuffer).toString(\"utf-8\");\n const divider =\n '\\n\\n<div style=\"line-height:12px\"><br></div>\\n\\n' +\n '<div style=\"border-left:2px solid #ccc; padding-left:8px; ' +\n 'margin-left:0; color:#666\">\\n' +\n \"---------- Forwarded message ---------<br>\" +\n sourceStr +\n \"\\n</div>\";\n if (mailOptions.html) {\n mailOptions.html += divider;\n } else if (mailOptions.text) {\n mailOptions.text +=\n \"\\n\\n---------- Forwarded message ---------\\n\" + sourceStr;\n }\n }\n } catch {\n /* If we can't fetch the referenced message, proceed without threading. */\n }\n }\n }\n\n const info = await transporter.sendMail(mailOptions);\n\n // Save a copy to Sent folder\n try {\n const rawMsg = await buildRawMessage(account, msg, info.messageId);\n await client.withMailbox(\"Sent\", async (imap) => {\n await imap.append(\"Sent\", rawMsg, [\"\\\\Seen\"]);\n });\n } catch {\n /* best-effort */\n }\n\n return { id: info.messageId };\n}\n\nexport async function saveDraft(\n clients: ImapClientFactory,\n account: AccountRecord,\n msg: SendInput,\n): Promise<{ id: string }> {\n const client = clients.get(account);\n const rawMsg = await buildRawMessage(account, msg);\n return client.withMailbox(\"Drafts\", async (imap) => {\n const result = (await imap.append(\"Drafts\", rawMsg, [\"\\\\Draft\"])) as { uid: number };\n return { id: encodeId(\"Drafts\", result.uid) };\n });\n}\n\nexport async function updateDraft(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n update: DraftUpdateInput,\n): Promise<{ id: string }> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n\n return client.withMailbox(folder, async (imap) => {\n const existing = (await imap.fetchOne(\n uid,\n { source: true, envelope: true },\n { uid: true },\n )) as { source?: string | ArrayBuffer; envelope?: ImapEnvelope };\n if (!existing?.source) {\n throw new Error(`draft not found: ${id}`);\n }\n\n const origSubject = existing.envelope\n ? (existing.envelope as ImapEnvelope).subject ?? \"\"\n : \"\";\n\n const updatedMsg: Record<string, unknown> = {\n from: `${account.displayName ?? \"\"} <${account.email}>`,\n subject: update.subject ?? origSubject,\n attachDataUrls: true,\n };\n\n if (update.body !== undefined) {\n if (update.isHtml) {\n updatedMsg.html = update.body;\n } else {\n updatedMsg.text = update.body;\n }\n }\n\n const raw = await new Promise<Buffer>((resolve, reject) => {\n const mc = new MailComposer(updatedMsg);\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf);\n });\n });\n\n await imap.messageDelete(uid, { uid: true });\n const result = (await imap.append(folder, raw, [\"\\\\Draft\"])) as { uid: number };\n return { id: encodeId(folder, result.uid) };\n });\n}\n\nexport async function moveEmail(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n destinationId: string,\n): Promise<void> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n const dest = resolveFolder(destinationId);\n\n return client.withMailbox(folder, async (imap) => {\n await imap.messageMove(uid, dest, { uid: true });\n });\n}\n\nexport async function sendDraft(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n): Promise<{ id: string }> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n\n return client.withMailbox(folder, async (imap) => {\n const draft = (await imap.fetchOne(\n uid,\n { source: true },\n { uid: true },\n )) as { source?: string | ArrayBuffer };\n if (!draft?.source) {\n throw new Error(`draft not found: ${id}`);\n }\n\n const sourceStr =\n typeof draft.source === \"string\"\n ? draft.source\n : Buffer.from(draft.source as ArrayBuffer).toString(\"utf-8\");\n\n const transporter = client.getTransporter();\n const info = await transporter.sendMail({ raw: sourceStr });\n\n try {\n await imap.messageMove(uid, \"Sent\", { uid: true });\n } catch {\n /* best-effort */\n }\n\n return { id: info.messageId };\n });\n}\n\nexport async function addAttachmentToDraft(\n clients: ImapClientFactory,\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n): Promise<{\n id: string;\n attachment: { id: string; name: string; contentType?: string };\n}> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(draftId);\n\n return client.withMailbox(folder, async (imap) => {\n const existing = (await imap.fetchOne(\n uid,\n { source: true },\n { uid: true },\n )) as { source?: string | ArrayBuffer };\n if (!existing?.source) {\n throw new Error(`draft not found: ${draftId}`);\n }\n\n const sourceStr =\n typeof existing.source === \"string\"\n ? existing.source\n : Buffer.from(existing.source as ArrayBuffer).toString(\"utf-8\");\n\n const built = await new Promise<Buffer>((resolve, reject) => {\n const mc = new MailComposer({\n raw: sourceStr,\n attachments: [\n {\n filename: name,\n content: Buffer.from(contentBytes, \"base64\"),\n contentType: contentType ?? \"application/octet-stream\",\n },\n ],\n });\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf);\n });\n });\n\n await imap.messageDelete(uid, { uid: true });\n const result = (await imap.append(folder, built, [\"\\\\Draft\"])) as { uid: number };\n\n return {\n id: encodeId(folder, result.uid),\n attachment: {\n id: randomUUID(),\n name,\n contentType: contentType ?? \"application/octet-stream\",\n },\n };\n });\n}\n\nexport async function markRead(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n isRead: boolean,\n): Promise<void> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n\n return client.withMailbox(folder, async (imap) => {\n if (isRead) {\n await imap.messageFlagsAdd(uid, [\"\\\\Seen\"], { uid: true });\n } else {\n await imap.messageFlagsRemove(uid, [\"\\\\Seen\"], { uid: true });\n }\n });\n}\n\nexport async function createFolder(\n clients: ImapClientFactory,\n account: AccountRecord,\n input: CreateFolderInput,\n): Promise<FolderInfo> {\n const client = clients.get(account);\n const imap = await client.getImap();\n\n const path = input.parentFolderId\n ? `${input.parentFolderId}/${input.displayName}`\n : input.displayName;\n\n const result = await imap.mailboxCreate(path);\n\n return {\n id: result.path,\n displayName: result.path,\n parentFolderId: input.parentFolderId,\n childFolderCount: 0,\n totalItemCount: 0,\n unreadItemCount: 0,\n };\n}\n\nexport async function renameFolder(\n clients: ImapClientFactory,\n account: AccountRecord,\n folderId: string,\n newName: string,\n): Promise<FolderInfo> {\n const client = clients.get(account);\n const imap = await client.getImap();\n\n const lastSep = folderId.lastIndexOf(\"/\");\n const newPath =\n lastSep === -1 ? newName : folderId.slice(0, lastSep + 1) + newName;\n\n const result = await imap.mailboxRename(folderId, newPath);\n\n return {\n id: result.path,\n displayName: result.path,\n parentFolderId: lastSep === -1 ? undefined : folderId.slice(0, lastSep),\n childFolderCount: 0,\n totalItemCount: 0,\n unreadItemCount: 0,\n };\n}\n\nexport async function deleteFolder(\n clients: ImapClientFactory,\n account: AccountRecord,\n folderId: string,\n): Promise<void> {\n const client = clients.get(account);\n const imap = await client.getImap();\n await imap.mailboxDelete(folderId);\n}\n\nasync function buildRawMessage(\n account: AccountRecord,\n msg: SendInput,\n messageId?: string,\n): Promise<string> {\n const mailOptions: Record<string, unknown> = {\n from: `${account.displayName ?? \"\"} <${account.email}>`,\n to: msg.to\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \"),\n subject: msg.subject,\n attachDataUrls: true,\n };\n\n if (msg.isHtml) {\n mailOptions.html = msg.body;\n } else {\n mailOptions.text = msg.body;\n }\n\n if (msg.cc && msg.cc.length > 0) {\n mailOptions.cc = msg.cc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n if (msg.bcc && msg.bcc.length > 0) {\n mailOptions.bcc = msg.bcc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n\n if (messageId) {\n mailOptions.messageId = messageId;\n }\n\n return new Promise<string>((resolve, reject) => {\n const mc = new MailComposer(mailOptions);\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf.toString(\"utf-8\"));\n });\n });\n}\n","import type { AccountRecord, AccountStore } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n EmailFull,\n EmailProvider,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n SendInput,\n} from \"../types.js\";\nimport { ImapClientFactory } from \"./client.js\";\nimport {\n listEmails,\n searchEmails,\n readEmail,\n readAttachment,\n listFolders,\n} from \"./read-ops.js\";\nimport {\n addAccount,\n completeAddAccount,\n sendEmail,\n saveDraft,\n updateDraft,\n moveEmail,\n sendDraft,\n addAttachmentToDraft,\n markRead,\n createFolder,\n renameFolder,\n deleteFolder,\n} from \"./write-ops.js\";\n\nexport class ImapProvider implements EmailProvider {\n readonly id = \"imap\" as const;\n private readonly clients = new ImapClientFactory();\n\n constructor(private readonly store?: AccountStore) {}\n\n // ---------- account lifecycle ----------\n\n async addAccount(input: AddAccountInput): Promise<AddAccountResult> {\n if (!this.store) throw new Error(\"IMAP provider requires an AccountStore\");\n return addAccount(this.clients, this.store, input);\n }\n\n async completeAddAccount(_handle: string): Promise<CompleteAddAccountResult> {\n return completeAddAccount();\n }\n\n // ---------- browse ----------\n\n async listEmails(account: AccountRecord, opts: ListEmailsOptions): Promise<ListEmailsResult> {\n return listEmails(this.clients, account, opts);\n }\n\n async searchEmails(account: AccountRecord, query: string, opts: SearchEmailsOptions): Promise<EmailSummary[]> {\n return searchEmails(this.clients, account, query, opts);\n }\n\n async readEmail(account: AccountRecord, id: string): Promise<EmailFull> {\n return readEmail(this.clients, account, id);\n }\n\n async readAttachment(account: AccountRecord, messageId: string, attachmentId: string): Promise<AttachmentContent> {\n return readAttachment(this.clients, account, messageId, attachmentId);\n }\n\n // ---------- compose ----------\n\n async sendEmail(account: AccountRecord, msg: SendInput): Promise<{ id: string }> {\n return sendEmail(this.clients, account, msg);\n }\n\n async saveDraft(account: AccountRecord, msg: SendInput): Promise<{ id: string }> {\n return saveDraft(this.clients, account, msg);\n }\n\n async updateDraft(account: AccountRecord, id: string, update: DraftUpdateInput): Promise<{ id: string }> {\n return updateDraft(this.clients, account, id, update);\n }\n\n async moveEmail(account: AccountRecord, id: string, destinationId: string): Promise<void> {\n return moveEmail(this.clients, account, id, destinationId);\n }\n\n async sendDraft(account: AccountRecord, id: string): Promise<{ id: string }> {\n return sendDraft(this.clients, account, id);\n }\n\n async addAttachmentToDraft(\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n ): Promise<{ id: string; attachment: { id: string; name: string; contentType?: string } }> {\n return addAttachmentToDraft(this.clients, account, draftId, name, contentBytes, contentType);\n }\n\n // ---------- organize ----------\n\n async markRead(account: AccountRecord, id: string, isRead: boolean): Promise<void> {\n return markRead(this.clients, account, id, isRead);\n }\n\n // ---------- folders ----------\n\n async listFolders(account: AccountRecord, opts: ListFoldersOptions): Promise<FolderInfo[]> {\n return listFolders(this.clients, account, opts);\n }\n\n async createFolder(account: AccountRecord, input: CreateFolderInput): Promise<FolderInfo> {\n return createFolder(this.clients, account, input);\n }\n\n async renameFolder(account: AccountRecord, folderId: string, newName: string): Promise<FolderInfo> {\n return renameFolder(this.clients, account, folderId, newName);\n }\n\n async deleteFolder(account: AccountRecord, folderId: string): Promise<void> {\n return deleteFolder(this.clients, account, folderId);\n }\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport type { AccountStore, AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n EmailFull,\n EmailProvider,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n SendInput,\n} from \"../types.js\";\nimport {\n awaitDeviceCodeReady,\n beginDeviceCode,\n type SerializedGmailTokens,\n} from \"./auth.js\";\nimport { GmailClientFactory } from \"./client.js\";\nimport {\n listEmails,\n searchEmails,\n readEmail,\n readAttachment,\n listFolders,\n} from \"./read-ops.js\";\nimport {\n sendEmail,\n saveDraft,\n updateDraft,\n moveEmail,\n sendDraft,\n addAttachmentToDraft,\n markRead,\n createFolder,\n renameFolder,\n deleteFolder,\n} from \"./write-ops.js\";\n\n// ── pending flow (mirrors Outlook's PendingFlow pattern) ──\n\ninterface PendingFlow {\n begin: ReturnType<typeof beginDeviceCode>;\n emailHint?: string;\n startedAt: number;\n settled: \"pending\" | \"ready\" | \"error\" | \"expired\";\n account?: AccountRecord;\n error?: string;\n}\n\n// ── provider ──\n\nexport interface GmailProviderOptions {\n store: AccountStore;\n clientId?: string;\n clientSecret?: string;\n}\n\nexport class GmailProvider implements EmailProvider {\n readonly id = \"gmail\" as const;\n private readonly clients: GmailClientFactory;\n private readonly pending = new Map<string, PendingFlow>();\n private readonly clientId?: string;\n private readonly clientSecret?: string;\n\n constructor(private readonly opts: GmailProviderOptions) {\n this.clientId = opts.clientId;\n this.clientSecret = opts.clientSecret;\n this.clients = new GmailClientFactory(\n opts.store,\n opts.clientId,\n opts.clientSecret,\n );\n }\n\n // ── account lifecycle ──\n\n async addAccount(input: AddAccountInput): Promise<AddAccountResult> {\n const begin = beginDeviceCode(\n undefined,\n this.clientId,\n this.clientSecret,\n );\n await awaitDeviceCodeReady(begin);\n\n const handle = randomUUID();\n const flow: PendingFlow = {\n begin,\n emailHint: input.email,\n startedAt: Date.now(),\n settled: \"pending\",\n };\n this.pending.set(handle, flow);\n\n begin.result\n .then(async ({ tokens, email }) => {\n const resolvedEmail = (email || input.email || \"\").toLowerCase();\n if (!resolvedEmail) {\n flow.settled = \"error\";\n flow.error = \"no email returned from Google account\";\n return;\n }\n const rec: AccountRecord = {\n email: resolvedEmail,\n provider: \"gmail\",\n displayName: resolvedEmail,\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n };\n const saved = await this.opts.store.upsertAccount(rec);\n flow.account = saved;\n flow.settled = \"ready\";\n })\n .catch((err: unknown) => {\n flow.settled = \"error\";\n flow.error = err instanceof Error ? err.message : String(err);\n });\n\n return {\n status: \"pending\",\n handle,\n verification: {\n userCode: begin.userCode,\n verificationUri: begin.verificationUri,\n expiresAt: begin.expiresAt,\n message: begin.message,\n },\n };\n }\n\n async completeAddAccount(\n handle: string,\n ): Promise<CompleteAddAccountResult> {\n const flow = this.pending.get(handle);\n if (!flow) return { status: \"error\", error: \"unknown handle\" };\n if (\n Date.now() - flow.startedAt > 20 * 60_000 &&\n flow.settled === \"pending\"\n ) {\n flow.settled = \"expired\";\n flow.begin.cancel();\n }\n if (flow.settled === \"ready\" && flow.account) {\n this.pending.delete(handle);\n return { status: \"ready\", account: flow.account };\n }\n if (flow.settled === \"error\") {\n this.pending.delete(handle);\n return { status: \"error\", error: flow.error ?? \"unknown error\" };\n }\n if (flow.settled === \"expired\") {\n this.pending.delete(handle);\n return { status: \"expired\" };\n }\n return { status: \"pending\" };\n }\n\n // ── browse ──\n\n async listEmails(\n account: AccountRecord,\n opts: ListEmailsOptions,\n ): Promise<ListEmailsResult> {\n return listEmails(this.clients, account, opts);\n }\n\n async searchEmails(\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n ): Promise<EmailSummary[]> {\n return searchEmails(this.clients, account, query, opts);\n }\n\n async readEmail(account: AccountRecord, id: string): Promise<EmailFull> {\n return readEmail(this.clients, account, id);\n }\n\n async readAttachment(\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n ): Promise<AttachmentContent> {\n return readAttachment(this.clients, account, messageId, attachmentId);\n }\n\n // ── compose ──\n\n async sendEmail(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n return sendEmail(this.clients, account, msg);\n }\n\n async saveDraft(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n return saveDraft(this.clients, account, msg);\n }\n\n async updateDraft(\n account: AccountRecord,\n id: string,\n update: DraftUpdateInput,\n ): Promise<{ id: string }> {\n return updateDraft(this.clients, account, id, update);\n }\n\n async moveEmail(\n account: AccountRecord,\n id: string,\n destinationId: string,\n ): Promise<void> {\n return moveEmail(this.clients, account, id, destinationId);\n }\n\n async sendDraft(\n account: AccountRecord,\n id: string,\n ): Promise<{ id: string }> {\n return sendDraft(this.clients, account, id);\n }\n\n async addAttachmentToDraft(\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n ): Promise<{\n id: string;\n attachment: { id: string; name: string; contentType?: string };\n }> {\n return addAttachmentToDraft(\n this.clients,\n account,\n draftId,\n name,\n contentBytes,\n contentType,\n );\n }\n\n // ── organize ──\n\n async markRead(\n account: AccountRecord,\n id: string,\n isRead: boolean,\n ): Promise<void> {\n return markRead(this.clients, account, id, isRead);\n }\n\n // ── folders ──\n\n async listFolders(\n account: AccountRecord,\n opts: ListFoldersOptions,\n ): Promise<FolderInfo[]> {\n return listFolders(this.clients, account, opts);\n }\n\n async createFolder(\n account: AccountRecord,\n input: CreateFolderInput,\n ): Promise<FolderInfo> {\n return createFolder(this.clients, account, input);\n }\n\n async renameFolder(\n account: AccountRecord,\n folderId: string,\n newName: string,\n ): Promise<FolderInfo> {\n return renameFolder(this.clients, account, folderId, newName);\n }\n\n async deleteFolder(\n account: AccountRecord,\n folderId: string,\n ): Promise<void> {\n return deleteFolder(this.clients, account, folderId);\n }\n}\n","import { OAuth2Client } from \"google-auth-library\";\n\nconst GOOGLE_DEVICE_CODE_URL = \"https://oauth2.googleapis.com/device/code\";\nconst GOOGLE_TOKEN_URL = \"https://oauth2.googleapis.com/token\";\nconst GOOGLE_OAUTH2_REVOKE_URL = \"https://oauth2.googleapis.com/revoke\";\n\nconst DEFAULT_SCOPES = [\n \"https://www.googleapis.com/auth/gmail.modify\",\n];\n\nexport interface DeviceCodeBegin {\n userCode: string;\n verificationUri: string;\n message: string;\n expiresAt: string; // ISO\n /** Resolves with the tokens and email once the user completes the flow. */\n result: Promise<{ tokens: SerializedGmailTokens; email: string }>;\n /** Aborts the in-flight polling promise. */\n cancel(): void;\n}\n\nexport interface SerializedGmailTokens {\n /** Client ID used to authenticate this account. */\n clientId: string;\n /** Client secret, if any (optional for installed/TV apps). */\n clientSecret?: string;\n /** Current access token. */\n accessToken: string;\n /** Long-lived refresh token. */\n refreshToken: string;\n /** Expiry timestamp in milliseconds since epoch. */\n expiryDate: number;\n /** Scopes granted. */\n scopes: string[];\n /** Email address associated with this account. */\n email: string;\n}\n\n/** Type guard — validates that an unknown value has the shape of SerializedGmailTokens. */\nexport function isSerializedGmailTokens(\n obj: unknown,\n): obj is SerializedGmailTokens {\n if (typeof obj !== \"object\" || obj === null) return false;\n const o = obj as Record<string, unknown>;\n return (\n typeof o.clientId === \"string\" &&\n (o.clientSecret === undefined || typeof o.clientSecret === \"string\") &&\n typeof o.accessToken === \"string\" &&\n typeof o.refreshToken === \"string\" &&\n typeof o.expiryDate === \"number\" &&\n Array.isArray(o.scopes) &&\n typeof o.email === \"string\"\n );\n}\n\n/**\n * Build an {@link OAuth2Client} hydrated with stored tokens.\n * Returns a fresh client that can be used for silent refresh.\n */\nexport function buildOAuth2Client(\n tokens?: SerializedGmailTokens,\n): OAuth2Client {\n const client = new OAuth2Client({\n clientId: tokens?.clientId,\n clientSecret: tokens?.clientSecret,\n });\n if (tokens) {\n client.setCredentials({\n access_token: tokens.accessToken,\n refresh_token: tokens.refreshToken,\n expiry_date: tokens.expiryDate,\n scope: tokens.scopes.join(\" \"),\n });\n }\n return client;\n}\n\n/** Fetch the email address associated with an access token via the Gmail profile endpoint. */\nasync function getEmailFromToken(accessToken: string): Promise<string> {\n const res = await fetch(\n \"https://gmail.googleapis.com/gmail/v1/users/me/profile\",\n {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n },\n );\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(\n `Failed to get Gmail profile (${res.status}): ${body}`,\n );\n }\n const data = (await res.json()) as { emailAddress: string };\n return data.emailAddress;\n}\n\n/**\n * Start a Google OAuth 2.0 device-authorisation flow.\n *\n * The returned `result` promise resolves once the user has entered the code\n * and consented; callers should poll it (or await it) via `complete_add_account`.\n */\nexport function beginDeviceCode(\n scopes: string[] = DEFAULT_SCOPES,\n clientIdOverride?: string,\n clientSecretOverride?: string,\n): DeviceCodeBegin {\n const clientId = clientIdOverride || process.env.GOOGLE_CLIENT_ID;\n if (!clientId) {\n throw new Error(\n \"GOOGLE_CLIENT_ID is required for Gmail OAuth — set it in env or provider config\",\n );\n }\n const clientSecret =\n clientSecretOverride || process.env.GOOGLE_CLIENT_SECRET || undefined;\n\n let resolve!: (v: { tokens: SerializedGmailTokens; email: string }) => void;\n let reject!: (err: unknown) => void;\n const result = new Promise<{ tokens: SerializedGmailTokens; email: string }>(\n (res, rej) => {\n resolve = res;\n reject = rej;\n },\n );\n\n // Placeholders populated once the device-code HTTP call completes.\n let userCode = \"\";\n let verificationUri = \"\";\n let message = \"\";\n let expiresAt = new Date(Date.now() + 15 * 60_000).toISOString();\n let aborted = false;\n\n const ready = (async () => {\n try {\n // ── Step 1: request device code ──\n const dcParams = new URLSearchParams();\n dcParams.set(\"client_id\", clientId);\n if (clientSecret) dcParams.set(\"client_secret\", clientSecret);\n dcParams.set(\"scope\", scopes.join(\" \"));\n\n const dcRes = await fetch(GOOGLE_DEVICE_CODE_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: dcParams.toString(),\n });\n\n if (!dcRes.ok) {\n const errBody = (await dcRes.json().catch(() => ({}))) as {\n error?: string;\n error_description?: string;\n };\n throw new Error(\n `Google device-code request failed: ` +\n `${errBody.error_description ?? errBody.error ?? dcRes.statusText}`,\n );\n }\n\n const dcData = (await dcRes.json()) as {\n device_code: string;\n user_code: string;\n verification_url: string;\n expires_in: number;\n interval?: number;\n };\n\n userCode = dcData.user_code;\n verificationUri = dcData.verification_url;\n const deviceCode = dcData.device_code;\n let interval = dcData.interval ?? 5;\n if (dcData.expires_in) {\n expiresAt = new Date(\n Date.now() + dcData.expires_in * 1000,\n ).toISOString();\n }\n message = `Go to ${verificationUri} and enter code: ${userCode}`;\n\n // ── Step 2: poll for tokens ──\n const tokenParams = new URLSearchParams();\n tokenParams.set(\"client_id\", clientId);\n if (clientSecret) tokenParams.set(\"client_secret\", clientSecret);\n tokenParams.set(\"device_code\", deviceCode);\n tokenParams.set(\n \"grant_type\",\n \"urn:ietf:params:oauth:grant-type:device_code\",\n );\n\n const deadline = Date.now() + (dcData.expires_in * 1000);\n while (Date.now() < deadline && !aborted) {\n await new Promise((r) => setTimeout(r, interval * 1000));\n if (aborted) return;\n\n const tokenRes = await fetch(GOOGLE_TOKEN_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: tokenParams.toString(),\n });\n\n const tokenData = (await tokenRes.json()) as {\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n scope?: string;\n error?: string;\n };\n\n if (tokenData.access_token) {\n const email = await getEmailFromToken(tokenData.access_token);\n const tokens: SerializedGmailTokens = {\n clientId,\n clientSecret,\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token ?? \"\",\n expiryDate: tokenData.expires_in\n ? Date.now() + tokenData.expires_in * 1000\n : Date.now() + 3600_000,\n scopes: tokenData.scope\n ? tokenData.scope.split(\" \")\n : scopes,\n email,\n };\n resolve({ tokens, email });\n return;\n }\n\n switch (tokenData.error) {\n case \"authorization_pending\":\n break; // keep polling\n case \"slow_down\":\n interval += 1; // Google says to back off\n break;\n case \"expired_token\":\n throw new Error(\"Device code expired — please try again\");\n case \"access_denied\":\n throw new Error(\"User denied access\");\n default:\n throw new Error(\n `Token request failed: ${tokenData.error ?? \"unknown error\"}`,\n );\n }\n }\n\n if (!aborted) {\n throw new Error(\"Device code expired — please try again\");\n }\n } catch (err) {\n if (!aborted) reject(err);\n }\n })();\n\n return {\n get userCode() {\n return userCode;\n },\n get verificationUri() {\n return verificationUri;\n },\n get message() {\n return message;\n },\n get expiresAt() {\n return expiresAt;\n },\n result,\n cancel() {\n aborted = true;\n },\n ...({ _ready: ready } as Record<string, unknown>),\n } as DeviceCodeBegin;\n}\n\n/** Await `_ready` so the user-code fields are populated. */\nexport async function awaitDeviceCodeReady(b: DeviceCodeBegin): Promise<void> {\n const r = (b as unknown as { _ready: Promise<void> })._ready;\n await r;\n}\n\n/**\n * Acquire a fresh access token for a stored account, refreshing silently from\n * the persisted refresh token. Returns the (possibly-updated) tokens so the\n * caller can write them back to the store.\n */\nexport async function acquireAccessToken(\n tokens: SerializedGmailTokens,\n scopes: string[] = DEFAULT_SCOPES,\n): Promise<{ accessToken: string; tokens: SerializedGmailTokens }> {\n const client = buildOAuth2Client(tokens);\n const res = await client.getAccessToken();\n if (!res.token) {\n throw new Error(\n \"Failed to acquire access token — refresh token may be revoked; re-run add_account\",\n );\n }\n\n const creds = client.credentials;\n const next: SerializedGmailTokens = {\n ...tokens,\n accessToken: res.token,\n refreshToken: creds.refresh_token ?? tokens.refreshToken,\n expiryDate: creds.expiry_date ?? Date.now() + 3600_000,\n scopes,\n };\n return { accessToken: res.token, tokens: next };\n}\n\n/**\n * Revoke a refresh token so the stored account is fully de-authorized.\n * Best-effort — failures are swallowed since we'll delete the stored tokens\n * regardless.\n */\nexport async function revokeRefreshToken(\n tokens: SerializedGmailTokens,\n): Promise<void> {\n try {\n await fetch(GOOGLE_OAUTH2_REVOKE_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({ token: tokens.refreshToken }).toString(),\n });\n } catch {\n /* best-effort */\n }\n}\n","import { gmail_v1, google } from \"googleapis\";\n\nimport type { AccountStore, AccountRecord } from \"../../store/account-store.js\";\nimport {\n acquireAccessToken,\n buildOAuth2Client,\n isSerializedGmailTokens,\n type SerializedGmailTokens,\n} from \"./auth.js\";\n\n/**\n * Cached per-account entry: an OAuth2Client + a Gmail API instance.\n * The OAuth2Client handles token refresh automatically; we listen for token\n * events to persist refreshed credentials back to the AccountStore.\n */\ninterface GmailClientEntry {\n auth: ReturnType<typeof buildOAuth2Client>;\n gmail: gmail_v1.Gmail;\n}\n\n/**\n * Builds a Google `gmail_v1.Gmail` client bound to a stored account.\n * The client auto-refreshes access tokens via `google-auth-library` and\n * persists refreshed tokens back into the AccountStore.\n *\n * Clients are cached per email since the underlying library reuses connections.\n */\nexport class GmailClientFactory {\n private readonly cache = new Map<string, GmailClientEntry>();\n /** Serialize token-persist per email to prevent concurrent upsert races. */\n private readonly persistLocks = new Map<string, Promise<void>>();\n\n constructor(\n private readonly store: AccountStore,\n private readonly clientId?: string,\n private readonly clientSecret?: string,\n ) {}\n\n get(account: AccountRecord): GmailClientEntry {\n const key = account.email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) return existing;\n\n if (!isSerializedGmailTokens(account.tokens)) {\n throw new Error(\n \"Gmail account tokens are missing or corrupted — re-run add_account\",\n );\n }\n const tokens: SerializedGmailTokens = account.tokens;\n\n // Use stored clientId/clientSecret, falling back to constructor args\n const resolvedClientId = tokens.clientId || this.clientId;\n const resolvedSecret = tokens.clientSecret || this.clientSecret;\n\n const auth = buildOAuth2Client({\n ...tokens,\n clientId: resolvedClientId ?? tokens.clientId,\n clientSecret: resolvedSecret,\n });\n\n const store = this.store;\n const persistLocks = this.persistLocks;\n auth.on(\"tokens\", (updated) => {\n if (!updated.refresh_token && !updated.access_token) return;\n\n // Serialize persistence per email — two rapid token events can race\n // on the store read-modify-write cycle.\n const existing = persistLocks.get(key);\n const chain = (existing ?? Promise.resolve()).then(async () => {\n const fresh = store.getAccount(account.email) ?? account;\n const currentTokens = isSerializedGmailTokens(fresh.tokens)\n ? (fresh.tokens as unknown as SerializedGmailTokens)\n : tokens;\n\n const nextTokens: SerializedGmailTokens = {\n ...currentTokens,\n accessToken: updated.access_token ?? currentTokens.accessToken,\n refreshToken:\n updated.refresh_token ?? currentTokens.refreshToken,\n expiryDate:\n updated.expiry_date ?? currentTokens.expiryDate,\n scopes: updated.scope\n ? updated.scope.split(\" \")\n : currentTokens.scopes,\n };\n\n await store\n .upsertAccount({\n ...fresh,\n tokens: nextTokens as unknown as Record<string, unknown>,\n })\n .catch(() => {\n /* swallow — next call will refresh again */\n });\n });\n persistLocks.set(key, chain);\n chain.finally(() => {\n if (persistLocks.get(key) === chain) persistLocks.delete(key);\n });\n });\n\n const gmail = google.gmail({ version: \"v1\", auth });\n const entry: GmailClientEntry = { auth, gmail };\n this.cache.set(key, entry);\n return entry;\n }\n\n /** Drop a cached client (e.g. after removeAccount). */\n invalidate(email: string): void {\n this.cache.delete(email.toLowerCase());\n }\n}\n","import { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\n\nimport type { gmail_v1 } from \"googleapis\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AttachmentContent,\n EmailFull,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n EmailAddress,\n} from \"../types.js\";\nimport { GmailClientFactory } from \"./client.js\";\nimport {\n clampLimit,\n findHeader,\n mapHeaderAddr,\n mapSummary,\n mapFolder,\n parsePayload,\n pool,\n resolveLabel,\n type GmailMessageListEntry,\n} from \"./helpers.js\";\n\n/**\n * Browse operations for Gmail — list, search, read emails, attachments,\n * and folders.\n */\n\nexport async function listEmails(\n clients: GmailClientFactory,\n account: AccountRecord,\n opts: ListEmailsOptions,\n): Promise<ListEmailsResult> {\n const { gmail } = clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n const label = resolveLabel(opts.folder ?? \"inbox\");\n\n const params: gmail_v1.Params$Resource$Users$Messages$List = {\n userId: \"me\",\n labelIds: [label],\n maxResults: limit,\n };\n\n if (opts.unreadOnly) {\n params.q = \"is:unread\";\n }\n\n const allIds: GmailMessageListEntry[] = [];\n let pageToken: string | undefined;\n\n do {\n const res = await gmail.users.messages.list({ ...params, pageToken });\n if (res.data.messages) allIds.push(...res.data.messages);\n pageToken = res.data.nextPageToken ?? undefined;\n } while (pageToken && allIds.length < (opts.skip ?? 0) + limit);\n\n const skip = opts.skip ?? 0;\n const pageIds = allIds.slice(skip, skip + limit);\n const hasMore = skip + limit < allIds.length;\n\n if (pageIds.length === 0) {\n return { items: [], hasMore };\n }\n\n const items = await pool(pageIds, 10, async (entry) => {\n const msgId = entry.id ?? \"\";\n const msgRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msgId,\n format: \"metadata\",\n metadataHeaders: [\"From\", \"Subject\", \"To\", \"Date\"],\n });\n const msg = msgRes.data;\n return mapSummary(msgId, msg.payload?.headers ?? [], {\n labelIds: msg.labelIds,\n internalDate: msg.internalDate,\n });\n });\n\n return { items, hasMore };\n}\n\nexport async function searchEmails(\n clients: GmailClientFactory,\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n): Promise<EmailSummary[]> {\n const { gmail } = clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n\n const res = await gmail.users.messages.list({\n userId: \"me\",\n q: query,\n maxResults: limit,\n });\n\n const ids = res.data.messages ?? [];\n if (ids.length === 0) return [];\n\n const items = await pool(ids, 10, async (entry) => {\n const msgId = entry.id ?? \"\";\n const msgRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msgId,\n format: \"metadata\",\n metadataHeaders: [\"From\", \"Subject\", \"To\", \"Date\"],\n });\n const msg = msgRes.data;\n return mapSummary(msgId, msg.payload?.headers ?? [], {\n labelIds: msg.labelIds,\n internalDate: msg.internalDate,\n });\n });\n\n return items;\n}\n\nexport async function readEmail(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n): Promise<EmailFull> {\n const { gmail } = clients.get(account);\n\n const res = await gmail.users.messages.get({\n userId: \"me\",\n id,\n format: \"full\",\n });\n\n const msg = res.data;\n if (!msg) throw new Error(`message not found: ${id}`);\n\n const headers = msg.payload?.headers ?? [];\n const { bodyText, bodyHtml, attachments } = parsePayload(msg.payload ?? {});\n\n const summary = mapSummary(id, headers, {\n labelIds: msg.labelIds,\n internalDate: msg.internalDate,\n });\n\n return {\n ...summary,\n cc: mapHeaderAddr(findHeader(headers, \"Cc\")),\n bcc: mapHeaderAddr(findHeader(headers, \"Bcc\")),\n bodyText,\n bodyHtml,\n attachments: attachments.length > 0 ? attachments : undefined,\n hasAttachments: attachments.length > 0,\n };\n}\n\nexport async function readAttachment(\n clients: GmailClientFactory,\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n): Promise<AttachmentContent> {\n const { gmail } = clients.get(account);\n\n const msgRes = await gmail.users.messages.get({\n userId: \"me\",\n id: messageId,\n format: \"full\",\n });\n const { attachments } = parsePayload(msgRes.data.payload ?? {});\n const match = attachments.find((a) => a.id === attachmentId);\n\n const name = match?.name ?? \"attachment\";\n const contentType = match?.contentType;\n\n const attRes = await gmail.users.messages.attachments.get({\n userId: \"me\",\n messageId,\n id: attachmentId,\n });\n\n const data = attRes.data.data;\n if (!data) throw new Error(\"attachment data is empty\");\n\n const buf = Buffer.from(\n data.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n );\n\n const outPath = pathJoin(tmpdir(), name);\n writeFileSync(outPath, buf);\n\n return { name, contentType, path: outPath };\n}\n\nexport async function listFolders(\n clients: GmailClientFactory,\n account: AccountRecord,\n _opts: ListFoldersOptions,\n): Promise<FolderInfo[]> {\n const { gmail } = clients.get(account);\n const res = await gmail.users.labels.list({ userId: \"me\" });\n const labels = res.data.labels ?? [];\n return labels.map(mapFolder);\n}\n","import type { gmail_v1 } from \"googleapis\";\nimport MailComposer from \"nodemailer/lib/mail-composer/index.js\";\n\nimport { parseInlineImages } from \"../shared/inline-images.js\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AttachmentContent,\n EmailAddress,\n EmailFull,\n EmailSummary,\n FolderInfo,\n SendInput,\n} from \"../types.js\";\n\n// ── well-known folder ↔ Gmail label mapping ──\n\n/** Map a well-known folder name to its Gmail system-label id. */\nconst WELL_KNOWN_TO_LABEL: Record<string, string> = {\n inbox: \"INBOX\",\n sentitems: \"SENT\",\n drafts: \"DRAFT\",\n deleteditems: \"TRASH\",\n junkemail: \"SPAM\",\n outbox: \"\", // Gmail has no outbox; sendEmail handles this.\n};\n\nexport function resolveLabel(wellKnownOrId: string): string {\n const lower = wellKnownOrId.toLowerCase();\n return WELL_KNOWN_TO_LABEL[lower] ?? wellKnownOrId;\n}\n\n/**\n * For \"archive\" we must *remove* the INBOX label rather than add a\n * destination. Other well-known names map normally.\n */\nexport function resolveLabelsForMove(\n destinationId: string,\n): { addLabelIds: string[]; removeLabelIds: string[] } {\n if (destinationId.toLowerCase() === \"archive\") {\n return { addLabelIds: [], removeLabelIds: [\"INBOX\"] };\n }\n return { addLabelIds: [resolveLabel(destinationId)], removeLabelIds: [] };\n}\n\n// ── map Gmail API responses to shared types ──\n\nexport interface GmailMessageListEntry {\n id?: string | null;\n threadId?: string | null;\n}\n\nexport function mapHeaderAddr(\n raw: string | null | undefined,\n): EmailAddress[] {\n if (!raw) return [];\n const addrs = raw.split(\",\");\n return addrs.map((a) => {\n const trimmed = a.trim();\n const match = trimmed.match(/^(.+?)\\s*<(.+@.+)>$/);\n if (match) return { name: match[1]!.trim(), address: match[2]! };\n return { address: trimmed };\n });\n}\n\ntype GmailMessage = gmail_v1.Schema$Message;\ntype GmailMessagePart = gmail_v1.Schema$MessagePart;\n\nexport function findHeader(\n headers: GmailMessagePart[\"headers\"],\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n const h = headers.find(\n (h) => h.name?.toLowerCase() === name.toLowerCase(),\n );\n return h?.value ?? undefined;\n}\n\n/** Decode Gmail's base64url-encoded body part into a UTF-8 string. */\nexport function decodeBody(body: gmail_v1.Schema$MessagePartBody): string {\n if (!body?.data) return \"\";\n return Buffer.from(\n body.data.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n ).toString(\"utf-8\");\n}\n\ninterface ParsedPayload {\n bodyText?: string;\n bodyHtml?: string;\n attachments: NonNullable<EmailFull[\"attachments\"]>;\n}\n\n/** Walk the MIME part tree to extract text, HTML, and attachments. */\nexport function parsePayload(\n payload: GmailMessagePart,\n prefix = \"\",\n): ParsedPayload {\n let bodyText: string | undefined;\n let bodyHtml: string | undefined;\n const attachments: NonNullable<EmailFull[\"attachments\"]> = [];\n\n function walk(part: GmailMessagePart, partPrefix: string): void {\n const mime = part.mimeType ?? \"\";\n\n if (mime === \"text/plain\" && bodyText === undefined) {\n bodyText = decodeBody(part.body ?? {});\n return;\n }\n if (mime === \"text/html\" && bodyHtml === undefined) {\n bodyHtml = decodeBody(part.body ?? {});\n return;\n }\n\n if (part.parts) {\n for (let i = 0; i < part.parts.length; i++) {\n walk(part.parts[i]!, (partPrefix ? `${partPrefix}.` : \"\") + String(i));\n }\n return;\n }\n\n const topType = mime.split(\"/\")[0] ?? \"\";\n const hasFilename = !!part.filename || !!part.body?.attachmentId;\n const isAttachment =\n hasFilename ||\n (!!mime && topType !== \"text\" && topType !== \"multipart\");\n\n if (isAttachment && part.body?.attachmentId) {\n attachments.push({\n id: part.body.attachmentId,\n name: part.filename ?? part.partId ?? \"attachment\",\n contentType: mime || undefined,\n size: part.body.size != null ? Number(part.body.size) : undefined,\n });\n }\n }\n\n walk(payload, prefix);\n return { bodyText, bodyHtml, attachments };\n}\n\nexport function mapSummary(\n id: string,\n headers: GmailMessagePart[\"headers\"],\n flags: { labelIds?: (string | null)[] | null; internalDate?: string | null },\n): EmailSummary {\n return {\n id,\n subject: findHeader(headers, \"Subject\") ?? \"\",\n from: mapHeaderAddr(findHeader(headers, \"From\"))[0],\n to: mapHeaderAddr(findHeader(headers, \"To\")),\n receivedAt: flags.internalDate\n ? new Date(Number(flags.internalDate)).toISOString()\n : undefined,\n preview: undefined,\n isRead: !(flags.labelIds?.includes(\"UNREAD\") ?? false),\n hasAttachments: false,\n };\n}\n\nexport function mapFolder(label: gmail_v1.Schema$Label): FolderInfo {\n return {\n id: label.id ?? \"\",\n displayName: label.name ?? \"\",\n parentFolderId: undefined,\n childFolderCount: 0,\n totalItemCount: label.messagesTotal ?? 0,\n unreadItemCount: label.messagesUnread ?? 0,\n };\n}\n\n// ── limit clamping ──\n\nexport function clampLimit(\n v: number | undefined,\n dflt: number,\n max: number,\n): number {\n if (!v || v <= 0) return dflt;\n return Math.min(v, max);\n}\n\n/** Run an async function over items with limited concurrency. */\nexport async function pool<T, R>(\n items: T[],\n concurrency: number,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = new Array(items.length);\n let idx = 0;\n async function worker(): Promise<void> {\n while (idx < items.length) {\n const i = idx++;\n results[i] = await fn(items[i]!);\n }\n }\n const workers = Array.from(\n { length: Math.min(concurrency, items.length) },\n () => worker(),\n );\n await Promise.all(workers);\n return results;\n}\n\n// ── RFC 2822 message building (reuses nodemailer) ──\n\nexport function base64urlEncode(buf: Buffer): string {\n return buf\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/**\n * Build a raw RFC 2822 message string from send/draft input.\n * Uses nodemailer's MailComposer for MIME construction, then\n * base64url-encodes the result for the Gmail API `raw` field.\n */\nexport async function buildRawMessage(\n account: AccountRecord,\n msg: SendInput,\n messageId?: string,\n): Promise<{ raw: string; threadId?: string }> {\n const { body: transformed, images } = parseInlineImages(msg.body);\n\n const mailOptions: Record<string, unknown> = {\n from: `${account.displayName ?? \"\"} <${account.email}>`,\n to: msg.to\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \"),\n subject: msg.subject,\n attachDataUrls: true,\n };\n\n if (msg.isHtml) {\n mailOptions.html = transformed;\n } else {\n mailOptions.text = transformed;\n }\n\n if (msg.cc && msg.cc.length > 0) {\n mailOptions.cc = msg.cc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n if (msg.bcc && msg.bcc.length > 0) {\n mailOptions.bcc = msg.bcc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n\n if (images.length > 0) {\n mailOptions.attachments = images.map((img) => ({\n filename: img.filename,\n content: Buffer.from(img.contentBytes, \"base64\"),\n contentType: img.contentType,\n cid: img.cid,\n }));\n }\n\n if (messageId) {\n mailOptions.messageId = messageId;\n }\n\n const rawStr = await new Promise<string>((resolve, reject) => {\n const mc = new MailComposer(mailOptions);\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf.toString(\"utf-8\"));\n });\n });\n\n return { raw: base64urlEncode(Buffer.from(rawStr, \"utf-8\")) };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { Buffer } from \"node:buffer\";\n\nimport MailComposer from \"nodemailer/lib/mail-composer/index.js\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n CreateFolderInput,\n DraftUpdateInput,\n EmailAddress,\n FolderInfo,\n SendInput,\n} from \"../types.js\";\nimport {\n GmailClientFactory,\n} from \"./client.js\";\nimport {\n base64urlEncode,\n buildRawMessage,\n mapFolder,\n mapHeaderAddr,\n findHeader,\n resolveLabel,\n resolveLabelsForMove,\n} from \"./helpers.js\";\n\n/**\n * Write operations for Gmail — send, draft, move, mark, folders.\n */\n\nexport async function sendEmail(\n clients: GmailClientFactory,\n account: AccountRecord,\n msg: SendInput,\n): Promise<{ id: string }> {\n const { gmail } = clients.get(account);\n\n let threadId: string | undefined;\n let rawBody: { raw: string };\n\n if (msg.forwardMessageId) {\n const fwdRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msg.forwardMessageId,\n format: \"raw\",\n });\n threadId = fwdRes.data.threadId ?? undefined;\n const fwdRaw = fwdRes.data.raw;\n if (fwdRaw) {\n const fwdStr = Buffer.from(\n fwdRaw.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n ).toString(\"utf-8\");\n\n const divider =\n '\\n\\n<div style=\"line-height:12px\"><br></div>\\n\\n' +\n '<div style=\"border-left:2px solid #ccc; padding-left:8px; ' +\n 'margin-left:0; color:#666\">\\n' +\n \"---------- Forwarded message ---------<br>\" +\n fwdStr +\n \"\\n</div>\";\n\n const combinedMsg = { ...msg, body: msg.body + divider };\n rawBody = await buildRawMessage(account, combinedMsg);\n } else {\n rawBody = await buildRawMessage(account, msg);\n }\n } else {\n rawBody = await buildRawMessage(account, msg);\n\n if (msg.inReplyTo) {\n try {\n const refRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msg.inReplyTo,\n format: \"minimal\",\n });\n threadId = refRes.data.threadId ?? undefined;\n } catch {\n /* proceed without threading */\n }\n }\n }\n\n const sendRes = await gmail.users.messages.send({\n userId: \"me\",\n requestBody: {\n raw: rawBody.raw,\n threadId,\n },\n });\n\n return { id: sendRes.data.id ?? \"\" };\n}\n\nexport async function saveDraft(\n clients: GmailClientFactory,\n account: AccountRecord,\n msg: SendInput,\n): Promise<{ id: string }> {\n const { gmail } = clients.get(account);\n const { raw } = await buildRawMessage(account, msg);\n\n let threadId: string | undefined;\n if (msg.inReplyTo) {\n try {\n const refRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msg.inReplyTo,\n format: \"minimal\",\n });\n threadId = refRes.data.threadId ?? undefined;\n } catch {\n /* proceed without threading */\n }\n }\n\n const draftRes = await gmail.users.drafts.create({\n userId: \"me\",\n requestBody: {\n message: { raw, threadId },\n },\n });\n\n return { id: draftRes.data.message?.id ?? draftRes.data.id ?? \"\" };\n}\n\nexport async function updateDraft(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n update: DraftUpdateInput,\n): Promise<{ id: string }> {\n const { gmail } = clients.get(account);\n\n const draftRes = await gmail.users.drafts.get({\n userId: \"me\",\n id,\n format: \"raw\",\n });\n\n const existingMessage = draftRes.data.message;\n if (!existingMessage?.raw) {\n throw new Error(`draft not found: ${id}`);\n }\n\n const existingHeaders = existingMessage.payload?.headers ?? [];\n const origSubject = findHeader(existingHeaders, \"Subject\") ?? \"\";\n\n const rawStr = Buffer.from(\n existingMessage.raw.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n ).toString(\"utf-8\");\n\n // Extract existing To/CC recipients from headers\n const existingTo = update.to ?? mapHeaderAddr(findHeader(existingHeaders, \"To\"));\n const existingCc = update.cc ?? mapHeaderAddr(findHeader(existingHeaders, \"Cc\"));\n const existingBcc = update.bcc ?? mapHeaderAddr(findHeader(existingHeaders, \"Bcc\"));\n\n const { raw } = await buildRawMessage(account, {\n to: existingTo,\n subject: update.subject ?? origSubject,\n body: update.body ?? \"\",\n isHtml: update.isHtml,\n cc: existingCc.length > 0 ? existingCc : undefined,\n bcc: existingBcc.length > 0 ? existingBcc : undefined,\n });\n\n const updated = await gmail.users.drafts.update({\n userId: \"me\",\n id,\n requestBody: {\n message: {\n raw,\n threadId: existingMessage.threadId ?? undefined,\n },\n },\n });\n\n return { id: updated.data.message?.id ?? updated.data.id ?? id };\n}\n\nexport async function moveEmail(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n destinationId: string,\n): Promise<void> {\n const { gmail } = clients.get(account);\n const { addLabelIds, removeLabelIds } =\n resolveLabelsForMove(destinationId);\n\n await gmail.users.messages.modify({\n userId: \"me\",\n id,\n requestBody: { addLabelIds, removeLabelIds },\n });\n}\n\nexport async function sendDraft(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n): Promise<{ id: string }> {\n const { gmail } = clients.get(account);\n const res = await gmail.users.drafts.send({\n userId: \"me\",\n requestBody: { id },\n });\n return { id: res.data.id ?? id };\n}\n\nexport async function addAttachmentToDraft(\n clients: GmailClientFactory,\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n): Promise<{\n id: string;\n attachment: { id: string; name: string; contentType?: string };\n}> {\n const { gmail } = clients.get(account);\n\n const draftRes = await gmail.users.drafts.get({\n userId: \"me\",\n id: draftId,\n format: \"raw\",\n });\n\n const existingMessage = draftRes.data.message;\n if (!existingMessage?.raw) {\n throw new Error(`draft not found: ${draftId}`);\n }\n\n const rawStr = Buffer.from(\n existingMessage.raw.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n ).toString(\"utf-8\");\n\n const newRawStr = await new Promise<string>((resolve, reject) => {\n const mc = new MailComposer({\n raw: rawStr,\n attachments: [\n {\n filename: name,\n content: Buffer.from(contentBytes, \"base64\"),\n contentType: contentType ?? \"application/octet-stream\",\n },\n ],\n });\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf.toString(\"utf-8\"));\n });\n });\n\n const updated = await gmail.users.drafts.update({\n userId: \"me\",\n id: draftId,\n requestBody: {\n message: {\n raw: base64urlEncode(Buffer.from(newRawStr, \"utf-8\")),\n threadId: existingMessage.threadId ?? undefined,\n },\n },\n });\n\n return {\n id: updated.data.message?.id ?? updated.data.id ?? draftId,\n attachment: {\n id: randomUUID(),\n name,\n contentType: contentType ?? \"application/octet-stream\",\n },\n };\n}\n\nexport async function markRead(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n isRead: boolean,\n): Promise<void> {\n const { gmail } = clients.get(account);\n await gmail.users.messages.modify({\n userId: \"me\",\n id,\n requestBody: {\n removeLabelIds: isRead ? [\"UNREAD\"] : undefined,\n addLabelIds: isRead ? undefined : [\"UNREAD\"],\n },\n });\n}\n\nexport async function createFolder(\n clients: GmailClientFactory,\n account: AccountRecord,\n input: CreateFolderInput,\n): Promise<FolderInfo> {\n const { gmail } = clients.get(account);\n const created = await gmail.users.labels.create({\n userId: \"me\",\n requestBody: {\n name: input.displayName,\n messageListVisibility: \"show\",\n labelListVisibility: \"labelShow\",\n },\n });\n return mapFolder(created.data);\n}\n\nexport async function renameFolder(\n clients: GmailClientFactory,\n account: AccountRecord,\n folderId: string,\n newName: string,\n): Promise<FolderInfo> {\n const { gmail } = clients.get(account);\n const updated = await gmail.users.labels.patch({\n userId: \"me\",\n id: folderId,\n requestBody: { name: newName },\n });\n return mapFolder(updated.data);\n}\n\nexport async function deleteFolder(\n clients: GmailClientFactory,\n account: AccountRecord,\n folderId: string,\n): Promise<void> {\n const { gmail } = clients.get(account);\n await gmail.users.labels.delete({\n userId: \"me\",\n id: folderId,\n });\n}\n","import type { AccountStore, AccountRecord } from \"../store/account-store.js\";\nimport type { EmailProvider, ProviderId } from \"./types.js\";\nimport type { ProvidersConfig } from \"../config.js\";\nimport { OutlookProvider } from \"./outlook/index.js\";\nimport { ImapProvider } from \"./imap/index.js\";\nimport { GmailProvider } from \"./gmail/index.js\";\n\nexport interface Registry {\n get(id: ProviderId): EmailProvider;\n resolveByEmail(email: string): { provider: EmailProvider; account: AccountRecord };\n list(): EmailProvider[];\n}\n\nexport interface BuildRegistryOptions {\n store: AccountStore;\n providers?: ProvidersConfig;\n}\n\nexport function buildRegistry(opts: BuildRegistryOptions): Registry {\n const outlookCfg = opts.providers?.outlook;\n const providers = new Map<ProviderId, EmailProvider>();\n providers.set(\"outlook\", new OutlookProvider({\n store: opts.store,\n clientId: outlookCfg?.clientId,\n tenantId: outlookCfg?.tenantId,\n }));\n providers.set(\"imap\", new ImapProvider(opts.store));\n const gmailCfg = opts.providers?.gmail;\n providers.set(\"gmail\", new GmailProvider({\n store: opts.store,\n clientId: gmailCfg?.clientId,\n clientSecret: gmailCfg?.clientSecret,\n }));\n\n function get(id: ProviderId): EmailProvider {\n const p = providers.get(id);\n if (!p) throw new Error(`unknown provider: ${id}`);\n return p;\n }\n\n function resolveByEmail(email: string): {\n provider: EmailProvider;\n account: AccountRecord;\n } {\n const account = opts.store.getAccount(email);\n if (!account) {\n throw new Error(\n `no account registered for \"${email}\". Call add_account first.`,\n );\n }\n return { provider: get(account.provider), account };\n }\n\n return {\n get,\n resolveByEmail,\n list: () => Array.from(providers.values()),\n };\n}\n","import { z } from \"zod\";\nimport type { ResolvedTools } from \"../config.js\";\nimport { markdownToHtml } from \"../markdown-to-html.js\";\n\n/** JSON-stringify a value into a single MCP text content block. */\nexport function ok(\n data: unknown,\n structuredContent?: Record<string, unknown>,\n) {\n const result: {\n content: Array<{ type: \"text\"; text: string }>;\n structuredContent?: Record<string, unknown>;\n } = {\n content: [{ type: \"text\" as const, text: JSON.stringify(data, null, 2) }],\n };\n if (structuredContent !== undefined) {\n result.structuredContent = structuredContent;\n }\n return result;\n}\n\nexport function fail(message: string) {\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: message }],\n };\n}\n\nexport function errMsg(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\n// ── shared schemas ──\n\n/** Enum matching {@link import(\"../providers/types.js\").ProviderId}. */\nexport const providerIdEnum = z.enum([\"outlook\", \"imap\", \"gmail\"]);\n\nexport const emailAddrSchema = z.object({\n address: z.string().email(),\n name: z.string().optional(),\n});\n\nexport const emailAddrOutputSchema = z.object({\n name: z.string().optional(),\n address: z.string(),\n});\n\nexport const accountSummaryOutputSchema = z.object({\n email: z.string(),\n provider: providerIdEnum,\n displayName: z.string().optional(),\n addedAt: z.string(),\n hasSignature: z.boolean(),\n hasStyle: z.boolean(),\n});\n\nexport const styleOutputSchema = z.object({\n fontFamily: z.string().optional(),\n fontSize: z.string().optional(),\n fontColor: z.string().optional(),\n});\n\n/** Full account record including tokens, signature, and style. */\nexport const accountFullOutputSchema = z.object({\n email: z.string(),\n provider: providerIdEnum,\n displayName: z.string().optional(),\n tokens: z.record(z.string(), z.unknown()),\n addedAt: z.string(),\n signature: z.string().optional(),\n style: styleOutputSchema.optional(),\n});\n\nexport const emailSummaryOutputSchema = z.object({\n id: z.string(),\n subject: z.string(),\n from: emailAddrOutputSchema.optional(),\n to: z.array(emailAddrOutputSchema).optional(),\n receivedAt: z.string().optional(),\n preview: z.string().optional(),\n isRead: z.boolean().optional(),\n hasAttachments: z.boolean().optional(),\n folder: z.string().optional(),\n});\n\nexport const attachmentMetaOutputSchema = z.object({\n id: z.string(),\n name: z.string(),\n contentType: z.string().optional(),\n size: z.number().optional(),\n});\n\nexport const folderInfoOutputSchema = z.object({\n id: z.string(),\n displayName: z.string(),\n parentFolderId: z.string().optional(),\n childFolderCount: z.number(),\n totalItemCount: z.number(),\n unreadItemCount: z.number(),\n});\n\n// ── body composition helpers ──\n\nexport interface ComposeBodyInput {\n body: string;\n format: \"html\" | \"markdown\";\n signature?: string;\n style?: { fontFamily?: string; fontSize?: string; fontColor?: string };\n includeSignature: boolean;\n}\n\nexport function composeBody(\n input: ComposeBodyInput,\n): { body: string; isHtml: boolean } {\n const { body, format, signature, style, includeSignature } = input;\n\n // Convert markdown to HTML first, then proceed as HTML\n const htmlBody = format === \"markdown\" ? markdownToHtml(body) : body;\n\n const hasSignature = includeSignature && !!signature;\n const hasStyle = !!(\n style &&\n (style.fontFamily || style.fontSize || style.fontColor)\n );\n\n if (!hasSignature && !hasStyle) {\n return { body: htmlBody, isHtml: true };\n }\n\n const styleAttr = hasStyle ? buildStyleAttr(style!) : \"\";\n let result = hasStyle\n ? `<div style=\"${styleAttr}\">${htmlBody}</div>`\n : htmlBody;\n if (hasSignature) result += `\\n<div class=\"signature\">${signature}</div>`;\n return { body: result, isHtml: true };\n}\n\nexport function buildStyleAttr(style: {\n fontFamily?: string;\n fontSize?: string;\n fontColor?: string;\n}): string {\n const parts: string[] = [];\n if (style.fontFamily) parts.push(`font-family: ${style.fontFamily}`);\n if (style.fontSize) parts.push(`font-size: ${style.fontSize}`);\n if (style.fontColor) parts.push(`color: ${style.fontColor}`);\n return parts.join(\"; \");\n}\n\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/\\n/g, \"<br>\");\n}\n\n// ── tool filtering ──\n\n/** Returns true when `name` should be registered given the tool filtering config. */\nexport function shouldRegister(\n name: string,\n tools: ResolvedTools,\n): boolean {\n if (tools.enabledTools) {\n return tools.enabledTools.has(name);\n }\n if (tools.disabledTools) {\n return !tools.disabledTools.has(name);\n }\n return true;\n}\n","import { marked } from \"marked\";\n\n/** Convert Markdown string to HTML. */\nexport function markdownToHtml(md: string): string {\n return marked.parse(md, { async: false }) as string;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { promises as fs } from \"node:fs\";\nimport { z } from \"zod\";\n\nimport type { AccountStore } from \"../store/account-store.js\";\nimport type { AgentStore } from \"../store/agent-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ProviderId } from \"../providers/types.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport {\n checkAccountAccess,\n checkProvisioning,\n} from \"./agent-context.js\";\nimport {\n ok,\n fail,\n errMsg,\n providerIdEnum,\n accountSummaryOutputSchema,\n accountFullOutputSchema,\n styleOutputSchema,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerAccountTools(\n server: McpServer,\n ctx: {\n store: AccountStore;\n agentStore?: AgentStore;\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { store, registry, tools, agentContext, agentStore } = ctx;\n\n // ---------- list_accounts ----------\n\n const listAccountsOutputSchema = z.object({\n accounts: z.array(accountSummaryOutputSchema),\n });\n\n if (shouldRegister(\"list_accounts\", tools)) {\n server.registerTool(\n \"list_accounts\",\n {\n description:\n \"List all email accounts known to this server (no secrets). \" +\n \"Use the returned `email` value as the `account` argument to other tools.\",\n inputSchema: z.object({}),\n outputSchema: listAccountsOutputSchema,\n },\n async () => {\n const rows = store.listAccounts().map((a) => ({\n email: a.email,\n provider: a.provider,\n displayName: a.displayName,\n addedAt: a.addedAt,\n hasSignature: !!a.signature,\n hasStyle: !!(\n a.style &&\n (a.style.fontFamily || a.style.fontSize || a.style.fontColor)\n ),\n }));\n const data = { accounts: rows };\n return ok(data, data);\n },\n );\n }\n\n // ---------- add_account ----------\n\n const addAccountOutputSchema = z.object({\n status: z.enum([\"pending\", \"ready\"]),\n handle: z.string().optional(),\n verification: z\n .object({\n userCode: z.string(),\n verificationUri: z.string(),\n expiresAt: z.string(),\n message: z.string(),\n })\n .optional(),\n account: accountFullOutputSchema.optional(),\n });\n\n if (shouldRegister(\"add_account\", tools)) {\n server.registerTool(\n \"add_account\",\n {\n description:\n \"Start adding an email account. For Outlook this returns a device code \" +\n \"the user must enter at the verification URL; then call `complete_add_account` \" +\n \"with the returned `handle` to finalize. Disabled in --read-only mode.\",\n inputSchema: z.object({\n provider: providerIdEnum.describe(\"Email backend. 'outlook' (Microsoft Graph) and 'imap' are fully implemented.\"),\n email: z\n .string()\n .email()\n .optional()\n .describe(\n \"Optional hint — the provider will verify it against the auth result.\",\n ),\n config: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"Provider-specific config (e.g. IMAP host/port). Unused for Outlook.\",\n ),\n }),\n outputSchema: addAccountOutputSchema,\n },\n async (args) => {\n const permErr = checkProvisioning(agentContext ?? null);\n if (permErr) return fail(permErr);\n const provider = registry.get(args.provider as ProviderId);\n try {\n const res = await provider.addAccount({\n email: args.email,\n config: args.config,\n });\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- complete_add_account ----------\n\n const completeAddAccountOutputSchema = z.object({\n status: z.enum([\"pending\", \"ready\", \"expired\", \"error\"]),\n account: accountFullOutputSchema.optional(),\n error: z.string().optional(),\n });\n\n if (shouldRegister(\"complete_add_account\", tools)) {\n server.registerTool(\n \"complete_add_account\",\n {\n description:\n \"Poll/finalize a pending add_account flow. Returns `pending` until the user \" +\n \"completes the device-code step, then `ready` with the persisted account.\",\n inputSchema: z.object({\n provider: providerIdEnum,\n handle: z.string().min(1),\n }),\n outputSchema: completeAddAccountOutputSchema,\n },\n async (args) => {\n const permErr = checkProvisioning(agentContext ?? null);\n if (permErr) return fail(permErr);\n const provider = registry.get(args.provider as ProviderId);\n if (!provider.completeAddAccount) {\n return fail(\n `provider ${args.provider} has no async add-account flow`,\n );\n }\n try {\n const res = await provider.completeAddAccount(args.handle);\n // Auto-assign the newly provisioned account to the calling agent.\n if (res.status === \"ready\" && res.account && agentContext && agentStore) {\n agentStore\n .assignAccount(agentContext.agentId, res.account.email)\n .catch(() => {\n /* best-effort — account is provisioned either way */\n });\n }\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- account settings ----------\n\n const accountSettingsOutputSchema = z.object({\n signature: z.string().nullable(),\n style: styleOutputSchema.nullable(),\n });\n\n if (shouldRegister(\"get_account_settings\", tools)) {\n server.registerTool(\n \"get_account_settings\",\n {\n description:\n \"Get signature (HTML) and style preferences for an account.\",\n inputSchema: z.object({ account: z.string().email() }),\n outputSchema: accountSettingsOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const acct = store.getAccount(args.account);\n if (!acct)\n return fail(`no account registered for \"${args.account}\"`);\n const data = {\n signature: acct.signature ?? null,\n style: acct.style ?? null,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n if (shouldRegister(\"set_account_settings\", tools)) {\n server.registerTool(\n \"set_account_settings\",\n {\n description:\n \"Set signature (HTML snippet) and/or style preferences for an account. \" +\n \"Use `signaturePath` to load a signature from a file (useful for signatures with base64 images). \" +\n \"`signature` and `signaturePath` are mutually exclusive. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: z\n .object({\n account: z.string().email(),\n signature: z\n .string()\n .optional()\n .describe(\n \"HTML snippet — may contain formatting, images, links. \" +\n \"Pass an empty string to clear. \" +\n \"Mutually exclusive with `signaturePath`.\",\n ),\n signaturePath: z\n .string()\n .optional()\n .describe(\n \"Path to a file containing the signature HTML. \" +\n \"The file content is read and stored as the signature. \" +\n \"Useful when the signature contains large base64 images. \" +\n \"Mutually exclusive with `signature`.\",\n ),\n style: z\n .object({\n fontFamily: z.string().optional(),\n fontSize: z.string().optional(),\n fontColor: z.string().optional(),\n })\n .optional()\n .describe(\n \"Font preferences applied to outgoing HTML emails. Pass null to clear.\",\n ),\n })\n .refine(\n (data) => !(data.signature !== undefined && data.signaturePath),\n {\n message:\n \"signature and signaturePath are mutually exclusive — use one or the other\",\n },\n ),\n outputSchema: accountSettingsOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const acct = store.getAccount(args.account);\n if (!acct)\n return fail(`no account registered for \"${args.account}\"`);\n let resolvedSignature: string | undefined = acct.signature;\n if (args.signaturePath) {\n resolvedSignature = await fs.readFile(args.signaturePath, \"utf-8\");\n } else if (args.signature !== undefined) {\n resolvedSignature = args.signature || undefined;\n }\n const updated = await store.upsertAccount({\n ...acct,\n signature: resolvedSignature,\n style: args.style ?? acct.style,\n });\n const data = {\n signature: updated.signature ?? null,\n style: updated.style ?? null,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- remove_account ----------\n\n const removeAccountOutputSchema = z.object({\n removed: z.boolean(),\n email: z.string(),\n });\n\n if (shouldRegister(\"remove_account\", tools)) {\n server.registerTool(\n \"remove_account\",\n {\n description:\n \"Forget an account and delete its stored tokens. Disabled in --read-only mode.\",\n inputSchema: z.object({ email: z.string().email() }),\n outputSchema: removeAccountOutputSchema,\n },\n async (args) => {\n const permErr = checkProvisioning(agentContext ?? null);\n if (permErr) return fail(permErr);\n const removed = await store.removeAccount(args.email);\n const data = { removed, email: args.email };\n return ok(data, data);\n },\n );\n }\n}\n","/**\n * Agent identity carried through the tool pipeline in HTTP multi-tenant mode.\n * In stdio mode this is `null` (unrestricted access).\n */\nexport interface AgentContext {\n /** Human-readable agent id from agents.yaml. */\n agentId: string;\n /** Email addresses this agent is authorized to access. */\n accounts: string[];\n /** Whether this agent can provision/remove accounts. */\n provisioning: boolean;\n}\n\n/**\n * Check that an agent is authorized to operate on the given email account.\n * In stdio mode (agentContext is null), access is unrestricted.\n *\n * Returns an error message string if denied, or `null` if allowed.\n */\nexport function checkAccountAccess(\n agentContext: AgentContext | null,\n accountEmail: string,\n): string | null {\n if (!agentContext) return null; // stdio mode — unrestricted\n const norm = accountEmail.trim().toLowerCase();\n if (agentContext.accounts.some((a) => a.toLowerCase() === norm)) {\n return null;\n }\n return `Agent \"${agentContext.agentId}\" is not authorized for account \"${accountEmail}\"`;\n}\n\n/**\n * Check that an agent has provisioning permission.\n * In stdio mode (agentContext is null), provisioning is unrestricted.\n *\n * Returns an error message string if denied, or `null` if allowed.\n */\nexport function checkProvisioning(\n agentContext: AgentContext | null,\n): string | null {\n if (!agentContext) return null; // stdio mode — unrestricted\n if (agentContext.provisioning) return null;\n return `Agent \"${agentContext.agentId}\" does not have provisioning permission`;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { checkAccountAccess } from \"./agent-context.js\";\nimport { selectBody } from \"../html-to-markdown.js\";\nimport {\n ok,\n fail,\n errMsg,\n emailAddrOutputSchema,\n emailSummaryOutputSchema,\n attachmentMetaOutputSchema,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerBrowseTools(\n server: McpServer,\n ctx: {\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { registry, tools, agentContext } = ctx;\n\n // ---------- email ops ----------\n\n const emailListOutputSchema = z.object({\n account: z.string(),\n count: z.number(),\n items: z.array(emailSummaryOutputSchema),\n skip: z.number(),\n hasMore: z.boolean(),\n });\n\n const searchEmailsOutputSchema = z.object({\n account: z.string(),\n count: z.number(),\n items: z.array(emailSummaryOutputSchema),\n });\n\n if (shouldRegister(\"list_emails\", tools)) {\n server.registerTool(\n \"list_emails\",\n {\n description:\n \"List recent emails in a folder of the given account. Pass the user's email \" +\n \"address as `account`; the server routes to the correct backend automatically.\",\n inputSchema: z.object({\n account: z.string().email(),\n folder: z.string().default(\"inbox\").optional(),\n limit: z.number().int().positive().max(100).optional(),\n unreadOnly: z.boolean().optional(),\n skip: z.number().int().min(0).optional(),\n }),\n outputSchema: emailListOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const { items, hasMore } = await provider.listEmails(account, {\n folder: args.folder,\n limit: args.limit,\n unreadOnly: args.unreadOnly,\n skip: args.skip,\n });\n const data = {\n account: account.email,\n count: items.length,\n items,\n skip: args.skip ?? 0,\n hasMore,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n if (shouldRegister(\"search_emails\", tools)) {\n server.registerTool(\n \"search_emails\",\n {\n description:\n \"Search emails by free-text query (KQL on Outlook). Returns lightweight summaries.\",\n inputSchema: z.object({\n account: z.string().email(),\n query: z.string().min(1),\n limit: z.number().int().positive().max(100).optional(),\n }),\n outputSchema: searchEmailsOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const items = await provider.searchEmails(account, args.query, {\n limit: args.limit,\n });\n const data = {\n account: account.email,\n count: items.length,\n items,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n const readEmailOutputSchema = z.object({\n id: z.string(),\n subject: z.string(),\n from: emailAddrOutputSchema.optional(),\n to: z.array(emailAddrOutputSchema).optional(),\n cc: z.array(emailAddrOutputSchema).optional(),\n bcc: z.array(emailAddrOutputSchema).optional(),\n receivedAt: z.string().optional(),\n preview: z.string().optional(),\n isRead: z.boolean().optional(),\n hasAttachments: z.boolean().optional(),\n folder: z.string().optional(),\n attachments: z.array(attachmentMetaOutputSchema).optional(),\n body: z.string(),\n bodyFormat: z.enum([\"markdown\", \"html\", \"text\"]),\n });\n\n if (shouldRegister(\"read_email\", tools)) {\n server.registerTool(\n \"read_email\",\n {\n description:\n \"Fetch a single email with full body and recipients by id. \" +\n \"Body is returned as `body` with `bodyFormat` indicating the format. \" +\n \"Default format is 'markdown' — HTML is automatically converted to save context tokens.\",\n inputSchema: z.object({\n account: z.string().email(),\n id: z.string().min(1),\n format: z\n .enum([\"markdown\", \"html\", \"text\"])\n .default(\"markdown\")\n .optional()\n .describe(\n \"Output body format. 'markdown' converts HTML to Markdown (default), \" +\n \"'html' returns the raw HTML, 'text' returns plain text.\",\n ),\n }),\n outputSchema: readEmailOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const msg = await provider.readEmail(account, args.id);\n const format = args.format ?? \"markdown\";\n const body = selectBody(msg, format);\n const data = {\n id: msg.id,\n subject: msg.subject,\n from: msg.from,\n to: msg.to,\n cc: msg.cc,\n bcc: msg.bcc,\n receivedAt: msg.receivedAt,\n preview: msg.preview,\n isRead: msg.isRead,\n hasAttachments: msg.hasAttachments,\n folder: msg.folder,\n attachments: msg.attachments,\n body,\n bodyFormat: format,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n const readAttachmentOutputSchema = z.object({\n name: z.string(),\n contentType: z.string().optional(),\n path: z.string(),\n });\n\n if (shouldRegister(\"read_attachment\", tools)) {\n server.registerTool(\n \"read_attachment\",\n {\n description:\n \"Download an email attachment to a temporary file and return its path. \" +\n \"Use messageId and attachmentId from a prior read_email call.\",\n inputSchema: z.object({\n account: z.string().email(),\n messageId: z.string().min(1),\n attachmentId: z.string().min(1),\n }),\n outputSchema: readAttachmentOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.readAttachment(\n account,\n args.messageId,\n args.attachmentId,\n );\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import TurndownService from \"turndown\";\n\nconst turndown = new TurndownService();\n\n/** Light wrapper — callers just pass HTML, get markdown back. */\nexport function htmlToMarkdown(html: string): string {\n return turndown.turndown(html);\n}\n\n/** Pick the right body for the requested format. */\nexport function selectBody(\n msg: { bodyHtml?: string; bodyText?: string },\n format: \"markdown\" | \"html\" | \"text\",\n): string {\n switch (format) {\n case \"markdown\": {\n if (msg.bodyHtml) return htmlToMarkdown(msg.bodyHtml);\n if (msg.bodyText) return msg.bodyText;\n return \"\";\n }\n case \"html\": {\n if (msg.bodyHtml) return msg.bodyHtml;\n if (msg.bodyText) return msg.bodyText;\n return \"\";\n }\n case \"text\": {\n if (msg.bodyText) return msg.bodyText;\n if (msg.bodyHtml) return msg.bodyHtml.replace(/<[^>]*>/g, \"\");\n return \"\";\n }\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { checkAccountAccess } from \"./agent-context.js\";\nimport {\n ok,\n fail,\n errMsg,\n folderInfoOutputSchema,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerFolderTools(\n server: McpServer,\n ctx: {\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { registry, tools, agentContext } = ctx;\n\n // ---------- list_folders ----------\n\n const listFoldersOutputSchema = z.object({\n account: z.string(),\n count: z.number(),\n items: z.array(folderInfoOutputSchema),\n });\n\n if (shouldRegister(\"list_folders\", tools)) {\n server.registerTool(\n \"list_folders\",\n {\n description:\n \"List available mail folders. Returns top-level folders by default, \" +\n \"or child folders of the given parent when `parentFolderId` is provided.\",\n inputSchema: z.object({\n account: z.string().email(),\n parentFolderId: z\n .string()\n .optional()\n .describe(\n \"When provided, lists child folders of this folder. \" +\n \"When omitted, lists top-level folders (children of the root).\",\n ),\n }),\n outputSchema: listFoldersOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const items = await provider.listFolders(account, {\n parentFolderId: args.parentFolderId,\n });\n const data = {\n account: account.email,\n count: items.length,\n items,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- create_folder ----------\n\n const createFolderOutputSchema = z.object({\n created: z.literal(true),\n folder: folderInfoOutputSchema,\n });\n\n if (shouldRegister(\"create_folder\", tools)) {\n server.registerTool(\n \"create_folder\",\n {\n description:\n \"Create a new mail folder. Creates under the root folder by default, \" +\n \"or under the specified parent when `parentFolderId` is provided. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: z.object({\n account: z.string().email(),\n displayName: z\n .string()\n .min(1)\n .describe(\"Name of the new folder\"),\n parentFolderId: z\n .string()\n .optional()\n .describe(\n \"When provided, creates the folder as a child of this folder. \" +\n \"When omitted, creates under the root folder.\",\n ),\n }),\n outputSchema: createFolderOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const folder = await provider.createFolder(account, {\n displayName: args.displayName,\n parentFolderId: args.parentFolderId,\n });\n const data = { created: true as const, folder };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- delete_folder ----------\n\n const deleteFolderOutputSchema = z.object({\n deleted: z.literal(true),\n id: z.string(),\n });\n\n if (shouldRegister(\"delete_folder\", tools)) {\n server.registerTool(\n \"delete_folder\",\n {\n description:\n \"Delete a mail folder by ID. Disabled in --read-only mode.\",\n inputSchema: z.object({\n account: z.string().email(),\n folderId: z\n .string()\n .min(1)\n .describe(\"ID of the folder to delete\"),\n }),\n outputSchema: deleteFolderOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.deleteFolder(account, args.folderId);\n const data = { deleted: true as const, id: args.folderId };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- rename_folder ----------\n\n const renameFolderOutputSchema = z.object({\n renamed: z.literal(true),\n folder: folderInfoOutputSchema,\n });\n\n if (shouldRegister(\"rename_folder\", tools)) {\n server.registerTool(\n \"rename_folder\",\n {\n description:\n \"Rename an existing mail folder. Disabled in --read-only mode.\",\n inputSchema: z.object({\n account: z.string().email(),\n folderId: z\n .string()\n .min(1)\n .describe(\"ID of the folder to rename\"),\n newName: z\n .string()\n .min(1)\n .describe(\"New display name for the folder\"),\n }),\n outputSchema: renameFolderOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const folder = await provider.renameFolder(\n account,\n args.folderId,\n args.newName,\n );\n const data = { renamed: true as const, folder };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { checkAccountAccess } from \"./agent-context.js\";\nimport { ok, fail, errMsg, shouldRegister } from \"./shared.js\";\n\nexport function registerOrganizeTools(\n server: McpServer,\n ctx: {\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { registry, tools, agentContext } = ctx;\n\n // Shared helpers — extract the resolved-account lookup and error handling\n // so archive/trash/mark_read/mark_unread handlers stay minimal.\n\n async function moveToWellKnown(\n args: { account: string; id: string },\n destination: string,\n resultKey: string,\n ) {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, destination);\n const data: Record<string, unknown> = { id: args.id };\n data[resultKey] = true;\n return ok(data, data);\n }\n\n async function markReadState(\n args: { account: string; id: string },\n isRead: boolean,\n ) {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.markRead(account, args.id, isRead);\n const data = { marked: true as const, id: args.id, isRead };\n return ok(data, data);\n }\n\n // ---------- archive ----------\n\n const archiveMoveSchema = z.object({\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to move\"),\n });\n\n const archiveOutputSchema = z.object({\n archived: z.literal(true),\n id: z.string(),\n });\n\n if (shouldRegister(\"archive_email\", tools)) {\n server.registerTool(\n \"archive_email\",\n {\n description:\n \"Move a message to the Archive folder. Disabled in --read-only mode.\",\n inputSchema: archiveMoveSchema,\n outputSchema: archiveOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n return await moveToWellKnown(args, \"archive\", \"archived\");\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- trash ----------\n\n const trashOutputSchema = z.object({\n trashed: z.literal(true),\n id: z.string(),\n });\n\n if (shouldRegister(\"trash_email\", tools)) {\n server.registerTool(\n \"trash_email\",\n {\n description:\n \"Move a message to the Deleted Items (trash) folder. Disabled in --read-only mode.\",\n inputSchema: archiveMoveSchema,\n outputSchema: trashOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n return await moveToWellKnown(args, \"deleteditems\", \"trashed\");\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- move ----------\n\n const moveEmailOutputSchema = z.object({\n moved: z.literal(true),\n id: z.string(),\n destination: z.string(),\n });\n\n if (shouldRegister(\"move_email\", tools)) {\n server.registerTool(\n \"move_email\",\n {\n description:\n \"Move a message to any folder by well-known name (e.g. 'inbox', 'drafts', \" +\n \"'junkemail', 'sentitems', 'outbox') or custom folder ID. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: z.object({\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to move\"),\n destination: z\n .string()\n .min(1)\n .describe(\n \"Destination folder — a well-known folder name \" +\n \"('archive', 'deleteditems', 'inbox', 'drafts', 'junkemail', \" +\n \"'sentitems', 'outbox') or a raw folder ID.\",\n ),\n }),\n outputSchema: moveEmailOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, args.destination);\n const data = {\n moved: true as const,\n id: args.id,\n destination: args.destination,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- mark_read / mark_unread ----------\n\n const markReadInputSchema = z.object({\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to mark as read\"),\n });\n\n const markReadOutputSchema = z.object({\n marked: z.literal(true),\n id: z.string(),\n isRead: z.boolean(),\n });\n\n if (shouldRegister(\"mark_read\", tools)) {\n server.registerTool(\n \"mark_read\",\n {\n description:\n \"Mark a message as read. Disabled in --read-only mode.\",\n inputSchema: markReadInputSchema,\n outputSchema: markReadOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n return await markReadState(args, true);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n if (shouldRegister(\"mark_unread\", tools)) {\n server.registerTool(\n \"mark_unread\",\n {\n description:\n \"Mark a message as unread. Disabled in --read-only mode.\",\n inputSchema: markReadInputSchema,\n outputSchema: markReadOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n return await markReadState(args, false);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { AccountRecord, AccountStore } from \"../store/account-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { EmailProvider, SendInput } from \"../providers/types.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { checkAccountAccess } from \"./agent-context.js\";\nimport {\n ok,\n fail,\n errMsg,\n emailAddrSchema,\n composeBody,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerComposeTools(\n server: McpServer,\n ctx: {\n store: AccountStore;\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { store, registry, tools, agentContext } = ctx;\n\n const sendEmailSchema = z.object({\n account: z.string().email(),\n to: z.array(emailAddrSchema).min(1),\n cc: z.array(emailAddrSchema).optional(),\n bcc: z.array(emailAddrSchema).optional(),\n subject: z.string(),\n body: z.string(),\n format: z\n .enum([\"html\", \"markdown\"])\n .describe(\n \"Body format. 'html' sends the body as-is (must be valid HTML). \" +\n \"'markdown' converts the body from Markdown to HTML for clean rendering on the recipient side.\",\n ),\n include_signature: z\n .boolean()\n .describe(\n \"Whether to append the account's saved HTML signature to the email. \" +\n \"If true, don't include a signature in the body param to avoid double signature. \" +\n \"Returns an error if true but no signature is configured for this account.\",\n ),\n inReplyTo: z\n .string()\n .optional()\n .describe(\n \"Message ID to reply to. When set, sends as a threaded reply \" +\n \"which includes the quoted thread history automatically.\",\n ),\n replyAll: z\n .boolean()\n .default(false)\n .optional()\n .describe(\n \"When true and `inReplyTo` is set, reply to all recipients \" +\n \"instead of just the sender.\",\n ),\n forwardMessageId: z\n .string()\n .optional()\n .describe(\n \"Message ID to forward. When set, sends as a forward of the \" +\n \"specified message, preserving the original content. \" +\n \"Mutually exclusive with `inReplyTo`.\",\n ),\n });\n\n type SendEmailArgs = z.infer<typeof sendEmailSchema>;\n\n async function handleSendOrDraft(\n args: SendEmailArgs,\n action: (\n provider: EmailProvider,\n account: AccountRecord,\n msg: SendInput,\n ) => Promise<{ id: string }>,\n resultKey: string,\n toolName: string,\n ) {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n if (args.include_signature && !account.signature) {\n return fail(\n \"include_signature is true but no signature is configured for this account. \" +\n \"Set up a signature first with set_account_settings.\",\n );\n }\n const composed = composeBody({\n body: args.body,\n format: args.format,\n signature: account.signature,\n style: account.style,\n includeSignature: args.include_signature,\n });\n if (args.inReplyTo && args.forwardMessageId) {\n return fail(\n \"inReplyTo and forwardMessageId are mutually exclusive — use one or the other\",\n );\n }\n const res = await action(provider, account, {\n to: args.to,\n cc: args.cc,\n bcc: args.bcc,\n subject: args.subject,\n body: composed.body,\n isHtml: composed.isHtml,\n inReplyTo: args.inReplyTo,\n replyAll: args.replyAll,\n forwardMessageId: args.forwardMessageId,\n });\n const result: Record<string, unknown> = { [resultKey]: true, ...res };\n if (toolName === \"draft_email\" && res.id) {\n const draft = await provider.readEmail(account, res.id);\n result.draftHtml = draft.bodyHtml;\n }\n return ok(result, result);\n } catch (err) {\n return fail(errMsg(err));\n }\n }\n\n // ---------- send_email ----------\n\n const sendEmailOutputSchema = {\n sent: z.literal(true),\n id: z.string(),\n };\n\n if (shouldRegister(\"send_email\", tools)) {\n server.registerTool(\n \"send_email\",\n {\n description:\n \"Send an email from the given account. Appends the \" +\n \"account's signature (HTML) and applies style preferences when \" +\n \"`include_signature` is true. Returns an error if \" +\n \"`include_signature` is true but no signature is configured. \" +\n \"When `inReplyTo` is set, sends as a reply (or reply-all) which \" +\n \"preserves thread history and conversation threading. \" +\n \"When `forwardMessageId` is set, sends as a forward of the \" +\n \"specified message, preserving the original content. \" +\n \"`inReplyTo` and `forwardMessageId` are mutually exclusive. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: sendEmailSchema,\n outputSchema: sendEmailOutputSchema,\n },\n async (args) =>\n handleSendOrDraft(\n args as SendEmailArgs,\n (p, a, m) => p.sendEmail(a, m),\n \"sent\",\n \"send_email\",\n ),\n );\n }\n\n // ---------- draft_email ----------\n\n const draftEmailOutputSchema = {\n draft: z.literal(true),\n id: z.string(),\n draftHtml: z.string().optional(),\n };\n\n if (shouldRegister(\"draft_email\", tools)) {\n server.registerTool(\n \"draft_email\",\n {\n description:\n \"Create a draft email from the given account without sending it. \" +\n \"Works identically to send_email — appends signature when \" +\n \"`include_signature` is true, applies style, and supports replies \" +\n \"and forwards — but saves the message to the Drafts folder \" +\n \"instead of sending. Returns the draft message ID and the draft's \" +\n \"HTML body content (`draftHtml`). Before sending the draft, \" +\n \"inspect `draftHtml` to verify the draft looks correct: no \" +\n \"duplicate signature blocks, no broken or missing inline images, \" +\n \"no malformed HTML, and no other formatting issues. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: sendEmailSchema,\n outputSchema: draftEmailOutputSchema,\n },\n async (args) =>\n handleSendOrDraft(\n args as SendEmailArgs,\n (p, a, m) => p.saveDraft(a, m),\n \"draft\",\n \"draft_email\",\n ),\n );\n }\n\n // ---------- edit_draft ----------\n\n const editDraftSchema = z.object({\n account: z.string().email(),\n id: z.string().min(1).describe(\"Draft message ID to edit\"),\n to: z.array(emailAddrSchema).optional(),\n cc: z.array(emailAddrSchema).optional(),\n bcc: z.array(emailAddrSchema).optional(),\n subject: z.string().optional(),\n body: z.string().optional(),\n format: z\n .enum([\"html\", \"markdown\"])\n .optional()\n .describe(\n \"Body format. Only meaningful when `body` is also provided. \" +\n \"'html' sends the body as-is (must be valid HTML). \" +\n \"'markdown' converts the body from Markdown to HTML for clean rendering on the recipient side.\",\n ),\n include_signature: z\n .boolean()\n .optional()\n .describe(\n \"Whether to re-apply the account's saved HTML signature to the body. \" +\n \"If true, don't include a signature in the body param. \" +\n \"Only meaningful when `body` is also provided. \" +\n \"Returns an error if true but no signature is configured for this account.\",\n ),\n });\n\n type EditDraftArgs = z.infer<typeof editDraftSchema>;\n\n const editDraftOutputSchema = {\n edited: z.literal(true),\n id: z.string(),\n draftHtml: z.string().optional(),\n };\n\n if (shouldRegister(\"edit_draft\", tools)) {\n server.registerTool(\n \"edit_draft\",\n {\n description:\n \"Edit an existing draft email by ID. Only the fields you provide \" +\n \"are updated — unmentioned fields stay unchanged. When `body` is \" +\n \"provided and `include_signature` is true, the account's signature \" +\n \"is re-applied. Returns the draft ID and the draft's updated HTML \" +\n \"body content (`draftHtml`). Before sending, inspect `draftHtml` \" +\n \"to verify the draft looks correct. \" +\n \"Does not support changing `inReplyTo` or `forwardMessageId` — \" +\n \"those are set at creation time via `draft_email`. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: editDraftSchema,\n outputSchema: editDraftOutputSchema,\n },\n async (args) => {\n const a = args as EditDraftArgs;\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, a.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(a.account);\n if (a.include_signature && !account.signature) {\n return fail(\n \"include_signature is true but no signature is configured for this account. \" +\n \"Set up a signature first with set_account_settings.\",\n );\n }\n let bodyPayload: string | undefined;\n let isHtmlPayload: boolean | undefined;\n if (a.body !== undefined) {\n const composed = composeBody({\n body: a.body,\n format: a.format ?? \"html\",\n signature: account.signature,\n style: account.style,\n includeSignature: !!a.include_signature,\n });\n bodyPayload = composed.body;\n isHtmlPayload = composed.isHtml;\n }\n const res = await provider.updateDraft(account, a.id, {\n to: a.to,\n cc: a.cc,\n bcc: a.bcc,\n subject: a.subject,\n body: bodyPayload,\n isHtml: isHtmlPayload,\n });\n const draft = await provider.readEmail(account, res.id);\n const result: Record<string, unknown> = {\n edited: true as const,\n id: res.id,\n draftHtml: draft.bodyHtml,\n };\n return ok(result, result);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- send_draft ----------\n\n const sendDraftOutputSchema = {\n sent: z.literal(true),\n id: z.string(),\n };\n\n if (shouldRegister(\"send_draft\", tools)) {\n server.registerTool(\n \"send_draft\",\n {\n description:\n \"Send an existing draft email by ID. \" +\n \"Use this with draft IDs returned by `draft_email` or `edit_draft`. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Draft message ID to send\"),\n },\n outputSchema: sendDraftOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.sendDraft(account, args.id);\n const data = { sent: true as const, id: res.id };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- add_attachment_to_draft ----------\n\n const addAttachmentOutputSchema = {\n attached: z.literal(true),\n id: z.string(),\n attachment: z.object({\n id: z.string(),\n name: z.string(),\n contentType: z.string().optional(),\n }),\n };\n\n if (shouldRegister(\"add_attachment_to_draft\", tools)) {\n server.registerTool(\n \"add_attachment_to_draft\",\n {\n description:\n \"Add a file attachment to an existing draft email by ID. \" +\n \"`contentBytes` must be base64-encoded file content. \" +\n \"`contentType` is the MIME type (e.g. 'application/pdf'); \" +\n \"defaults to 'application/octet-stream' if omitted. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Draft message ID\"),\n name: z\n .string()\n .min(1)\n .describe(\"Attachment filename (e.g. 'report.pdf')\"),\n contentBytes: z\n .string()\n .min(1)\n .describe(\"Base64-encoded file content\"),\n contentType: z\n .string()\n .optional()\n .describe(\"MIME type (e.g. 'application/pdf')\"),\n },\n outputSchema: addAttachmentOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.addAttachmentToDraft(\n account,\n args.id,\n args.name,\n args.contentBytes,\n args.contentType,\n );\n const data = {\n attached: true as const,\n id: res.id,\n attachment: res.attachment,\n };\n return ok(data, data as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { ResolvedTools } from \"../config.js\";\nimport type { WatchNotification } from \"../watcher/index.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { ok, fail, errMsg, shouldRegister } from \"./shared.js\";\n\nexport interface NotificationToolContext {\n tools: ResolvedTools;\n /** Shared buffer the watcher writes to. Draining is the tool's job. */\n notificationBuffer: WatchNotification[];\n agentContext?: AgentContext | null;\n}\n\nexport function registerNotificationTools(\n server: McpServer,\n ctx: NotificationToolContext,\n): void {\n const { tools, notificationBuffer, agentContext } = ctx;\n\n const notifyOutputSchema = z.object({\n count: z.number(),\n items: z.array(\n z.object({\n type: z.enum([\"new_emails\", \"auth_failure\"]),\n account: z.string(),\n emails: z.array(z.unknown()).optional(),\n error: z.string().optional(),\n timestamp: z.string(),\n }),\n ),\n });\n\n if (shouldRegister(\"check_notifications\", tools)) {\n server.registerTool(\n \"check_notifications\",\n {\n description:\n \"Check for pending email watch notifications. \" +\n \"Returns new-email alerts and auth-failure warnings that the inbox watcher \" +\n \"has accumulated since the last call. Drains the notification buffer on read.\",\n inputSchema: z.object({}),\n outputSchema: notifyOutputSchema,\n },\n async () => {\n try {\n // Drain atomically — splice returns removed items and clears them\n // from the array in one operation.\n const pending = notificationBuffer.splice(0);\n // Scope to agent's accounts in HTTP mode; unrestricted in stdio.\n const filtered = agentContext\n ? pending.filter((n) =>\n agentContext.accounts.some(\n (a) => a.toLowerCase() === n.account.toLowerCase(),\n ),\n )\n : pending;\n const data = { count: filtered.length, items: filtered };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\nimport type { AccountStore } from \"../store/account-store.js\";\nimport type { AgentStore } from \"../store/agent-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\n\n// Re-export compose helpers for tests\nexport { composeBody, escapeHtml, buildStyleAttr } from \"./shared.js\";\nexport { markdownToHtml } from \"../markdown-to-html.js\";\n\n// Submodule registration functions\nimport { registerAccountTools } from \"./accounts.js\";\nimport { registerBrowseTools } from \"./browse.js\";\nimport { registerFolderTools } from \"./folders.js\";\nimport { registerOrganizeTools } from \"./organize.js\";\nimport { registerComposeTools } from \"./compose.js\";\nimport { registerNotificationTools } from \"./notifications.js\";\nimport type { WatchNotification } from \"../watcher/index.js\";\n\nexport interface RegisterToolsOptions {\n store: AccountStore;\n agentStore?: AgentStore;\n registry: Registry;\n tools: ResolvedTools;\n notificationBuffer?: WatchNotification[];\n /** Agent identity for access control. null = stdio mode (unrestricted). */\n agentContext?: AgentContext | null;\n}\n\nexport function registerTools(\n server: McpServer,\n opts: RegisterToolsOptions,\n): void {\n const { store, registry, tools, agentContext, agentStore } = opts;\n\n registerAccountTools(server, { store, registry, tools, agentContext, agentStore });\n registerBrowseTools(server, { registry, tools, agentContext });\n registerFolderTools(server, { registry, tools, agentContext });\n registerOrganizeTools(server, { registry, tools, agentContext });\n registerComposeTools(server, { store, registry, tools, agentContext });\n if (opts.notificationBuffer) {\n registerNotificationTools(server, {\n tools,\n notificationBuffer: opts.notificationBuffer,\n agentContext,\n });\n }\n}\n","// Keep in sync with package.json version.\nexport const VERSION = \"0.4.1\";\n","import { readFileSync } from \"node:fs\";\nimport { z } from \"zod\";\n\n// ── Schema ──\n\nconst httpConfigSchema = z.object({\n enabled: z.boolean().default(false),\n port: z.number().int().min(1).max(65535).default(3000),\n host: z.string().default(\"127.0.0.1\"),\n});\n\nconst toolsConfigSchema = z.object({\n disabled: z.array(z.string()).optional(),\n enabled: z.array(z.string()).optional(),\n});\n\nconst outlookProviderSchema = z.object({\n clientId: z.string().optional(),\n tenantId: z.string().optional(),\n});\n\nconst gmailProviderSchema = z.object({\n clientId: z.string().optional(),\n clientSecret: z.string().optional(),\n});\n\nconst providersConfigSchema = z.object({\n outlook: outlookProviderSchema.optional(),\n gmail: gmailProviderSchema.optional(),\n});\n\nconst watchConfigSchema = z.object({\n enabled: z.boolean().default(true),\n pollIntervalSeconds: z.number().int().min(10).max(3600).default(60),\n});\n\nconst rawConfigSchema = z.object({\n dataDir: z.string().optional(),\n http: httpConfigSchema.optional(),\n tools: toolsConfigSchema.optional(),\n providers: providersConfigSchema.optional(),\n watch: watchConfigSchema.optional(),\n});\n\n// ── Types ──\n\nexport interface HttpConfig {\n enabled: boolean;\n port: number;\n host: string;\n}\n\nexport interface ToolsConfig {\n disabled?: string[];\n enabled?: string[];\n}\n\nexport interface OutlookProviderConfig {\n clientId?: string;\n tenantId?: string;\n}\n\nexport interface GmailProviderConfig {\n clientId?: string;\n clientSecret?: string;\n}\n\nexport interface ProvidersConfig {\n outlook?: OutlookProviderConfig;\n gmail?: GmailProviderConfig;\n}\n\nexport interface WatchConfig {\n enabled: boolean;\n pollIntervalSeconds: number;\n}\n\n/** Fully resolved application configuration (after ${VAR} expansion and CLI merge). */\nexport interface AppConfig {\n dataDir?: string;\n http: HttpConfig;\n tools?: ToolsConfig;\n providers?: ProvidersConfig;\n watch?: WatchConfig;\n /** Path to agents.yaml for HTTP multi-tenant mode. Only used when http.enabled is true. */\n agentsConfigPath?: string;\n}\n\n/** CLI flags that can override config file values. */\nexport interface CliOverrides {\n http?: boolean;\n port?: number;\n host?: string;\n dataDir?: string;\n agentsConfig?: string;\n}\n\n// ── Known tool names ──\n\n/**\n * Every tool that {@link registerTools} may register.\n * Used for validation — typos in tools.disabled / tools.enabled are caught at startup.\n */\nexport const KNOWN_TOOLS = [\n \"list_accounts\",\n \"add_account\",\n \"complete_add_account\",\n \"get_account_settings\",\n \"set_account_settings\",\n \"remove_account\",\n \"list_emails\",\n \"search_emails\",\n \"read_email\",\n \"read_attachment\",\n \"archive_email\",\n \"trash_email\",\n \"move_email\",\n \"mark_read\",\n \"mark_unread\",\n \"list_folders\",\n \"create_folder\",\n \"delete_folder\",\n \"rename_folder\",\n \"send_email\",\n \"draft_email\",\n \"edit_draft\",\n \"send_draft\",\n \"add_attachment_to_draft\",\n \"check_notifications\",\n] as const;\n\n// ── ${VAR} resolution ──\n\nconst ENV_VAR_RE = /\\$\\{([A-Z_][A-Z0-9_]*)\\}/g;\n\nfunction resolveEnvVars(value: string): string {\n return value.replace(ENV_VAR_RE, (_match, name: string) => {\n return process.env[name] ?? \"\";\n });\n}\n\n/** Recursively resolve `${VAR}` placeholders in all string values. */\nfunction deepResolve(obj: unknown): unknown {\n if (typeof obj === \"string\") return resolveEnvVars(obj);\n if (Array.isArray(obj)) return obj.map(deepResolve);\n if (obj && typeof obj === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(obj as Record<string, unknown>)) {\n out[key] = deepResolve(val);\n }\n return out;\n }\n return obj;\n}\n\n// ── Validation ──\n\nfunction validateToolNames(\n toolNames: string[] | undefined,\n listName: string,\n): void {\n if (!toolNames || toolNames.length === 0) return;\n const known = new Set<string>(KNOWN_TOOLS as readonly string[]);\n for (const name of toolNames) {\n if (!known.has(name)) {\n throw new Error(\n `Unknown tool \"${name}\" in ${listName}. Known tools: ${KNOWN_TOOLS.join(\", \")}`,\n );\n }\n }\n}\n\n// ── Loading ──\n\n/**\n * Load and validate `hypermail-config.json`.\n *\n * @param configPath File path, or `undefined` to use defaults.\n * @param cliOverrides CLI flags that take precedence over config file values.\n * @returns A fully resolved {@link AppConfig}.\n */\nexport function loadConfig(\n configPath: string | undefined,\n cliOverrides: CliOverrides = {},\n): AppConfig {\n let raw: Record<string, unknown> = {};\n\n if (configPath) {\n try {\n raw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch (err) {\n const detail =\n err instanceof SyntaxError\n ? \"Invalid JSON\"\n : err instanceof Error\n ? err.message\n : String(err);\n throw new Error(`Failed to read config file \"${configPath}\": ${detail}`);\n }\n }\n\n // Resolve ${VAR} before zod validation so env-var references become real values.\n raw = deepResolve(raw) as Record<string, unknown>;\n\n // Validate structure\n const parsed = rawConfigSchema.parse(raw);\n\n // Manual validations that go beyond zod's capabilities\n if (parsed.tools) {\n if (parsed.tools.disabled && parsed.tools.enabled) {\n throw new Error(\n \"tools.disabled and tools.enabled are mutually exclusive — use one or the other\",\n );\n }\n if (parsed.tools.enabled !== undefined && parsed.tools.enabled.length === 0) {\n throw new Error(\n \"tools.enabled is empty — at least one tool must be listed. \" +\n \"To enable all tools, omit the tools section entirely.\",\n );\n }\n validateToolNames(parsed.tools.disabled, \"tools.disabled\");\n validateToolNames(parsed.tools.enabled, \"tools.enabled\");\n }\n\n // Merge CLI overrides on top of config file values\n const http: HttpConfig = {\n enabled: cliOverrides.http ?? parsed.http?.enabled ?? false,\n port: cliOverrides.port ?? parsed.http?.port ?? 3000,\n host: cliOverrides.host ?? parsed.http?.host ?? \"127.0.0.1\",\n };\n\n return {\n dataDir:\n cliOverrides.dataDir ??\n parsed.dataDir ??\n process.env.HYPERMAIL_MCP_DATA_DIR,\n http,\n tools: parsed.tools\n ? { disabled: parsed.tools.disabled, enabled: parsed.tools.enabled }\n : undefined,\n providers: parsed.providers as ProvidersConfig | undefined,\n watch: parsed.watch as WatchConfig | undefined,\n agentsConfigPath:\n cliOverrides.agentsConfig ??\n process.env.HYPERMAIL_AGENTS_CONFIG,\n };\n}\n\n// ── Helpers ──\n\n/** Extracted tool filtering state for {@link registerTools}. */\nexport interface ResolvedTools {\n /** If set, only these tools are registered (allowlist mode). */\n enabledTools: Set<string> | null;\n /** If set, these tools are NOT registered (blocklist mode). */\n disabledTools: Set<string> | null;\n}\n\n/** Convert {@link AppConfig.tools} into the sets that {@link registerTools} consumes. */\nexport function resolveTools(config: AppConfig): ResolvedTools {\n if (!config.tools) {\n return { enabledTools: null, disabledTools: null };\n }\n return {\n enabledTools: config.tools.enabled\n ? new Set(config.tools.enabled)\n : null,\n disabledTools: config.tools.disabled\n ? new Set(config.tools.disabled)\n : null,\n };\n}\n","import type { AccountStore, AccountRecord } from \"../store/account-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { EmailSummary } from \"../providers/types.js\";\n\n// ── types ──\n\nexport interface WatchNotification {\n type: \"new_emails\" | \"auth_failure\";\n account: string;\n /** New emails since last poll. Only present for type: \"new_emails\". */\n emails?: EmailSummary[];\n /** Error message. Only present for type: \"auth_failure\". */\n error?: string;\n /** ISO timestamp of when this notification was created. */\n timestamp: string;\n}\n\nexport interface WatcherManagerOptions {\n registry: Registry;\n store: AccountStore;\n /** Polling interval per account, in seconds. */\n pollIntervalSeconds: number;\n /**\n * Called when a push notification should be sent to the connected client.\n * May be called even when no SSE session is active — the callback should\n * handle that gracefully (e.g. by catching send errors).\n */\n onNotification: (notification: WatchNotification) => void;\n /**\n * Shared in-memory buffer of pending notifications. The watcher appends\n * new entries; the check_notifications tool drains them via splice(0).\n */\n buffer: WatchNotification[];\n /**\n * Optional list of email addresses to watch. When provided, only these\n * accounts are polled. When omitted, all stored accounts are polled\n * (stdio mode / legacy behavior).\n */\n accountFilter?: string[];\n}\n\n// ── manager ──\n\nexport class WatcherManager {\n private readonly opts: WatcherManagerOptions;\n private timers: ReturnType<typeof setInterval>[] = [];\n private running = false;\n /** Per-account inflight guards to prevent overlapping polls. */\n private readonly inflight = new Map<string, boolean>();\n /** Accounts with active polling timers (lowercased email). */\n private readonly tracked = new Set<string>();\n\n constructor(opts: WatcherManagerOptions) {\n this.opts = opts;\n }\n\n start(): void {\n if (this.running) return;\n this.running = true;\n\n // Initial scan — schedule polling for all matching accounts.\n this.scanAccounts();\n\n // Periodic re-scan to pick up accounts added after start().\n const rescanTimer = setInterval(() => {\n if (!this.running) return;\n this.scanAccounts();\n }, this.opts.pollIntervalSeconds * 1000);\n this.timers.push(rescanTimer);\n }\n\n stop(): void {\n this.running = false;\n for (const t of this.timers) clearInterval(t);\n this.timers = [];\n this.tracked.clear();\n }\n\n // ── internals ──\n\n private scanAccounts(): void {\n let accounts = this.opts.store.listAccounts();\n if (this.opts.accountFilter) {\n const filter = new Set(this.opts.accountFilter.map((e) => e.toLowerCase()));\n accounts = accounts.filter((a) => filter.has(a.email.toLowerCase()));\n }\n for (const account of accounts) {\n this.schedulePoll(account);\n }\n }\n\n private schedulePoll(account: AccountRecord): void {\n const key = account.email.toLowerCase();\n if (this.tracked.has(key)) return;\n this.tracked.add(key);\n\n // Run immediately on start, then on interval.\n this.pollAccount(account).catch(() => {\n /* errors surfaced via notifications */\n });\n\n const timer = setInterval(() => {\n if (!this.running) return;\n this.pollAccount(account).catch(() => {\n /* errors surfaced via notifications */\n });\n }, this.opts.pollIntervalSeconds * 1000);\n\n this.timers.push(timer);\n }\n\n private async pollAccount(account: AccountRecord): Promise<void> {\n const key = account.email.toLowerCase();\n if (this.inflight.get(key)) return;\n this.inflight.set(key, true);\n\n try {\n const { provider } = this.opts.registry.resolveByEmail(account.email);\n const seenIds = new Set(account.lastSeenIds ?? []);\n const isFirstPoll = !account.lastSeenAt && !account.lastSeenIds?.length;\n const limit = 25;\n const MAX_PAGES = 5;\n let skip = 0;\n let pageCount = 0;\n const newEmails: EmailSummary[] = [];\n let newestTimestamp = account.lastSeenAt ?? \"\";\n\n // Paginate through inbox until we hit a previously seen email ID\n // or exhaust available pages.\n let hitBoundary = false;\n while (pageCount < MAX_PAGES) {\n const { items, hasMore } = await provider.listEmails(account, {\n folder: \"inbox\",\n limit,\n skip,\n });\n pageCount++;\n\n for (const item of items) {\n if (!item.receivedAt) continue;\n if (seenIds.has(item.id)) {\n hitBoundary = true;\n break;\n }\n newEmails.push(item);\n if (item.receivedAt > newestTimestamp) {\n newestTimestamp = item.receivedAt;\n }\n }\n\n if (hitBoundary || !hasMore) break;\n skip += limit;\n }\n\n // First poll: set baseline silently. Subsequent polls: notify.\n if (!isFirstPoll && newEmails.length > 0) {\n this.enqueue({\n type: \"new_emails\",\n account: account.email,\n emails: newEmails,\n timestamp: new Date().toISOString(),\n });\n }\n\n // Persist updated state: prepend new IDs to lastSeenIds (cap 200),\n // update lastSeenAt. On empty-inbox first poll, mark current time\n // as baseline so future polls exit first-poll mode.\n if (isFirstPoll && newEmails.length === 0 && !newestTimestamp) {\n newestTimestamp = new Date().toISOString();\n }\n const newIds = newEmails.map((e) => e.id);\n const updatedLastSeenIds = [\n ...newIds,\n ...(account.lastSeenIds ?? []),\n ].slice(0, 200);\n\n try {\n await this.opts.store.upsertAccount({\n ...account,\n lastSeenAt: newestTimestamp || undefined,\n lastSeenIds: updatedLastSeenIds,\n });\n } catch (storeErr) {\n // eslint-disable-next-line no-console\n console.error(\n \"[hypermail-mcp] failed to persist poll state for\",\n account.email,\n \":\",\n storeErr instanceof Error ? storeErr.message : String(storeErr),\n );\n }\n } catch (err: unknown) {\n this.enqueue({\n type: \"auth_failure\",\n account: account.email,\n error: err instanceof Error ? err.message : String(err),\n timestamp: new Date().toISOString(),\n });\n } finally {\n this.inflight.delete(key);\n }\n }\n\n private enqueue(notification: WatchNotification): void {\n this.opts.buffer.push(notification);\n // Also try push delivery — may fail silently if no SSE connection.\n try {\n this.opts.onNotification(notification);\n } catch {\n /* push not available; tool-based polling fallback will deliver it */\n }\n }\n}\n","import { readFileSync, watch, type FSWatcher } from \"node:fs\";\nimport { load as loadYaml } from \"js-yaml\";\nimport { z } from \"zod\";\n\nimport type { AgentStore } from \"../store/agent-store.js\";\n\n// ── Schema ──\n\nconst agentDefSchema = z.object({\n id: z\n .string()\n .min(1)\n .regex(\n /^[a-z0-9_-]+$/,\n \"agent id must contain only lowercase letters, digits, hyphens, and underscores\",\n ),\n api_key: z\n .string()\n .min(1)\n .regex(\n /^hm_sk_[a-f0-9]{64}$/,\n \"api_key must match hm_sk_ prefix + 64 hex chars (use `hypermail-mcp generate-key`)\",\n ),\n name: z.string().min(1),\n accounts: z.array(z.string().email()).optional().default([]),\n provisioning: z.boolean().optional().default(false),\n});\n\nconst emailAccountDefSchema = z.object({\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n display_name: z.string().optional(),\n});\n\nconst agentsConfigSchema = z.object({\n agents: z.array(agentDefSchema).optional().default([]),\n email_accounts: z\n .record(z.string().email(), emailAccountDefSchema)\n .optional()\n .default({}),\n});\n\n// ── Types ──\n\nexport interface AgentDef {\n id: string;\n api_key: string;\n name: string;\n accounts: string[];\n provisioning: boolean;\n}\n\nexport interface EmailAccountDef {\n provider: \"outlook\" | \"imap\" | \"gmail\";\n display_name?: string;\n}\n\nexport interface AgentsConfig {\n agents: AgentDef[];\n email_accounts: Record<string, EmailAccountDef>;\n}\n\n// ── Loading ──\n\n/**\n * Load and validate `agents.yaml`.\n *\n * @param configPath Absolute or relative path to the YAML file.\n * @returns The parsed and validated {@link AgentsConfig}.\n */\nexport function loadAgentsConfig(configPath: string): AgentsConfig {\n let raw: unknown;\n try {\n raw = loadYaml(readFileSync(configPath, \"utf-8\"));\n } catch (err) {\n if (err instanceof Error && \"code\" in err && (err as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new Error(\n `Agents config file not found: ${configPath}. ` +\n \"Create an agents.yaml with at least one agent to enable HTTP multi-tenant mode.\",\n );\n }\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to parse agents config \"${configPath}\": ${detail}`);\n }\n\n const parsed = agentsConfigSchema.parse(raw ?? {});\n\n // Validate: no duplicate agent ids\n const ids = new Set<string>();\n for (const a of parsed.agents) {\n if (ids.has(a.id)) {\n throw new Error(`Duplicate agent id \"${a.id}\" in agents config`);\n }\n ids.add(a.id);\n }\n\n return {\n agents: parsed.agents.map((a) => ({\n id: a.id,\n api_key: a.api_key,\n name: a.name,\n accounts: a.accounts,\n provisioning: a.provisioning,\n })),\n email_accounts: parsed.email_accounts as Record<string, EmailAccountDef>,\n };\n}\n\n// ── Syncing ──\n\n/**\n * Sync agent definitions from the parsed YAML config into the AgentStore.\n *\n * - New agents (in config but not in store) are upserted with their plaintext API key hashed.\n * - Existing agents (in both) are updated (name, accounts, provisioning). API key hash is\n * NOT touched unless the plaintext key changed — avoids re-hashing on every reload.\n * - Stale agents (in store but not in config) are removed.\n * - Auto-assigned accounts (added via `add_account` tool) are preserved — they are merged\n * with the YAML-defined assignments per agent.\n *\n * @returns The list of agent ids that were removed (so their sessions can be invalidated).\n */\nexport async function syncAgentsToStore(\n config: AgentsConfig,\n store: AgentStore,\n): Promise<string[]> {\n const configAgentIds = new Set(config.agents.map((a) => a.id));\n const storedAgents = store.listAgents();\n\n // Upsert config-defined agents\n for (const def of config.agents) {\n await store.upsertAgent({\n id: def.id,\n plaintextApiKey: def.api_key,\n name: def.name,\n accounts: def.accounts,\n provisioning: def.provisioning,\n });\n }\n\n // Remove agents not in config anymore\n const removed: string[] = [];\n for (const stored of storedAgents) {\n if (!configAgentIds.has(stored.id)) {\n await store.removeAgent(stored.id);\n removed.push(stored.id);\n }\n }\n\n return removed;\n}\n\n// ── Live reload ──\n\nexport interface LiveReloadHandle {\n /** Stop watching for changes. */\n close(): void;\n}\n\n/**\n * Watch `agents.yaml` for changes and sync into the AgentStore on every\n * modification. Debounces rapid writes (e.g. editor atomic saves).\n *\n * @param configPath Absolute path to agents.yaml.\n * @param store The AgentStore to sync into.\n * @param onChange Called after each sync with the list of removed agent ids.\n * @param onError Called on parse/sync errors (logged, not fatal).\n */\nexport function watchAgentsConfig(\n configPath: string,\n store: AgentStore,\n onChange: (removedIds: string[]) => void,\n onError: (err: Error) => void,\n): LiveReloadHandle {\n let timer: ReturnType<typeof setTimeout> | null = null;\n let watcher: FSWatcher | null = null;\n\n const reload = async () => {\n try {\n const config = loadAgentsConfig(configPath);\n const removed = await syncAgentsToStore(config, store);\n onChange(removed);\n } catch (err) {\n onError(err instanceof Error ? err : new Error(String(err)));\n }\n };\n\n // Initial load\n reload().catch((err) => onError(err));\n\n // Watch for changes\n try {\n watcher = watch(configPath, (_eventType) => {\n // Debounce: coalesce rapid successive events into one reload.\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = null;\n reload().catch((err) => onError(err));\n }, 200);\n });\n } catch (err) {\n // fs.watch may fail on some platforms (e.g. network mounts) — not fatal;\n // config can still be loaded once at startup.\n }\n\n return {\n close() {\n if (timer) clearTimeout(timer);\n if (watcher) watcher.close();\n },\n };\n}\n"],"mappings":"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","names":["randomBytes","randomUUID","path","fs","path","fs","path","path","fs","FILE_NAME","fs","path","randomUUID","existing","randomUUID","tmpdir","pathJoin","clampLimit","mapSummary","clampLimit","mapSummary","pathJoin","tmpdir","randomUUID","randomUUID","path","randomUUID","DEFAULT_SCOPES","beginDeviceCode","awaitDeviceCodeReady","existing","writeFileSync","tmpdir","pathJoin","MailComposer","h","mapSummary","mapFolder","clampLimit","buildRawMessage","MailComposer","listEmails","clampLimit","mapSummary","searchEmails","readEmail","readAttachment","pathJoin","tmpdir","writeFileSync","listFolders","mapFolder","randomUUID","Buffer","MailComposer","sendEmail","Buffer","buildRawMessage","saveDraft","updateDraft","moveEmail","sendDraft","addAttachmentToDraft","MailComposer","randomUUID","markRead","createFolder","mapFolder","renameFolder","deleteFolder","beginDeviceCode","awaitDeviceCodeReady","randomUUID","listEmails","searchEmails","readEmail","readAttachment","sendEmail","saveDraft","updateDraft","moveEmail","sendDraft","addAttachmentToDraft","markRead","listFolders","createFolder","renameFolder","deleteFolder","fs","z","z","fs","z","z","z","z","z","z","z","z","z","z","z","readFileSync","z","path","randomUUID","randomBytes"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/server.ts","../src/store/account-store.ts","../src/store/crypto.ts","../src/store/agent-store.ts","../src/providers/outlook/index.ts","../src/providers/shared/inline-images.ts","../src/providers/outlook/client.ts","../src/providers/outlook/auth.ts","../src/providers/imap/client.ts","../src/providers/imap/read-ops.ts","../src/providers/imap/helpers.ts","../src/providers/imap/write-ops.ts","../src/providers/imap/index.ts","../src/providers/gmail/index.ts","../src/providers/gmail/auth.ts","../src/providers/gmail/client.ts","../src/providers/gmail/read-ops.ts","../src/providers/gmail/helpers.ts","../src/providers/gmail/write-ops.ts","../src/providers/registry.ts","../src/tools/shared.ts","../src/markdown-to-html.ts","../src/tools/accounts.ts","../src/tools/agent-context.ts","../src/tools/browse.ts","../src/html-to-markdown.ts","../src/tools/folders.ts","../src/tools/organize.ts","../src/tools/compose.ts","../src/tools/notifications.ts","../src/tools/index.ts","../package.json","../src/version.ts","../src/config.ts","../src/watcher/manager.ts","../src/config/agents-config.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\n\nimport { startServer } from \"./server.js\";\nimport { loadConfig } from \"./config.js\";\n\ntype ParsedArgs = {\n http: boolean;\n port: number;\n host: string;\n dataDir?: string;\n config?: string;\n agentsConfig?: string;\n help: boolean;\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = {\n http: false,\n port: 3000,\n host: \"127.0.0.1\",\n help: false,\n };\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n switch (a) {\n case \"--http\":\n out.http = true;\n break;\n case \"--port\":\n out.port = Number(argv[++i] ?? \"3000\");\n break;\n case \"--host\":\n out.host = String(argv[++i] ?? \"127.0.0.1\");\n break;\n case \"--data-dir\":\n out.dataDir = String(argv[++i] ?? \"\");\n break;\n case \"--config\":\n out.config = String(argv[++i] ?? \"\");\n break;\n case \"--agents-config\":\n out.agentsConfig = String(argv[++i] ?? \"\");\n break;\n case \"-h\":\n case \"--help\":\n out.help = true;\n break;\n default:\n if (a && a.startsWith(\"--\")) {\n // ignore unknown flags rather than crashing — keeps the CLI forgiving\n // when embedded in MCP host configs.\n }\n }\n }\n return out;\n}\n\nfunction printHelp(): void {\n const msg = `hypermail-mcp — unified email MCP server\n\nUsage:\n hypermail-mcp [options]\n\nOptions:\n --http Run as Streamable HTTP server (default: stdio)\n --port <n> HTTP port (default: 3000)\n --host <addr> HTTP bind address (default: 127.0.0.1)\n --data-dir <path> Where to store the encrypted accounts file\n (default: $HYPERMAIL_MCP_DATA_DIR or ~/.hypermail-mcp)\n --config <path> Path to hypermail-config.json\n -h, --help Show this help\n\nConfiguration:\n All server settings (data dir, HTTP, tool filtering, provider credentials)\n live in hypermail-config.json. Pass it via --config.\n\nExample hypermail-config.json:\n {\n \"dataDir\": \"/path/to/data\",\n \"http\": { \"enabled\": false },\n \"tools\": { \"disabled\": [\"send_email\"] },\n \"providers\": {\n \"outlook\": { \"clientId\": \"\\${MS_CLIENT_ID}\", \"tenantId\": \"\\${MS_TENANT_ID}\" },\n \"gmail\": { \"clientId\": \"\\${GOOGLE_CLIENT_ID}\", \"clientSecret\": \"\\${GOOGLE_CLIENT_SECRET}\" }\n }\n }\n`;\n process.stdout.write(msg);\n}\n\nasync function main(): Promise<void> {\n const rawArgs = process.argv.slice(2);\n\n // Subcommand: generate-key\n if (rawArgs[0] === \"generate-key\") {\n const key = `hm_sk_${randomBytes(32).toString(\"hex\")}`;\n process.stdout.write(key + \"\\n\");\n return;\n }\n\n const opts = parseArgs(rawArgs);\n if (opts.help) {\n printHelp();\n return;\n }\n\n const config = loadConfig(opts.config, {\n http: opts.http,\n port: opts.port,\n host: opts.host,\n dataDir: opts.dataDir,\n agentsConfig: opts.agentsConfig,\n });\n\n await startServer({ config });\n}\n\nmain().catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] fatal:\", err);\n process.exit(1);\n});\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { randomUUID } from \"node:crypto\";\nimport { createServer as createHttpServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport path from \"node:path\";\n\nimport { AccountStore } from \"./store/account-store.js\";\nimport { AgentStore } from \"./store/agent-store.js\";\nimport { buildRegistry } from \"./providers/registry.js\";\nimport { registerTools } from \"./tools/index.js\";\nimport { VERSION } from \"./version.js\";\nimport type { AppConfig, ResolvedTools } from \"./config.js\";\nimport { resolveTools } from \"./config.js\";\nimport { WatcherManager } from \"./watcher/index.js\";\nimport type { WatchNotification } from \"./watcher/index.js\";\nimport {\n loadAgentsConfig,\n watchAgentsConfig,\n} from \"./config/agents-config.js\";\nimport type { AgentContext } from \"./tools/agent-context.js\";\n\nexport interface ServerOptions {\n /** Fully resolved application config from hypermail-config.json. */\n config: AppConfig;\n}\n\nexport async function startServer(opts: ServerOptions): Promise<void> {\n const { config } = opts;\n const store = await AccountStore.open({ dataDir: config.dataDir });\n const registry = buildRegistry({ store, providers: config.providers });\n const tools: ResolvedTools = resolveTools(config);\n\n // Shared notification buffer: the watcher pushes, the check_notifications\n // tool drains. Only created when both HTTP and watch are enabled.\n const watchEnabled = config.http.enabled && config.watch?.enabled !== false;\n const notificationBuffer: WatchNotification[] | undefined = watchEnabled\n ? []\n : undefined;\n\n // Factory: creates a fresh McpServer with all tools registered.\n // HTTP mode creates one per session; stdio mode uses a single instance.\n let agentStoreForFactory: AgentStore | undefined;\n const createServer = (agentContext: AgentContext | null = null): McpServer => {\n const s = new McpServer(\n { name: \"hypermail-mcp\", version: VERSION },\n { capabilities: { tools: {}, logging: {} } },\n );\n registerTools(s, { store, registry, tools, notificationBuffer, agentContext, agentStore: agentStoreForFactory });\n return s;\n };\n\n if (config.http.enabled) {\n // Open AgentStore and load agents.yaml (HTTP mode only).\n let liveReloadHandle: { close(): void } | undefined;\n if (config.agentsConfigPath) {\n agentStoreForFactory = await AgentStore.open({ dataDir: config.dataDir });\n liveReloadHandle = watchAgentsConfig(\n path.resolve(config.agentsConfigPath),\n agentStoreForFactory!,\n (_removedIds) => {\n // Sessions use the same agentStore instance — they'll pick up\n // updated agents on next lookup. Removed agents' existing sessions\n // remain valid until they disconnect (local-trust model).\n },\n (err) => {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] agents.yaml reload error:\", err.message);\n },\n );\n }\n\n // Per-session notification targets — the watcher pushes to all of them.\n const notifyTargets = new Set<(n: WatchNotification) => void>();\n\n // Compute account filter from all agents' authorized accounts.\n // When no agents are configured, poll all stored accounts (legacy).\n const accountFilter: string[] | undefined = agentStoreForFactory\n ? (() => {\n const all = new Set<string>();\n for (const agent of agentStoreForFactory.listAgents()) {\n for (const email of agent.accounts) {\n all.add(email.toLowerCase());\n }\n }\n return all.size > 0 ? [...all] : undefined;\n })()\n : undefined;\n\n if (watchEnabled) {\n const watcher = new WatcherManager({\n registry,\n store,\n pollIntervalSeconds: config.watch?.pollIntervalSeconds ?? 60,\n accountFilter,\n onNotification: (notification) => {\n for (const fn of notifyTargets) {\n fn(notification);\n }\n },\n buffer: notificationBuffer!,\n });\n watcher.start();\n }\n\n await startHttp(\n createServer,\n config.http.host,\n config.http.port,\n notifyTargets,\n agentStoreForFactory,\n );\n\n // Cleanup on shutdown\n if (liveReloadHandle) {\n process.on(\"SIGINT\", () => liveReloadHandle!.close());\n process.on(\"SIGTERM\", () => liveReloadHandle!.close());\n }\n } else {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n }\n}\n\ninterface HttpSession {\n transport: StreamableHTTPServerTransport;\n server: McpServer;\n agentContext: AgentContext | null;\n}\n\nasync function startHttp(\n createServer: (agentContext: AgentContext | null) => McpServer,\n host: string,\n port: number,\n notifyTargets: Set<(n: WatchNotification) => void>,\n agentStore?: AgentStore,\n): Promise<void> {\n // One McpServer + transport per session, keyed by Mcp-Session-Id header.\n const sessions = new Map<string, HttpSession>();\n\n const http = createHttpServer(async (req: IncomingMessage, res: ServerResponse) => {\n try {\n if (!req.url || !req.url.startsWith(\"/mcp\")) {\n res.statusCode = 404;\n res.end(\"not found\");\n return;\n }\n const sessionId = (req.headers[\"mcp-session-id\"] as string | undefined) ?? undefined;\n let session = sessionId ? sessions.get(sessionId) : undefined;\n\n if (!session) {\n // ── Session-init API key validation ──\n let agentContext: AgentContext | null = null;\n if (agentStore) {\n const apiKey = (req.headers[\"x-api-key\"] as string | undefined)?.trim();\n if (!apiKey) {\n res.statusCode = 401;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(JSON.stringify({ error: \"Missing x-api-key header\" }));\n return;\n }\n const agent = agentStore.findAgentByApiKey(apiKey);\n if (!agent) {\n res.statusCode = 401;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(JSON.stringify({ error: \"Invalid API key\" }));\n return;\n }\n agentContext = {\n agentId: agent.id,\n accounts: agent.accounts,\n provisioning: agent.provisioning,\n };\n }\n\n const server = createServer(agentContext);\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (sid: string) => {\n sessions.set(sid, { transport, server, agentContext });\n\n // Register push notification target for this session.\n // Scope to this agent's accounts only.\n const agentAccounts = agentContext\n ? new Set(agentContext.accounts.map((a) => a.toLowerCase()))\n : null;\n const notifyFn = (n: WatchNotification) => {\n // Only deliver notifications for accounts this agent can access.\n if (agentAccounts && !agentAccounts.has(n.account.toLowerCase())) {\n return;\n }\n server.server\n .notification({\n method: \"notifications/message\",\n params: {\n level: n.type === \"new_emails\" ? \"notice\" : \"warning\",\n logger: \"hypermail-watch\",\n data: n,\n },\n })\n .catch(() => {\n /* SSE not connected — fallback via check_notifications */\n });\n };\n notifyTargets.add(notifyFn);\n transport.onclose = () => {\n if (transport.sessionId) sessions.delete(transport.sessionId);\n notifyTargets.delete(notifyFn);\n };\n },\n });\n await server.connect(transport);\n session = { transport, server, agentContext };\n }\n\n // Buffer body for POST / DELETE\n let body: unknown = undefined;\n if (req.method === \"POST\" || req.method === \"DELETE\") {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n const raw = Buffer.concat(chunks).toString(\"utf8\");\n body = raw ? JSON.parse(raw) : undefined;\n }\n await session.transport.handleRequest(req, res, body);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] http error:\", err);\n if (!res.headersSent) {\n res.statusCode = 500;\n res.end(\"internal error\");\n }\n }\n });\n\n await new Promise<void>((resolve) => http.listen(port, host, resolve));\n // eslint-disable-next-line no-console\n console.error(`[hypermail-mcp] listening on http://${host}:${port}/mcp`);\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\n\nimport {\n encrypt,\n decrypt,\n resolveDataDir,\n resolveKey,\n writeAtomic,\n} from \"./crypto.js\";\n\n/**\n * One stored account. `tokens` is provider-specific (e.g. serialized MSAL cache\n * for Outlook, host/port/password blob for IMAP) — the store is opaque to it.\n */\nexport interface AccountRecord {\n email: string;\n provider: \"outlook\" | \"imap\" | \"gmail\";\n displayName?: string;\n tokens: Record<string, unknown>;\n addedAt: string;\n /** HTML snippet — may contain formatting, images, links. Injected at end of outgoing emails. */\n signature?: string;\n /** Font/style preferences applied to outgoing HTML emails. */\n style?: { fontFamily?: string; fontSize?: string; fontColor?: string };\n /** ISO timestamp of the newest email the watcher has already seen.\n * Used by the email-watcher to detect new mail since last poll. */\n lastSeenAt?: string;\n /** Email IDs the watcher has already seen (most recent first, capped at 200).\n * Used for ID-based dedup — emails whose ID is in this list are skipped\n * during polling, preventing duplicate/lost notifications from timestamp\n * collisions. */\n lastSeenIds?: string[];\n}\n\ninterface StoreFile {\n version: 1;\n accounts: AccountRecord[];\n}\n\nexport interface OpenOptions {\n dataDir?: string;\n /** Inject the encryption key directly (mostly for tests). Otherwise resolved\n * from `HYPERMAIL_MCP_KEY` env, then OS keychain, then auto-generated. */\n key?: Buffer;\n}\n\nconst FILE_NAME = \"accounts.json.enc\";\n\nexport class AccountStore {\n private constructor(\n private readonly filePath: string,\n private readonly key: Buffer,\n private data: StoreFile,\n ) {}\n\n static async open(opts: OpenOptions = {}): Promise<AccountStore> {\n const dataDir = resolveDataDir(opts.dataDir);\n await fs.mkdir(dataDir, { recursive: true, mode: 0o700 });\n const filePath = path.join(dataDir, FILE_NAME);\n const key = opts.key ?? (await resolveKey(dataDir));\n\n let data: StoreFile;\n try {\n const buf = await fs.readFile(filePath);\n data = decrypt(buf, key);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n data = { version: 1, accounts: [] };\n } else {\n throw err;\n }\n }\n return new AccountStore(filePath, key, data);\n }\n\n listAccounts(): AccountRecord[] {\n // Return shallow clones without tokens leaking out unintentionally is the\n // caller's job; here we expose the full record for provider use.\n return this.data.accounts.map((a) => ({ ...a }));\n }\n\n getAccount(email: string): AccountRecord | undefined {\n const norm = email.trim().toLowerCase();\n const rec = this.data.accounts.find((a) => a.email.toLowerCase() === norm);\n return rec ? { ...rec } : undefined;\n }\n\n async upsertAccount(rec: AccountRecord): Promise<AccountRecord> {\n const norm = rec.email.trim().toLowerCase();\n const next: AccountRecord = { ...rec, email: norm };\n const idx = this.data.accounts.findIndex((a) => a.email.toLowerCase() === norm);\n if (idx >= 0) this.data.accounts[idx] = next;\n else this.data.accounts.push(next);\n await this.flush();\n return { ...next };\n }\n\n async removeAccount(email: string): Promise<boolean> {\n const norm = email.trim().toLowerCase();\n const before = this.data.accounts.length;\n this.data.accounts = this.data.accounts.filter((a) => a.email.toLowerCase() !== norm);\n if (this.data.accounts.length === before) return false;\n await this.flush();\n return true;\n }\n\n private async flush(): Promise<void> {\n const buf = encrypt(this.data, this.key);\n await writeAtomic(this.filePath, buf);\n }\n}\n","import {\n createCipheriv,\n createDecipheriv,\n randomBytes,\n createHash,\n scryptSync,\n timingSafeEqual,\n} from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\n\nexport const ALGO = \"aes-256-gcm\";\nexport const KEY_LEN = 32;\n\n// ── AES-256-GCM encrypt / decrypt ──\n\n/** Encrypt JSON-serializable data with AES-256-GCM. Returns [1-byte version=1][12 iv][16 tag][ct...]. */\nexport function encrypt(data: unknown, key: Buffer): Buffer {\n if (key.length !== KEY_LEN) throw new Error(`key must be ${KEY_LEN} bytes`);\n const iv = randomBytes(12);\n const cipher = createCipheriv(ALGO, key, iv);\n const plaintext = Buffer.from(JSON.stringify(data), \"utf8\");\n const ct = Buffer.concat([cipher.update(plaintext), cipher.final()]);\n const tag = cipher.getAuthTag();\n return Buffer.concat([Buffer.from([1]), iv, tag, ct]);\n}\n\n/** Decrypt a buffer produced by {@link encrypt}. Returns the parsed JSON value. */\nexport function decrypt<T = unknown>(buf: Buffer, key: Buffer): T {\n if (key.length !== KEY_LEN) throw new Error(`key must be ${KEY_LEN} bytes`);\n if (buf.length < 1 + 12 + 16 + 1) throw new Error(\"encrypted data truncated\");\n const v = buf[0];\n if (v !== 1) throw new Error(`unsupported data version: ${v}`);\n const iv = buf.subarray(1, 13);\n const tag = buf.subarray(13, 29);\n const ct = buf.subarray(29);\n const decipher = createDecipheriv(ALGO, key, iv);\n decipher.setAuthTag(tag);\n const pt = Buffer.concat([decipher.update(ct), decipher.final()]);\n return JSON.parse(pt.toString(\"utf8\")) as T;\n}\n\n// ── key + path resolution ──\n\nexport function resolveDataDir(explicit?: string): string {\n if (explicit && explicit.length > 0) return path.resolve(explicit);\n const env = process.env.HYPERMAIL_MCP_DATA_DIR;\n if (env && env.length > 0) return path.resolve(env);\n return path.join(homedir(), \".hypermail-mcp\");\n}\n\nexport function parseEnvKey(raw: string): Buffer | undefined {\n const s = raw.trim();\n // hex (64 chars)\n if (/^[0-9a-fA-F]{64}$/.test(s)) return Buffer.from(s, \"hex\");\n // base64 — accept any length, then check\n try {\n const buf = Buffer.from(s, \"base64\");\n if (buf.length === KEY_LEN) return buf;\n } catch {\n /* ignore */\n }\n // last-resort: derive 32 bytes via SHA-256 over the raw string\n return createHash(\"sha256\").update(s, \"utf8\").digest();\n}\n\nexport async function resolveKey(dataDir: string): Promise<Buffer> {\n const env = process.env.HYPERMAIL_MCP_KEY;\n if (env && env.length > 0) {\n const k = parseEnvKey(env);\n if (k) return k;\n }\n\n // Try OS keychain via keytar (optional dep).\n const fromKeytar = await tryKeytarGet();\n if (fromKeytar) return fromKeytar;\n\n // Local-dev fallback: persist a generated key to a 0600 file.\n const keyFile = path.join(dataDir, \"master.key\");\n try {\n const existing = await fs.readFile(keyFile);\n if (existing.length === KEY_LEN) return existing;\n } catch {\n /* fall through to generate */\n }\n const gen = randomBytes(KEY_LEN);\n await fs.writeFile(keyFile, gen, { mode: 0o600 });\n await tryKeytarSet(gen);\n return gen;\n}\n\n// ── API key hashing (scrypt — built into Node, no native deps) ──\n\n/**\n * Hash an API key with scrypt. Returns \"salt:hash\" (both hex-encoded) for\n * storage. Suitable for <10 agents — scrypt is purpose-built for password\n * hashing and runs in-process with no native compilation.\n */\nexport function hashApiKey(apiKey: string): string {\n const salt = randomBytes(16).toString(\"hex\");\n const hash = scryptSync(apiKey, salt, 32).toString(\"hex\");\n return `${salt}:${hash}`;\n}\n\n/**\n * Verify a plaintext API key against a stored \"salt:hash\" string produced by\n * {@link hashApiKey}. Uses constant-time comparison.\n */\nexport function verifyApiKey(apiKey: string, stored: string): boolean {\n const [salt, hash] = stored.split(\":\");\n if (!salt || !hash) return false;\n try {\n const computed = scryptSync(apiKey, salt, 32);\n const expected = Buffer.from(hash, \"hex\");\n if (computed.length !== expected.length) return false;\n return timingSafeEqual(computed, expected);\n } catch {\n return false;\n }\n}\n\n// ── atomic file write ──\n\n/** Write `data` to `filePath` atomically (tmp + rename). */\nexport async function writeAtomic(filePath: string, data: Buffer): Promise<void> {\n const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, data, { mode: 0o600 });\n await fs.rename(tmp, filePath);\n}\n\n// ── keytar helpers (private) ──\n\nasync function tryKeytarGet(): Promise<Buffer | undefined> {\n try {\n const mod = (await import(\"keytar\")) as typeof import(\"keytar\");\n const val = await mod.getPassword(\"hypermail-mcp\", \"master\");\n if (val) {\n const buf = Buffer.from(val, \"base64\");\n if (buf.length === KEY_LEN) return buf;\n }\n } catch {\n /* keytar not installed or unsupported platform */\n }\n return undefined;\n}\n\nasync function tryKeytarSet(key: Buffer): Promise<void> {\n try {\n const mod = (await import(\"keytar\")) as typeof import(\"keytar\");\n await mod.setPassword(\"hypermail-mcp\", \"master\", key.toString(\"base64\"));\n } catch {\n /* ignore */\n }\n}\n","import path from \"node:path\";\nimport { promises as fs } from \"node:fs\";\n\nimport {\n encrypt,\n decrypt,\n resolveDataDir,\n resolveKey,\n writeAtomic,\n hashApiKey,\n verifyApiKey,\n} from \"./crypto.js\";\n\n/**\n * One stored agent. API keys are hashed at rest (scrypt) — the plaintext key\n * is never stored. The `id` is a human-readable slug; `accounts` lists the\n * email addresses this agent is authorized to operate on.\n */\nexport interface AgentRecord {\n id: string;\n /** scrypt hash of the agent's API key (format: \"salt:hash\", both hex). */\n apiKeyHash: string;\n name: string;\n /** Email addresses assigned to this agent. */\n accounts: string[];\n /** Whether this agent can provision/remove accounts. */\n provisioning: boolean;\n createdAt: string;\n}\n\ninterface AgentStoreFile {\n version: 1;\n agents: AgentRecord[];\n}\n\nexport interface AgentStoreOpenOptions {\n dataDir?: string;\n /** Inject the encryption key directly (mostly for tests). */\n key?: Buffer;\n}\n\nconst FILE_NAME = \"agents.json.enc\";\n\nexport class AgentStore {\n private constructor(\n private readonly filePath: string,\n private readonly key: Buffer,\n private data: AgentStoreFile,\n ) {}\n\n static async open(opts: AgentStoreOpenOptions = {}): Promise<AgentStore> {\n const dataDir = resolveDataDir(opts.dataDir);\n await fs.mkdir(dataDir, { recursive: true, mode: 0o700 });\n const filePath = path.join(dataDir, FILE_NAME);\n const key = opts.key ?? (await resolveKey(dataDir));\n\n let data: AgentStoreFile;\n try {\n const buf = await fs.readFile(filePath);\n data = decrypt<AgentStoreFile>(buf, key);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n data = { version: 1, agents: [] };\n } else {\n throw err;\n }\n }\n return new AgentStore(filePath, key, data);\n }\n\n // ── queries ──\n\n listAgents(): AgentRecord[] {\n return this.data.agents.map((a) => ({ ...a }));\n }\n\n getAgent(id: string): AgentRecord | undefined {\n const rec = this.data.agents.find((a) => a.id === id);\n return rec ? { ...rec } : undefined;\n }\n\n /**\n * Look up an agent by plaintext API key. Hashes the incoming key and\n * compares against stored hashes with constant-time comparison.\n * Returns undefined if no agent matches.\n */\n findAgentByApiKey(apiKey: string): AgentRecord | undefined {\n for (const agent of this.data.agents) {\n if (verifyApiKey(apiKey, agent.apiKeyHash)) {\n return { ...agent };\n }\n }\n return undefined;\n }\n\n // ── mutations ──\n\n /**\n * Add or update an agent. If `plaintextApiKey` is provided, it is hashed\n * and stored; if omitted, the existing hash is preserved (useful for\n * updates that don't change the key).\n */\n async upsertAgent(\n rec: Omit<AgentRecord, \"apiKeyHash\" | \"createdAt\"> & {\n plaintextApiKey?: string;\n },\n ): Promise<AgentRecord> {\n const idx = this.data.agents.findIndex((a) => a.id === rec.id);\n const existing = idx >= 0 ? this.data.agents[idx] : undefined;\n const apiKeyHash = rec.plaintextApiKey\n ? hashApiKey(rec.plaintextApiKey)\n : existing?.apiKeyHash;\n if (!apiKeyHash) {\n throw new Error(\n `agent ${rec.id}: must provide plaintextApiKey for new agents`,\n );\n }\n\n const next: AgentRecord = {\n id: rec.id,\n apiKeyHash,\n name: rec.name,\n accounts: [...(rec.accounts ?? [])],\n provisioning: rec.provisioning ?? false,\n createdAt: existing?.createdAt ?? new Date().toISOString(),\n };\n\n if (idx >= 0) {\n this.data.agents[idx] = next;\n } else {\n this.data.agents.push(next);\n }\n await this.flush();\n return { ...next };\n }\n\n async removeAgent(id: string): Promise<boolean> {\n const before = this.data.agents.length;\n this.data.agents = this.data.agents.filter((a) => a.id !== id);\n if (this.data.agents.length === before) return false;\n await this.flush();\n return true;\n }\n\n /**\n * Assign an email account to an agent. Idempotent — no error if already\n * assigned. Auto-assignment from `add_account` in HTTP mode calls this.\n */\n async assignAccount(agentId: string, email: string): Promise<AgentRecord> {\n const norm = email.trim().toLowerCase();\n const agent = this.data.agents.find((a) => a.id === agentId);\n if (!agent) throw new Error(`agent ${agentId} not found`);\n if (!agent.accounts.includes(norm)) {\n agent.accounts.push(norm);\n await this.flush();\n }\n return { ...agent };\n }\n\n /**\n * Remove an email account from an agent's assignments. Idempotent.\n */\n async unassignAccount(agentId: string, email: string): Promise<AgentRecord> {\n const norm = email.trim().toLowerCase();\n const agent = this.data.agents.find((a) => a.id === agentId);\n if (!agent) throw new Error(`agent ${agentId} not found`);\n agent.accounts = agent.accounts.filter((a) => a !== norm);\n await this.flush();\n return { ...agent };\n }\n\n // ── persistence ──\n\n private async flush(): Promise<void> {\n const buf = encrypt(this.data, this.key);\n await writeAtomic(this.filePath, buf);\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\n\nimport { ResponseType, type Client } from \"@microsoft/microsoft-graph-client\";\n\nimport { parseInlineImages } from \"../shared/inline-images.js\";\n\nimport type { AccountRecord, AccountStore } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n EmailFull,\n EmailProvider,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n SendInput,\n EmailAddress,\n} from \"../types.js\";\nimport { OutlookClientFactory } from \"./client.js\";\nimport {\n awaitDeviceCodeReady,\n beginDeviceCode,\n type DeviceCodeBegin,\n type SerializedTokens,\n} from \"./auth.js\";\n\n// ---------- inline image conversion ----------\n\ninterface InlineAttachment {\n \"@odata.type\": string;\n name: string;\n contentType: string;\n contentId: string;\n contentBytes: string;\n isInline: boolean;\n}\n\n/**\n * Scans HTML for data:image/...;base64,... URIs, extracts the raw base64\n * data, assigns unique contentIds, and returns the transformed body\n * (with src=\"cid:...\" references) plus an array of inline fileAttachment\n * objects ready for the Graph API.\n *\n * Delegates the HTML parsing to the shared {@link parseInlineImages} and\n * then wraps each image in an Outlook-specific `@odata.type` attachment.\n *\n * Pass-through when there are no matches — returns the original body with\n * an empty attachments array.\n */\nexport function convertInlineImages(body: string): {\n body: string;\n attachments: InlineAttachment[];\n} {\n const { body: transformed, images } = parseInlineImages(body);\n const attachments: InlineAttachment[] = images.map((img) => ({\n \"@odata.type\": \"#microsoft.graph.fileAttachment\",\n name: img.filename,\n contentType: img.contentType,\n contentId: img.cid,\n contentBytes: img.contentBytes,\n isInline: true,\n }));\n return { body: transformed, attachments };\n}\n\ninterface PendingFlow {\n begin: DeviceCodeBegin;\n emailHint?: string;\n startedAt: number;\n settled: \"pending\" | \"ready\" | \"error\" | \"expired\";\n account?: AccountRecord;\n error?: string;\n}\n\nexport interface OutlookProviderOptions {\n store: AccountStore;\n clientId?: string;\n tenantId?: string;\n}\n\nexport class OutlookProvider implements EmailProvider {\n readonly id = \"outlook\" as const;\n private readonly clients: OutlookClientFactory;\n private readonly pending = new Map<string, PendingFlow>();\n private readonly clientId?: string;\n private readonly tenantId?: string;\n\n constructor(private readonly opts: OutlookProviderOptions) {\n this.clientId = opts.clientId;\n this.tenantId = opts.tenantId;\n this.clients = new OutlookClientFactory(opts.store, opts.clientId, opts.tenantId);\n }\n\n // ---------- account lifecycle ----------\n\n async addAccount(input: AddAccountInput): Promise<AddAccountResult> {\n const begin = beginDeviceCode(undefined, this.clientId, this.tenantId);\n await awaitDeviceCodeReady(begin);\n\n const handle = randomUUID();\n const flow: PendingFlow = {\n begin,\n emailHint: input.email,\n startedAt: Date.now(),\n settled: \"pending\",\n };\n this.pending.set(handle, flow);\n\n // Fire-and-forget: when the user finishes, persist and update flow.\n begin.result\n .then(async ({ tokens, account }) => {\n const email = (account.username || input.email || \"\").toLowerCase();\n if (!email) {\n flow.settled = \"error\";\n flow.error = \"no email returned from Microsoft account\";\n return;\n }\n const rec: AccountRecord = {\n email,\n provider: \"outlook\",\n displayName: account.name ?? undefined,\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n };\n const saved = await this.opts.store.upsertAccount(rec);\n flow.account = saved;\n flow.settled = \"ready\";\n })\n .catch((err: unknown) => {\n flow.settled = \"error\";\n flow.error = err instanceof Error ? err.message : String(err);\n });\n\n return {\n status: \"pending\",\n handle,\n verification: {\n userCode: begin.userCode,\n verificationUri: begin.verificationUri,\n expiresAt: begin.expiresAt,\n message: begin.message,\n },\n };\n }\n\n async completeAddAccount(handle: string): Promise<CompleteAddAccountResult> {\n const flow = this.pending.get(handle);\n if (!flow) return { status: \"error\", error: \"unknown handle\" };\n // expire after 20 minutes regardless\n if (Date.now() - flow.startedAt > 20 * 60_000 && flow.settled === \"pending\") {\n flow.settled = \"expired\";\n flow.begin.cancel();\n }\n if (flow.settled === \"ready\" && flow.account) {\n this.pending.delete(handle);\n return { status: \"ready\", account: flow.account };\n }\n if (flow.settled === \"error\") {\n this.pending.delete(handle);\n return { status: \"error\", error: flow.error ?? \"unknown error\" };\n }\n if (flow.settled === \"expired\") {\n this.pending.delete(handle);\n return { status: \"expired\" };\n }\n return { status: \"pending\" };\n }\n\n // ---------- email ops ----------\n\n async listEmails(\n account: AccountRecord,\n opts: ListEmailsOptions,\n ): Promise<ListEmailsResult> {\n const client = this.clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n const folder = opts.folder ?? \"inbox\";\n const filterParts: string[] = [];\n if (opts.unreadOnly) filterParts.push(\"isRead eq false\");\n\n let req = client\n .api(`/me/mailFolders/${encodeURIComponent(folder)}/messages`)\n .top(limit)\n .skip(opts.skip ?? 0)\n .select([\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n ].join(\",\"))\n .orderby(\"receivedDateTime DESC\");\n\n if (filterParts.length > 0) req = req.filter(filterParts.join(\" and \"));\n\n const res = (await req.get()) as { value: GraphMessage[]; \"@odata.nextLink\"?: string };\n return {\n items: res.value.map((m) => mapSummary(m, folder)),\n hasMore: !!res[\"@odata.nextLink\"],\n };\n }\n\n async searchEmails(\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n ): Promise<EmailSummary[]> {\n const client = this.clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n // $search requires the ConsistencyLevel: eventual header\n const res = (await client\n .api(\"/me/messages\")\n .header(\"ConsistencyLevel\", \"eventual\")\n .top(limit)\n .search(`\"${query.replace(/\"/g, '\\\\\"')}\"`)\n .select(\n [\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n ].join(\",\"),\n )\n .get()) as { value: GraphMessage[] };\n return res.value.map((m) => mapSummary(m));\n }\n\n async readEmail(account: AccountRecord, id: string): Promise<EmailFull> {\n const client = this.clients.get(account);\n const m = (await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .select(\n [\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"ccRecipients\",\n \"bccRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n \"body\",\n ].join(\",\"),\n )\n .get()) as GraphMessage;\n\n let attachments: EmailFull[\"attachments\"] = undefined;\n if (m.hasAttachments) {\n try {\n const attRes = (await client\n .api(`/me/messages/${encodeURIComponent(id)}/attachments`)\n .select(\"id,name,contentType,size\")\n .get()) as { value: GraphAttachment[] };\n attachments = attRes.value.map((a) => ({\n id: a.id,\n name: a.name,\n contentType: a.contentType,\n size: a.size,\n }));\n } catch {\n /* ignore attachment listing failure */\n }\n }\n\n const summary = mapSummary(m);\n const body = m.body;\n return {\n ...summary,\n cc: (m.ccRecipients ?? []).map(mapRecipient),\n bcc: (m.bccRecipients ?? []).map(mapRecipient),\n bodyText: body?.contentType === \"text\" ? body.content : undefined,\n bodyHtml: body?.contentType === \"html\" ? body.content : undefined,\n attachments,\n };\n }\n\n async readAttachment(\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n ): Promise<AttachmentContent> {\n const client = this.clients.get(account);\n // First, get the attachment metadata to know the filename\n const att = (await client\n .api(`/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`)\n .select(\"name,contentType\")\n .get()) as { name: string; contentType?: string };\n\n // Download the raw content as ArrayBuffer\n const data = (await client\n .api(`/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}/$value`)\n .responseType(ResponseType.ARRAYBUFFER)\n .get()) as ArrayBuffer;\n\n // Write to temp file with original name\n const outPath = pathJoin(tmpdir(), att.name);\n writeFileSync(outPath, Buffer.from(data));\n\n return {\n name: att.name,\n contentType: att.contentType,\n path: outPath,\n };\n }\n\n // Shared helper — creates a draft from a reference message (forward or\n // reply), prepends our composed body before the existing content, and\n // attaches inline images. Returns the draft message ID.\n private async buildDraftFromReference(\n client: Client,\n createEndpoint: string,\n createPayload: Record<string, unknown>,\n converted: { body: string; attachments: InlineAttachment[] },\n ): Promise<string> {\n const draft: { id: string } = await client\n .api(createEndpoint)\n .post(createPayload);\n\n const draftMsg: { body?: { content?: string; contentType?: string } } =\n await client.api(`/me/messages/${draft.id}`).select(\"body\").get();\n\n const draftBody = draftMsg.body?.content ?? \"\";\n const draftContentType = draftMsg.body?.contentType ?? \"HTML\";\n const spacer = '<div style=\"line-height:12px\"><br></div>';\n const prepend = converted.body + spacer;\n const finalBody = draftBody.includes(\"<body\")\n ? draftBody.replace(/(<body[^>]*>)/i, `$1${prepend}`)\n : prepend + draftBody;\n\n await client.api(`/me/messages/${draft.id}`).patch({\n body: { contentType: draftContentType, content: finalBody },\n });\n\n for (const att of converted.attachments) {\n await client.api(`/me/messages/${draft.id}/attachments`).post(att);\n }\n\n return draft.id;\n }\n\n // Shared backend for sendEmail and saveDraft — handles forward, reply, and\n // new-message paths. The `mode` controls whether the message is sent\n // immediately or saved as a draft.\n private async sendOrSave(\n account: AccountRecord,\n msg: SendInput,\n mode: \"send\" | \"draft\",\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n const converted = convertInlineImages(msg.body);\n\n const toRecipients = msg.to.map(toRecipient);\n const ccRecipients = (msg.cc ?? []).map(toRecipient);\n const bccRecipients = (msg.bcc ?? []).map(toRecipient);\n\n // Forward — build a forward draft, then send if mode is \"send\".\n if (msg.forwardMessageId) {\n const draftId = await this.buildDraftFromReference(\n client,\n `/me/messages/${encodeURIComponent(msg.forwardMessageId)}/createForward`,\n { message: { toRecipients, ccRecipients, bccRecipients }, comment: \"\" },\n converted,\n );\n if (mode === \"send\") {\n await client.api(`/me/messages/${draftId}/send`).post({});\n }\n return { id: draftId };\n }\n\n // Reply — build a reply draft, then send if mode is \"send\".\n if (msg.inReplyTo) {\n const createEndpoint = msg.replyAll\n ? `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReplyAll`\n : `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReply`;\n const draftId = await this.buildDraftFromReference(\n client, createEndpoint, {}, converted,\n );\n if (mode === \"send\") {\n await client.api(`/me/messages/${draftId}/send`).post({});\n }\n return { id: draftId };\n }\n\n // New email — sendMail (mode=send) or POST /me/messages (mode=draft).\n const messagePayload: Record<string, unknown> = {\n subject: msg.subject,\n body: {\n contentType: msg.isHtml ? \"HTML\" : \"Text\",\n content: converted.body,\n },\n toRecipients,\n ccRecipients,\n bccRecipients,\n };\n if (converted.attachments.length > 0) {\n messagePayload.attachments = converted.attachments;\n }\n\n if (mode === \"send\") {\n await client.api(\"/me/sendMail\").post({\n message: messagePayload,\n saveToSentItems: true,\n });\n // Graph's sendMail returns 202 with no body; we don't have an id back.\n return { id: \"\" };\n }\n\n const draft: { id: string } = await client\n .api(\"/me/messages\")\n .post(messagePayload);\n return { id: draft.id };\n }\n\n async sendEmail(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n return this.sendOrSave(account, msg, \"send\");\n }\n\n async saveDraft(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n return this.sendOrSave(account, msg, \"draft\");\n }\n\n async updateDraft(\n account: AccountRecord,\n id: string,\n update: DraftUpdateInput,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n const payload: Record<string, unknown> = {};\n\n if (update.subject !== undefined) {\n payload.subject = update.subject;\n }\n if (update.to !== undefined) {\n payload.toRecipients = update.to.map(toRecipient);\n }\n if (update.cc !== undefined) {\n payload.ccRecipients = update.cc.map(toRecipient);\n }\n if (update.bcc !== undefined) {\n payload.bccRecipients = update.bcc.map(toRecipient);\n }\n if (update.body !== undefined) {\n const converted = convertInlineImages(update.body);\n payload.body = {\n contentType: update.isHtml ? \"HTML\" : \"Text\",\n content: converted.body,\n };\n if (converted.attachments.length > 0) {\n // Patch existing inline attachments: Graph will replace all\n // attachments on the message. We send only the new ones.\n payload.attachments = converted.attachments;\n }\n }\n\n await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .patch(payload);\n\n return { id };\n }\n\n async moveEmail(\n account: AccountRecord,\n id: string,\n destinationId: string,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/messages/${encodeURIComponent(id)}/move`)\n .post({ destinationId });\n }\n\n async sendDraft(\n account: AccountRecord,\n id: string,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n await client.api(`/me/messages/${encodeURIComponent(id)}/send`).post({});\n return { id };\n }\n\n async addAttachmentToDraft(\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n ): Promise<{ id: string; attachment: { id: string; name: string; contentType?: string } }> {\n const client = this.clients.get(account);\n const att = (await client\n .api(`/me/messages/${encodeURIComponent(draftId)}/attachments`)\n .post({\n \"@odata.type\": \"#microsoft.graph.fileAttachment\",\n name,\n contentType: contentType ?? \"application/octet-stream\",\n contentBytes,\n })) as { id: string; name: string; contentType?: string };\n return {\n id: draftId,\n attachment: { id: att.id, name: att.name, contentType: att.contentType },\n };\n }\n\n async markRead(\n account: AccountRecord,\n id: string,\n isRead: boolean,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .patch({ isRead });\n }\n\n async listFolders(\n account: AccountRecord,\n opts: ListFoldersOptions,\n ): Promise<FolderInfo[]> {\n const client = this.clients.get(account);\n const endpoint = opts.parentFolderId\n ? `/me/mailFolders/${encodeURIComponent(opts.parentFolderId)}/childFolders`\n : \"/me/mailFolders\";\n const res = (await client\n .api(endpoint)\n .select([\n \"id\",\n \"displayName\",\n \"parentFolderId\",\n \"childFolderCount\",\n \"totalItemCount\",\n \"unreadItemCount\",\n ].join(\",\"))\n .get()) as { value: GraphFolder[] };\n return (res.value ?? []).map(mapFolder);\n }\n\n async createFolder(\n account: AccountRecord,\n input: CreateFolderInput,\n ): Promise<FolderInfo> {\n const client = this.clients.get(account);\n const parentId = input.parentFolderId ?? \"msgfolderroot\";\n const created = (await client\n .api(`/me/mailFolders/${encodeURIComponent(parentId)}/childFolders`)\n .post({ displayName: input.displayName })) as GraphFolder;\n return mapFolder(created);\n }\n\n async renameFolder(\n account: AccountRecord,\n folderId: string,\n newName: string,\n ): Promise<FolderInfo> {\n const client = this.clients.get(account);\n const updated = (await client\n .api(`/me/mailFolders/${encodeURIComponent(folderId)}`)\n .patch({ displayName: newName })) as GraphFolder;\n return mapFolder(updated);\n }\n\n async deleteFolder(\n account: AccountRecord,\n folderId: string,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/mailFolders/${encodeURIComponent(folderId)}`)\n .delete();\n }\n}\n\n// ---------- mapping helpers ----------\n\ninterface GraphRecipient {\n emailAddress?: { name?: string; address?: string };\n}\ninterface GraphMessage {\n id: string;\n subject?: string;\n from?: GraphRecipient;\n toRecipients?: GraphRecipient[];\n ccRecipients?: GraphRecipient[];\n bccRecipients?: GraphRecipient[];\n receivedDateTime?: string;\n bodyPreview?: string;\n isRead?: boolean;\n hasAttachments?: boolean;\n body?: { contentType?: \"text\" | \"html\"; content?: string };\n}\ninterface GraphAttachment {\n id: string;\n name: string;\n contentType?: string;\n size?: number;\n}\ninterface GraphFolder {\n id: string;\n displayName: string;\n parentFolderId?: string;\n childFolderCount: number;\n totalItemCount: number;\n unreadItemCount: number;\n}\n\nfunction mapFolder(f: GraphFolder): FolderInfo {\n return {\n id: f.id,\n displayName: f.displayName,\n parentFolderId: f.parentFolderId,\n childFolderCount: f.childFolderCount,\n totalItemCount: f.totalItemCount,\n unreadItemCount: f.unreadItemCount,\n };\n}\n\nfunction mapRecipient(r: GraphRecipient): EmailAddress {\n return {\n name: r.emailAddress?.name,\n address: r.emailAddress?.address ?? \"\",\n };\n}\n\nfunction mapSummary(m: GraphMessage, folder?: string): EmailSummary {\n return {\n id: m.id,\n subject: m.subject ?? \"\",\n from: m.from ? mapRecipient(m.from) : undefined,\n to: (m.toRecipients ?? []).map(mapRecipient),\n receivedAt: m.receivedDateTime,\n preview: m.bodyPreview,\n isRead: m.isRead,\n hasAttachments: m.hasAttachments,\n folder,\n };\n}\n\nfunction toRecipient(a: EmailAddress): GraphRecipient {\n return { emailAddress: { name: a.name, address: a.address } };\n}\n\nfunction clampLimit(v: number | undefined, dflt: number, max: number): number {\n if (!v || v <= 0) return dflt;\n return Math.min(v, max);\n}\n","import { randomUUID } from \"node:crypto\";\n\n/** A generic inline image extracted from an HTML body. */\nexport interface InlineImage {\n /** The generated Content-ID (without \"cid:\" prefix). */\n cid: string;\n /** Raw base64 content bytes (without the data:image/...;base64, prefix). */\n contentBytes: string;\n /** Full MIME type, e.g. \"image/png\". */\n contentType: string;\n /** Suggested filename, e.g. \"signature-image.png\". */\n filename: string;\n}\n\n/**\n * Parse an HTML body for `data:image/<subtype>;base64,<payload>` URIs inside\n * `src=\"...\"` attributes. Each match is replaced with a `cid:<uuid>` reference,\n * and the extracted base64 data is collected into a flat image array.\n *\n * This is provider-agnostic — each provider wraps the result into its own\n * attachment format (e.g. Outlook `@odata.type` objects or nodemailer\n * `cid` attachments).\n */\nexport function parseInlineImages(html: string): {\n body: string;\n images: InlineImage[];\n} {\n const images: InlineImage[] = [];\n // Match src=\"data:image/<subtype>;base64,<payload>\"\n // Supports png, jpg, jpeg, gif, svg+xml, webp, bmp, etc.\n const re = /src=\"data:image\\/([\\w+]+);base64,([^\"]+)\"/gi;\n\n const transformed = html.replace(re, (_fullMatch, mimeSubtype, b64) => {\n const contentId = `sig-img-${randomUUID()}`;\n const ext =\n mimeSubtype.toLowerCase().replace(/\\+/g, \"-\") === \"svg-xml\"\n ? \"svg\"\n : mimeSubtype.toLowerCase().replace(/\\+/g, \"-\");\n images.push({\n cid: contentId,\n contentBytes: b64,\n contentType: `image/${mimeSubtype}`,\n filename: `signature-image.${ext}`,\n });\n return `src=\"cid:${contentId}\"`;\n });\n\n return { body: transformed, images };\n}\n","import \"isomorphic-fetch\";\nimport {\n Client,\n type AuthenticationProvider,\n} from \"@microsoft/microsoft-graph-client\";\n\nimport type { AccountStore, AccountRecord } from \"../../store/account-store.js\";\nimport { acquireAccessToken, isSerializedTokens, type SerializedTokens } from \"./auth.js\";\n\n/**\n * Builds a Graph `Client` bound to a stored account. The client uses an\n * `AuthenticationProvider` that calls msal silently on every request, and\n * writes the (possibly-refreshed) cache back into the AccountStore.\n *\n * Clients are cached per email since the underlying SDK reuses connections.\n */\nexport class OutlookClientFactory {\n private readonly cache = new Map<string, Client>();\n /** Serialize token refreshes per email to prevent concurrent-refresh races. */\n private readonly refreshLocks = new Map<string, Promise<string>>();\n\n constructor(\n private readonly store: AccountStore,\n private readonly clientId?: string,\n private readonly tenantId?: string,\n ) {}\n\n get(account: AccountRecord): Client {\n const key = account.email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) return existing;\n\n const store = this.store;\n const refreshLocks = this.refreshLocks;\n const provider: AuthenticationProvider = {\n getAccessToken: async () => {\n const existing = refreshLocks.get(key);\n if (existing) {\n try {\n return await existing;\n } catch {\n // previous refresh failed — fall through to retry\n }\n }\n const promise = (async (): Promise<string> => {\n const fresh = store.getAccount(account.email) ?? account;\n if (!isSerializedTokens(fresh.tokens)) {\n throw new Error(\n \"Outlook account tokens are missing or corrupted — re-run add_account\",\n );\n }\n const tokens: SerializedTokens = fresh.tokens;\n const { accessToken, tokens: nextTokens } = await acquireAccessToken(\n tokens,\n undefined,\n this.clientId,\n this.tenantId,\n );\n if (nextTokens.msalCache !== tokens.msalCache) {\n store\n .upsertAccount({\n ...fresh,\n tokens: nextTokens as unknown as Record<string, unknown>,\n })\n .catch(() => {\n /* swallow — next call will refresh again */\n });\n }\n return accessToken;\n })();\n refreshLocks.set(key, promise);\n try {\n return await promise;\n } finally {\n refreshLocks.delete(key);\n }\n },\n };\n\n const client = Client.initWithMiddleware({ authProvider: provider });\n this.cache.set(key, client);\n return client;\n }\n\n /** Drop a cached client (e.g. after removeAccount). */\n invalidate(email: string): void {\n this.cache.delete(email.toLowerCase());\n }\n}\n","import {\n PublicClientApplication,\n type Configuration,\n type AuthenticationResult,\n type AccountInfo,\n} from \"@azure/msal-node\";\n\n/**\n * Public client app id. Default is the well-known `ms-365` client id used by\n * the softeria/ms-365-mcp-server project — it's a public client registered\n * for personal MSA + multi-tenant work/school. Users can override via\n * MS_CLIENT_ID for their own Entra app registrations.\n */\nconst DEFAULT_CLIENT_ID = \"084a3e9f-a9f4-43f7-89f9-d229cf97853e\";\n// ^ Pre-registered public client app (same one used by softeria/ms-365-mcp-server).\n// Supports personal MSA + multi-tenant work/school via device-code flow.\n// Operators should set MS_CLIENT_ID to a client they control for production.\n\nconst DEFAULT_SCOPES = [\n \"offline_access\",\n \"User.Read\",\n \"Mail.ReadWrite\",\n \"Mail.Send\",\n];\n\nexport interface DeviceCodeBegin {\n userCode: string;\n verificationUri: string;\n message: string;\n expiresAt: string; // ISO\n /** Resolves with the auth result once the user completes the flow. */\n result: Promise<{ tokens: SerializedTokens; account: AccountInfo }>;\n /** Aborts the in-flight polling promise. */\n cancel(): void;\n}\n\nexport interface SerializedTokens {\n /** MSAL cache JSON, encrypted at rest by the account store. */\n msalCache: string;\n /** Home account id used to look up the account in the rehydrated cache. */\n homeAccountId: string;\n /** Tenant id captured at sign-in. */\n tenantId: string;\n /** Username captured at sign-in (typically the primary email). */\n username: string;\n scopes: string[];\n}\n\n/** Type guard — validates that an unknown value has the shape of SerializedTokens. */\nexport function isSerializedTokens(obj: unknown): obj is SerializedTokens {\n if (typeof obj !== \"object\" || obj === null) return false;\n const o = obj as Record<string, unknown>;\n return (\n typeof o.msalCache === \"string\" &&\n typeof o.homeAccountId === \"string\" &&\n typeof o.tenantId === \"string\" &&\n typeof o.username === \"string\" &&\n Array.isArray(o.scopes)\n );\n}\n\nfunction makeConfig(prevCacheJson?: string, clientIdOverride?: string, tenantOverride?: string): Configuration {\n const clientId = clientIdOverride || process.env.MS_CLIENT_ID || DEFAULT_CLIENT_ID;\n const tenant = tenantOverride || process.env.MS_TENANT_ID || \"common\";\n return {\n auth: {\n clientId,\n authority: `https://login.microsoftonline.com/${tenant}`,\n },\n cache: prevCacheJson\n ? {\n // msal-node supports an in-memory cache plugin; we hydrate manually\n // below via deserialize after construction.\n }\n : undefined,\n };\n}\n\nexport function buildPca(prevCacheJson?: string, clientIdOverride?: string, tenantOverride?: string): PublicClientApplication {\n const pca = new PublicClientApplication(makeConfig(prevCacheJson, clientIdOverride, tenantOverride));\n if (prevCacheJson) {\n pca.getTokenCache().deserialize(prevCacheJson);\n }\n return pca;\n}\n\n/**\n * Start a device-code flow. The returned `result` promise resolves once the\n * user has entered the code and consented; callers should poll it (or await it)\n * via `complete_add_account`.\n */\nexport function beginDeviceCode(\n scopes: string[] = DEFAULT_SCOPES,\n clientIdOverride?: string,\n tenantOverride?: string,\n): DeviceCodeBegin {\n const pca = buildPca(undefined, clientIdOverride, tenantOverride);\n let resolve!: (v: { tokens: SerializedTokens; account: AccountInfo }) => void;\n let reject!: (err: unknown) => void;\n const result = new Promise<{ tokens: SerializedTokens; account: AccountInfo }>(\n (res, rej) => {\n resolve = res;\n reject = rej;\n },\n );\n\n // We capture the deviceCodeCallback synchronously to surface the user-facing\n // info back out via this object before awaiting the long-running poll.\n let userCode = \"\";\n let verificationUri = \"\";\n let message = \"\";\n let expiresAt = new Date(Date.now() + 15 * 60_000).toISOString();\n let aborted = false;\n\n const ready = new Promise<void>((r) => {\n pca\n .acquireTokenByDeviceCode({\n scopes,\n deviceCodeCallback: (info) => {\n if (!info.userCode || !info.verificationUri) {\n // MSAL may fire the callback with an empty object if the\n // downstream HTTP request fails — reject so the caller\n // gets a clear error instead of silent empty strings.\n reject(\n new Error(\n \"Microsoft device-code endpoint returned no code. \" +\n \"Check MS_CLIENT_ID is a valid Azure Entra public-client application.\",\n ),\n );\n return;\n }\n userCode = info.userCode;\n verificationUri = info.verificationUri;\n message = info.message;\n if (info.expiresIn) {\n expiresAt = new Date(Date.now() + info.expiresIn * 1000).toISOString();\n }\n r();\n },\n })\n .then((authResult: AuthenticationResult | null) => {\n if (aborted) return;\n if (!authResult || !authResult.account) {\n reject(new Error(\"device-code flow returned no account\"));\n return;\n }\n const cache = pca.getTokenCache().serialize();\n const tokens: SerializedTokens = {\n msalCache: cache,\n homeAccountId: authResult.account.homeAccountId,\n tenantId: authResult.account.tenantId,\n username: authResult.account.username,\n scopes,\n };\n resolve({ tokens, account: authResult.account });\n })\n .catch((err) => {\n if (!aborted) reject(err);\n });\n });\n\n // Surface device-code info synchronously via a wrapper Promise:\n // we return the object but its strings are populated once `ready` settles.\n // To keep the API simple, we attach a getter that callers must `await` on.\n // Instead of getters, we wait for `ready` inside the begin helper:\n return {\n // these are placeholders until ready resolves\n get userCode() {\n return userCode;\n },\n get verificationUri() {\n return verificationUri;\n },\n get message() {\n return message;\n },\n get expiresAt() {\n return expiresAt;\n },\n result,\n cancel() {\n aborted = true;\n },\n // hidden helper for the caller to await initial code\n // (typed via a cast below where used)\n ...({ _ready: ready } as Record<string, unknown>),\n } as DeviceCodeBegin;\n}\n\n/** Await `_ready` so the user-code fields are populated. */\nexport async function awaitDeviceCodeReady(b: DeviceCodeBegin): Promise<void> {\n const r = (b as unknown as { _ready: Promise<void> })._ready;\n await r;\n}\n\n/**\n * Acquire a fresh access token for a stored account, refreshing silently from\n * the persisted MSAL cache. Returns the (possibly-updated) cache so the caller\n * can write it back to the store.\n */\nexport async function acquireAccessToken(\n tokens: SerializedTokens,\n scopes: string[] = DEFAULT_SCOPES,\n clientIdOverride?: string,\n tenantOverride?: string,\n): Promise<{ accessToken: string; tokens: SerializedTokens }> {\n const pca = buildPca(tokens.msalCache, clientIdOverride, tenantOverride);\n const cache = pca.getTokenCache();\n const account =\n (await cache.getAccountByHomeId(tokens.homeAccountId)) ??\n (await cache.getAllAccounts()).find((a) => a.username === tokens.username);\n if (!account) {\n throw new Error(\"no MSAL account in cache — re-run add_account\");\n }\n const res = await pca.acquireTokenSilent({ account, scopes });\n if (!res?.accessToken) {\n throw new Error(\"acquireTokenSilent returned no access token\");\n }\n const next: SerializedTokens = {\n ...tokens,\n msalCache: cache.serialize(),\n scopes,\n };\n return { accessToken: res.accessToken, tokens: next };\n}\n","import { ImapFlow } from \"imapflow\";\nimport type { Readable } from \"node:stream\";\nimport nodemailer from \"nodemailer\";\nimport type { Transporter } from \"nodemailer\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\n\n// ---------- token shape ----------\n\nexport interface ImapTokens {\n host: string;\n port: number;\n secure: boolean;\n user: string;\n password: string;\n smtpHost: string;\n smtpPort: number;\n smtpSecure: boolean;\n}\n\n/** Type guard — validates that an unknown value has the shape of ImapTokens. */\nexport function isImapTokens(obj: unknown): obj is ImapTokens {\n if (typeof obj !== \"object\" || obj === null) return false;\n const o = obj as Record<string, unknown>;\n return (\n typeof o.host === \"string\" &&\n typeof o.port === \"number\" &&\n typeof o.user === \"string\" &&\n typeof o.password === \"string\" &&\n typeof o.smtpHost === \"string\" &&\n typeof o.smtpPort === \"number\"\n );\n}\n\n/** Extract IMAP tokens from an account record, throwing if malformed. */\nexport function extractTokens(account: AccountRecord): ImapTokens {\n if (!isImapTokens(account.tokens)) {\n throw new Error(\n \"IMAP account tokens are missing or corrupted — re-run add_account\",\n );\n }\n return account.tokens as ImapTokens;\n}\n\n// ---------- client ----------\n\n/**\n * Per-account IMAP+SMTP client. Wraps an {@link ImapFlow} connection and a\n * {@link Transporter} from nodemailer. The factory caches instances so a\n * single account reuses its connection across calls.\n */\nexport class ImapClient {\n private imap: ImapFlow | null = null;\n private transporter: Transporter | null = null;\n private connecting: Promise<void> | null = null;\n\n constructor(private readonly tokens: ImapTokens) {}\n\n /** Get (or create) the ImapFlow instance. */\n async getImap(): Promise<ImapFlow> {\n if (this.imap) return this.imap;\n\n this.imap = new ImapFlow({\n host: this.tokens.host,\n port: this.tokens.port,\n secure: this.tokens.secure,\n auth: {\n user: this.tokens.user,\n pass: this.tokens.password,\n },\n logger: false,\n });\n\n // Connect on first use and serialise concurrent callers.\n if (!this.connecting) {\n this.connecting = this.imap\n .connect()\n .catch((err) => {\n // Clear state so next caller retries\n this.imap = null;\n this.connecting = null;\n throw err;\n });\n }\n await this.connecting;\n return this.imap;\n }\n\n /** Get (or create) a nodemailer SMTP transporter. */\n getTransporter(): Transporter {\n if (this.transporter) return this.transporter;\n this.transporter = nodemailer.createTransport({\n host: this.tokens.smtpHost,\n port: this.tokens.smtpPort,\n secure: this.tokens.smtpSecure,\n auth: {\n user: this.tokens.user,\n pass: this.tokens.password,\n },\n });\n return this.transporter;\n }\n\n /**\n * Acquire a mailbox lock and run `fn` with the mailbox selected.\n * Releases the lock automatically after `fn` completes.\n */\n async withMailbox<T>(mailbox: string, fn: (imap: ImapFlow) => Promise<T>): Promise<T> {\n const imap = await this.getImap();\n const lock = await imap.getMailboxLock(mailbox);\n try {\n return await fn(imap);\n } finally {\n lock.release();\n }\n }\n\n /** Disconnect IMAP and close the SMTP pool. */\n async disconnect(): Promise<void> {\n if (this.imap) {\n try {\n await this.imap.logout();\n } catch {\n /* ignore */\n }\n this.imap = null;\n this.connecting = null;\n }\n if (this.transporter) {\n this.transporter.close();\n this.transporter = null;\n }\n }\n}\n\n// ---------- factory ----------\n\n/**\n * Caches {@link ImapClient} instances per account email so connections are\n * reused across calls. Analogous to {@link OutlookClientFactory}.\n */\nexport class ImapClientFactory {\n private readonly cache = new Map<string, ImapClient>();\n\n get(account: AccountRecord): ImapClient {\n const key = account.email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) return existing;\n\n const tokens = extractTokens(account);\n const client = new ImapClient(tokens);\n this.cache.set(key, client);\n return client;\n }\n\n /** Drop a cached client (e.g. after removeAccount). */\n invalidate(email: string): void {\n const key = email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) {\n existing.disconnect().catch(() => {});\n this.cache.delete(key);\n }\n }\n}\n","import { createWriteStream } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { Readable } from \"node:stream\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AttachmentContent,\n EmailFull,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n} from \"../types.js\";\nimport { ImapClientFactory } from \"./client.js\";\nimport {\n BodyNode,\n clampLimit,\n decodeId,\n findAttachments,\n findPartByType,\n ImapEnvelope,\n mapSummary,\n mapEnvelopeAddr,\n mapMailboxToListEntry,\n ImapMailboxEntry,\n resolveFolder,\n} from \"./helpers.js\";\n\n/**\n * Browse operations for IMAP — list, search, read emails, attachments,\n * and folders. All functions are pure and take the client factory as\n * the first argument so the ImapProvider class can delegate to them.\n */\n\nexport async function listEmails(\n clients: ImapClientFactory,\n account: AccountRecord,\n opts: ListEmailsOptions,\n): Promise<ListEmailsResult> {\n const client = clients.get(account);\n const folder = resolveFolder(opts.folder ?? \"INBOX\");\n const limit = clampLimit(opts.limit, 25, 100);\n const skip = opts.skip ?? 0;\n\n return client.withMailbox(folder, async (imap) => {\n const searchCriteria: Record<string, unknown> = {};\n if (opts.unreadOnly) searchCriteria.seen = false;\n\n const allUids = (\n Object.keys(searchCriteria).length > 0\n ? await imap.search(searchCriteria, { uid: true })\n : await imap.search({ all: true }, { uid: true })\n ) as number[];\n\n allUids.sort((a, b) => b - a);\n const pageUids = allUids.slice(skip, skip + limit);\n const hasMore = skip + limit < allUids.length;\n\n if (pageUids.length === 0) {\n return { items: [], hasMore };\n }\n\n const messages = await imap.fetchAll(\n pageUids,\n { envelope: true, flags: true },\n { uid: true },\n );\n\n const items: EmailSummary[] = [];\n for (const msg of messages) {\n items.push(\n mapSummary(\n msg.uid as number,\n folder,\n msg.envelope as ImapEnvelope,\n msg.flags as Set<string>,\n ),\n );\n }\n return { items, hasMore };\n });\n}\n\nexport async function searchEmails(\n clients: ImapClientFactory,\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n): Promise<EmailSummary[]> {\n const client = clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n\n return client.withMailbox(\"INBOX\", async (imap) => {\n const uids = (await imap.search({ text: query }, { uid: true })) as number[];\n uids.sort((a, b) => b - a);\n const pageUids = uids.slice(0, limit);\n\n if (pageUids.length === 0) return [];\n\n const messages = await imap.fetchAll(\n pageUids,\n { envelope: true, flags: true },\n { uid: true },\n );\n\n return messages.map((msg) =>\n mapSummary(\n msg.uid as number,\n \"INBOX\",\n msg.envelope as ImapEnvelope,\n msg.flags as Set<string>,\n ),\n );\n });\n}\n\nexport async function readEmail(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n): Promise<EmailFull> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n\n return client.withMailbox(folder, async (imap) => {\n const msg = await imap.fetchOne(\n uid,\n { bodyStructure: true, envelope: true, flags: true },\n { uid: true },\n );\n\n if (!msg || !msg.envelope) {\n throw new Error(`message not found: ${id}`);\n }\n\n const envelope = msg.envelope as ImapEnvelope;\n const structure = msg.bodyStructure as BodyNode;\n const flags = (msg.flags as Set<string>) ?? new Set<string>();\n\n let bodyText: string | undefined;\n let bodyHtml: string | undefined;\n\n const textPart = findPartByType(structure, \"text/plain\");\n const htmlPart = findPartByType(structure, \"text/html\");\n\n if (textPart) {\n const { content } = await imap.download(uid, textPart, { uid: true });\n const chunks: Buffer[] = [];\n for await (const chunk of content as Readable) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n bodyText = Buffer.concat(chunks).toString(\"utf-8\");\n }\n\n if (htmlPart) {\n const { content } = await imap.download(uid, htmlPart, { uid: true });\n const chunks: Buffer[] = [];\n for await (const chunk of content as Readable) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n bodyHtml = Buffer.concat(chunks).toString(\"utf-8\");\n }\n\n const attachments: EmailFull[\"attachments\"] = findAttachments(\n structure,\n ).map((a) => ({\n id: a.part,\n name: a.name,\n contentType: a.contentType,\n size: a.size,\n }));\n\n const summary = mapSummary(uid, folder, envelope, flags);\n\n return {\n ...summary,\n cc: (envelope.cc ?? []).map(mapEnvelopeAddr),\n bcc: (envelope.bcc ?? []).map(mapEnvelopeAddr),\n bodyText,\n bodyHtml,\n attachments: attachments.length > 0 ? attachments : undefined,\n hasAttachments: attachments.length > 0,\n };\n });\n}\n\nexport async function readAttachment(\n clients: ImapClientFactory,\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n): Promise<AttachmentContent> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(messageId);\n\n return client.withMailbox(folder, async (imap) => {\n const msg = (await imap.fetchOne(\n uid,\n { bodyStructure: true },\n { uid: true },\n )) as { bodyStructure?: BodyNode } | false;\n\n let name = \"attachment\";\n let contentType: string | undefined;\n if (msg && msg.bodyStructure) {\n const attachments = findAttachments(msg.bodyStructure);\n const match = attachments.find((a) => a.part === attachmentId);\n if (match) {\n name = match.name;\n contentType = match.contentType;\n }\n }\n\n const { meta, content } = await imap.download(uid, attachmentId, {\n uid: true,\n });\n\n const outPath = pathJoin(tmpdir(), name);\n await pipeline(\n content as unknown as Readable,\n createWriteStream(outPath),\n );\n\n return {\n name,\n contentType: contentType ?? (meta as { contentType?: string }).contentType,\n path: outPath,\n };\n });\n}\n\nexport async function listFolders(\n clients: ImapClientFactory,\n account: AccountRecord,\n opts: ListFoldersOptions,\n): Promise<FolderInfo[]> {\n const client = clients.get(account);\n const imap = await client.getImap();\n\n const mailboxes = await imap.list({\n statusQuery: { messages: true, unseen: true, uidNext: true },\n } as never);\n\n let results: FolderInfo[] = (\n mailboxes as unknown as ImapMailboxEntry[]\n ).map(mapMailboxToListEntry);\n\n if (opts.parentFolderId) {\n const parentPath = opts.parentFolderId;\n results = results.filter(\n (f) =>\n f.parentFolderId === parentPath ||\n (parentPath === \"INBOX\" && f.displayName === \"INBOX\"),\n );\n } else {\n // Top-level: filter out children of other folders\n const allPaths = new Set(results.map((f) => f.displayName));\n results = results.filter((f) => {\n const lastSep = f.displayName.lastIndexOf(\"/\");\n if (lastSep === -1) return true;\n const parent = f.displayName.slice(0, lastSep);\n return !allPaths.has(parent);\n });\n }\n\n return results;\n}\n","import type { EmailAddress, EmailSummary, FolderInfo } from \"../types.js\";\nimport type { AccountRecord } from \"../../store/account-store.js\";\n\n// ---------- well-known folder mapping ----------\n\nconst WELL_KNOWN_TO_IMAP: Record<string, string> = {\n archive: \"Archive\",\n deleteditems: \"Trash\",\n inbox: \"INBOX\",\n drafts: \"Drafts\",\n sentitems: \"Sent\",\n junkemail: \"Junk\",\n outbox: \"Outbox\",\n};\n\nexport function resolveFolder(wellKnownOrPath: string): string {\n return WELL_KNOWN_TO_IMAP[wellKnownOrPath.toLowerCase()] ?? wellKnownOrPath;\n}\n\n// ---------- generic ----------\n\nexport function clampLimit(v: number | undefined, dflt: number, max: number): number {\n if (!v || v <= 0) return dflt;\n return Math.min(v, max);\n}\n\n// ---------- ID encoding ----------\n\n/** Encode a folder path + numeric UID into a composite message ID. */\nexport function encodeId(folder: string, uid: number): string {\n return `${folder}/${uid}`;\n}\n\n/** Decode a composite message ID back into folder + numeric UID. */\nexport function decodeId(id: string): { folder: string; uid: number } {\n const idx = id.lastIndexOf(\"/\");\n if (idx === -1) throw new Error(`invalid message ID: ${id}`);\n const folder = id.slice(0, idx);\n const uid = Number(id.slice(idx + 1));\n if (!Number.isFinite(uid) || uid <= 0) {\n throw new Error(`invalid message UID in ID: ${id}`);\n }\n return { folder, uid };\n}\n\n// ---------- body structure helpers ----------\n\nexport interface BodyNode {\n type?: string;\n part?: string;\n encoding?: string;\n size?: number;\n disposition?: string;\n dispositionParameters?: Record<string, string>;\n parameters?: Record<string, string>;\n childNodes?: BodyNode[];\n}\n\nexport interface ImapAttachmentMeta {\n part: string;\n name: string;\n contentType?: string;\n size?: number;\n}\n\n/** Recursively collect attachment metadata from a bodyStructure node. */\nexport function findAttachments(node: BodyNode): ImapAttachmentMeta[] {\n const attachments: ImapAttachmentMeta[] = [];\n const topType = (node.type ?? \"\").split(\"/\")[0];\n\n const isAttachment =\n node.disposition === \"attachment\" ||\n (!!node.type &&\n topType !== \"text\" &&\n topType !== \"multipart\" &&\n !node.disposition);\n\n if (isAttachment) {\n attachments.push({\n part: node.part ?? \"1\",\n name:\n node.dispositionParameters?.filename ??\n node.parameters?.name ??\n \"attachment\",\n contentType: node.type,\n size: node.size,\n });\n }\n\n if (node.childNodes) {\n for (const child of node.childNodes) {\n attachments.push(...findAttachments(child));\n }\n }\n\n return attachments;\n}\n\n/**\n * Find the part number for a specific content type (e.g. \"text/plain\",\n * \"text/html\") in the body structure tree.\n */\nexport function findPartByType(\n node: BodyNode,\n contentType: string,\n): string | undefined {\n if (node.type === contentType) return node.part ?? \"1\";\n if (node.childNodes) {\n for (const child of node.childNodes) {\n const found = findPartByType(child, contentType);\n if (found) return found;\n }\n }\n return undefined;\n}\n\n// ---------- envelope mapping ----------\n\nexport interface ImapEnvelopeAddr {\n name?: string;\n address?: string;\n}\n\nexport interface ImapEnvelope {\n subject?: string;\n date?: Date;\n messageId?: string;\n inReplyTo?: string;\n from?: ImapEnvelopeAddr[];\n to?: ImapEnvelopeAddr[];\n cc?: ImapEnvelopeAddr[];\n bcc?: ImapEnvelopeAddr[];\n}\n\nexport function mapEnvelopeAddr(a: ImapEnvelopeAddr): EmailAddress {\n return { name: a.name, address: a.address ?? \"\" };\n}\n\nexport function mapSummary(\n uid: number,\n folder: string,\n envelope: ImapEnvelope,\n flags: Set<string> = new Set(),\n): EmailSummary {\n const fromAddr =\n envelope.from && envelope.from.length > 0 && envelope.from[0]\n ? mapEnvelopeAddr(envelope.from[0])\n : undefined;\n return {\n id: encodeId(folder, uid),\n subject: envelope.subject ?? \"\",\n from: fromAddr,\n to: (envelope.to ?? []).map(mapEnvelopeAddr),\n receivedAt: envelope.date ? envelope.date.toISOString() : undefined,\n isRead: flags.has(\"\\\\Seen\"),\n folder,\n };\n}\n\n// ---------- mailbox mapping ----------\n\nexport interface ImapMailboxEntry {\n path: string;\n name?: string;\n specialUse?: string;\n delimiter?: string;\n listed?: boolean;\n subscribed?: boolean;\n status?: {\n messages?: number;\n unseen?: number;\n };\n}\n\nexport function mapMailboxToListEntry(m: ImapMailboxEntry): FolderInfo {\n const lastSep = m.path.lastIndexOf(\"/\");\n const parentFolderId =\n lastSep === -1 ? undefined : m.path.slice(0, lastSep);\n return {\n id: m.path,\n displayName: m.path,\n parentFolderId,\n childFolderCount: 0,\n totalItemCount: m.status?.messages ?? 0,\n unreadItemCount: m.status?.unseen ?? 0,\n };\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport MailComposer from \"nodemailer/lib/mail-composer/index.js\";\n\nimport type {\n AddAccountInput,\n AddAccountResult,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n FolderInfo,\n SendInput,\n} from \"../types.js\";\nimport { ImapClientFactory, ImapTokens, isImapTokens } from \"./client.js\";\nimport {\n decodeId,\n encodeId,\n ImapEnvelope,\n resolveFolder,\n} from \"./helpers.js\";\n\n/** Write operations for IMAP — send, draft, move, mark, folders. */\n\nexport async function addAccount(\n clients: ImapClientFactory,\n store: { upsertAccount(rec: AccountRecord): Promise<AccountRecord> },\n input: AddAccountInput,\n): Promise<AddAccountResult> {\n const cfg = input.config ?? {};\n const host = String(cfg.host ?? \"\");\n const port = Number(cfg.port ?? 993);\n const secure = cfg.secure !== false;\n const user = String(cfg.user ?? input.email ?? \"\");\n const password = String(cfg.password ?? \"\");\n const smtpHost = String(cfg.smtpHost ?? host);\n const smtpPort = Number(cfg.smtpPort ?? 587);\n const smtpSecure = cfg.smtpSecure === true;\n\n if (!host || !user || !password) {\n throw new Error(\n \"IMAP requires config: { host, port?, secure?, user, password, smtpHost?, smtpPort?, smtpSecure? }\",\n );\n }\n\n const tokens: ImapTokens = {\n host,\n port,\n secure,\n user,\n password,\n smtpHost: smtpHost || host,\n smtpPort: smtpPort || 587,\n smtpSecure,\n };\n\n // Validate by connecting briefly.\n const client = clients.get({\n email: user.toLowerCase(),\n provider: \"imap\",\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n } as AccountRecord);\n\n try {\n await client.getImap();\n } finally {\n clients.invalidate(user.toLowerCase());\n }\n\n // Optionally validate SMTP — best-effort.\n try {\n const t = client.getTransporter();\n await t.verify();\n } catch {\n /* SMTP verification is optional */\n }\n\n const email = user.toLowerCase();\n const rec: AccountRecord = {\n email,\n provider: \"imap\",\n displayName: input.email ?? user,\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n };\n const saved = await store.upsertAccount(rec);\n return { status: \"ready\", account: saved };\n}\n\nexport function completeAddAccount(): CompleteAddAccountResult {\n return {\n status: \"error\",\n error:\n \"IMAP accounts are set up synchronously — no polling needed. \" +\n \"Call add_account with IMAP config to create the account directly.\",\n };\n}\n\nexport async function sendEmail(\n clients: ImapClientFactory,\n account: AccountRecord,\n msg: SendInput,\n): Promise<{ id: string }> {\n const client = clients.get(account);\n const transporter = client.getTransporter();\n\n const mailOptions: import(\"nodemailer\").SendMailOptions = {\n from: `${account.displayName ?? \"\"} <${account.email}>`,\n to: msg.to\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \"),\n subject: msg.subject,\n };\n\n if (msg.isHtml) {\n mailOptions.html = msg.body;\n } else {\n mailOptions.text = msg.body;\n }\n (mailOptions as Record<string, unknown>).attachDataUrls = true;\n\n if (msg.cc && msg.cc.length > 0) {\n mailOptions.cc = msg.cc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n if (msg.bcc && msg.bcc.length > 0) {\n mailOptions.bcc = msg.bcc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n\n // Handle reply and forward threading\n if (msg.inReplyTo || msg.forwardMessageId) {\n const refId = msg.inReplyTo ?? msg.forwardMessageId;\n if (refId) {\n try {\n const { folder: refFolder, uid: refUid } = decodeId(refId);\n const refMsg = (await client.withMailbox(refFolder, async (imap) => {\n return imap.fetchOne(\n refUid,\n { envelope: true, source: true },\n { uid: true },\n );\n })) as { envelope?: ImapEnvelope; source?: string | ArrayBuffer };\n\n if (refMsg?.envelope) {\n const env = refMsg.envelope as ImapEnvelope;\n if (msg.inReplyTo && env.messageId && !msg.forwardMessageId) {\n mailOptions.inReplyTo = env.messageId;\n (mailOptions as Record<string, unknown>).references =\n env.messageId;\n }\n }\n\n // Embed forwarded message\n if (msg.forwardMessageId && refMsg?.source) {\n const sourceStr =\n typeof refMsg.source === \"string\"\n ? refMsg.source\n : Buffer.from(refMsg.source as ArrayBuffer).toString(\"utf-8\");\n const divider =\n '\\n\\n<div style=\"line-height:12px\"><br></div>\\n\\n' +\n '<div style=\"border-left:2px solid #ccc; padding-left:8px; ' +\n 'margin-left:0; color:#666\">\\n' +\n \"---------- Forwarded message ---------<br>\" +\n sourceStr +\n \"\\n</div>\";\n if (mailOptions.html) {\n mailOptions.html += divider;\n } else if (mailOptions.text) {\n mailOptions.text +=\n \"\\n\\n---------- Forwarded message ---------\\n\" + sourceStr;\n }\n }\n } catch {\n /* If we can't fetch the referenced message, proceed without threading. */\n }\n }\n }\n\n const info = await transporter.sendMail(mailOptions);\n\n // Save a copy to Sent folder\n try {\n const rawMsg = await buildRawMessage(account, msg, info.messageId);\n await client.withMailbox(\"Sent\", async (imap) => {\n await imap.append(\"Sent\", rawMsg, [\"\\\\Seen\"]);\n });\n } catch {\n /* best-effort */\n }\n\n return { id: info.messageId };\n}\n\nexport async function saveDraft(\n clients: ImapClientFactory,\n account: AccountRecord,\n msg: SendInput,\n): Promise<{ id: string }> {\n const client = clients.get(account);\n const rawMsg = await buildRawMessage(account, msg);\n return client.withMailbox(\"Drafts\", async (imap) => {\n const result = (await imap.append(\"Drafts\", rawMsg, [\"\\\\Draft\"])) as { uid: number };\n return { id: encodeId(\"Drafts\", result.uid) };\n });\n}\n\nexport async function updateDraft(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n update: DraftUpdateInput,\n): Promise<{ id: string }> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n\n return client.withMailbox(folder, async (imap) => {\n const existing = (await imap.fetchOne(\n uid,\n { source: true, envelope: true },\n { uid: true },\n )) as { source?: string | ArrayBuffer; envelope?: ImapEnvelope };\n if (!existing?.source) {\n throw new Error(`draft not found: ${id}`);\n }\n\n const origSubject = existing.envelope\n ? (existing.envelope as ImapEnvelope).subject ?? \"\"\n : \"\";\n\n const updatedMsg: Record<string, unknown> = {\n from: `${account.displayName ?? \"\"} <${account.email}>`,\n subject: update.subject ?? origSubject,\n attachDataUrls: true,\n };\n\n if (update.body !== undefined) {\n if (update.isHtml) {\n updatedMsg.html = update.body;\n } else {\n updatedMsg.text = update.body;\n }\n }\n\n const raw = await new Promise<Buffer>((resolve, reject) => {\n const mc = new MailComposer(updatedMsg);\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf);\n });\n });\n\n await imap.messageDelete(uid, { uid: true });\n const result = (await imap.append(folder, raw, [\"\\\\Draft\"])) as { uid: number };\n return { id: encodeId(folder, result.uid) };\n });\n}\n\nexport async function moveEmail(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n destinationId: string,\n): Promise<void> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n const dest = resolveFolder(destinationId);\n\n return client.withMailbox(folder, async (imap) => {\n await imap.messageMove(uid, dest, { uid: true });\n });\n}\n\nexport async function sendDraft(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n): Promise<{ id: string }> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n\n return client.withMailbox(folder, async (imap) => {\n const draft = (await imap.fetchOne(\n uid,\n { source: true },\n { uid: true },\n )) as { source?: string | ArrayBuffer };\n if (!draft?.source) {\n throw new Error(`draft not found: ${id}`);\n }\n\n const sourceStr =\n typeof draft.source === \"string\"\n ? draft.source\n : Buffer.from(draft.source as ArrayBuffer).toString(\"utf-8\");\n\n const transporter = client.getTransporter();\n const info = await transporter.sendMail({ raw: sourceStr });\n\n try {\n await imap.messageMove(uid, \"Sent\", { uid: true });\n } catch {\n /* best-effort */\n }\n\n return { id: info.messageId };\n });\n}\n\nexport async function addAttachmentToDraft(\n clients: ImapClientFactory,\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n): Promise<{\n id: string;\n attachment: { id: string; name: string; contentType?: string };\n}> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(draftId);\n\n return client.withMailbox(folder, async (imap) => {\n const existing = (await imap.fetchOne(\n uid,\n { source: true },\n { uid: true },\n )) as { source?: string | ArrayBuffer };\n if (!existing?.source) {\n throw new Error(`draft not found: ${draftId}`);\n }\n\n const sourceStr =\n typeof existing.source === \"string\"\n ? existing.source\n : Buffer.from(existing.source as ArrayBuffer).toString(\"utf-8\");\n\n const built = await new Promise<Buffer>((resolve, reject) => {\n const mc = new MailComposer({\n raw: sourceStr,\n attachments: [\n {\n filename: name,\n content: Buffer.from(contentBytes, \"base64\"),\n contentType: contentType ?? \"application/octet-stream\",\n },\n ],\n });\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf);\n });\n });\n\n await imap.messageDelete(uid, { uid: true });\n const result = (await imap.append(folder, built, [\"\\\\Draft\"])) as { uid: number };\n\n return {\n id: encodeId(folder, result.uid),\n attachment: {\n id: randomUUID(),\n name,\n contentType: contentType ?? \"application/octet-stream\",\n },\n };\n });\n}\n\nexport async function markRead(\n clients: ImapClientFactory,\n account: AccountRecord,\n id: string,\n isRead: boolean,\n): Promise<void> {\n const client = clients.get(account);\n const { folder, uid } = decodeId(id);\n\n return client.withMailbox(folder, async (imap) => {\n if (isRead) {\n await imap.messageFlagsAdd(uid, [\"\\\\Seen\"], { uid: true });\n } else {\n await imap.messageFlagsRemove(uid, [\"\\\\Seen\"], { uid: true });\n }\n });\n}\n\nexport async function createFolder(\n clients: ImapClientFactory,\n account: AccountRecord,\n input: CreateFolderInput,\n): Promise<FolderInfo> {\n const client = clients.get(account);\n const imap = await client.getImap();\n\n const path = input.parentFolderId\n ? `${input.parentFolderId}/${input.displayName}`\n : input.displayName;\n\n const result = await imap.mailboxCreate(path);\n\n return {\n id: result.path,\n displayName: result.path,\n parentFolderId: input.parentFolderId,\n childFolderCount: 0,\n totalItemCount: 0,\n unreadItemCount: 0,\n };\n}\n\nexport async function renameFolder(\n clients: ImapClientFactory,\n account: AccountRecord,\n folderId: string,\n newName: string,\n): Promise<FolderInfo> {\n const client = clients.get(account);\n const imap = await client.getImap();\n\n const lastSep = folderId.lastIndexOf(\"/\");\n const newPath =\n lastSep === -1 ? newName : folderId.slice(0, lastSep + 1) + newName;\n\n const result = await imap.mailboxRename(folderId, newPath);\n\n return {\n id: result.path,\n displayName: result.path,\n parentFolderId: lastSep === -1 ? undefined : folderId.slice(0, lastSep),\n childFolderCount: 0,\n totalItemCount: 0,\n unreadItemCount: 0,\n };\n}\n\nexport async function deleteFolder(\n clients: ImapClientFactory,\n account: AccountRecord,\n folderId: string,\n): Promise<void> {\n const client = clients.get(account);\n const imap = await client.getImap();\n await imap.mailboxDelete(folderId);\n}\n\nasync function buildRawMessage(\n account: AccountRecord,\n msg: SendInput,\n messageId?: string,\n): Promise<string> {\n const mailOptions: Record<string, unknown> = {\n from: `${account.displayName ?? \"\"} <${account.email}>`,\n to: msg.to\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \"),\n subject: msg.subject,\n attachDataUrls: true,\n };\n\n if (msg.isHtml) {\n mailOptions.html = msg.body;\n } else {\n mailOptions.text = msg.body;\n }\n\n if (msg.cc && msg.cc.length > 0) {\n mailOptions.cc = msg.cc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n if (msg.bcc && msg.bcc.length > 0) {\n mailOptions.bcc = msg.bcc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n\n if (messageId) {\n mailOptions.messageId = messageId;\n }\n\n return new Promise<string>((resolve, reject) => {\n const mc = new MailComposer(mailOptions);\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf.toString(\"utf-8\"));\n });\n });\n}\n","import type { AccountRecord, AccountStore } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n EmailFull,\n EmailProvider,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n SendInput,\n} from \"../types.js\";\nimport { ImapClientFactory } from \"./client.js\";\nimport {\n listEmails,\n searchEmails,\n readEmail,\n readAttachment,\n listFolders,\n} from \"./read-ops.js\";\nimport {\n addAccount,\n completeAddAccount,\n sendEmail,\n saveDraft,\n updateDraft,\n moveEmail,\n sendDraft,\n addAttachmentToDraft,\n markRead,\n createFolder,\n renameFolder,\n deleteFolder,\n} from \"./write-ops.js\";\n\nexport class ImapProvider implements EmailProvider {\n readonly id = \"imap\" as const;\n private readonly clients = new ImapClientFactory();\n\n constructor(private readonly store?: AccountStore) {}\n\n // ---------- account lifecycle ----------\n\n async addAccount(input: AddAccountInput): Promise<AddAccountResult> {\n if (!this.store) throw new Error(\"IMAP provider requires an AccountStore\");\n return addAccount(this.clients, this.store, input);\n }\n\n async completeAddAccount(_handle: string): Promise<CompleteAddAccountResult> {\n return completeAddAccount();\n }\n\n // ---------- browse ----------\n\n async listEmails(account: AccountRecord, opts: ListEmailsOptions): Promise<ListEmailsResult> {\n return listEmails(this.clients, account, opts);\n }\n\n async searchEmails(account: AccountRecord, query: string, opts: SearchEmailsOptions): Promise<EmailSummary[]> {\n return searchEmails(this.clients, account, query, opts);\n }\n\n async readEmail(account: AccountRecord, id: string): Promise<EmailFull> {\n return readEmail(this.clients, account, id);\n }\n\n async readAttachment(account: AccountRecord, messageId: string, attachmentId: string): Promise<AttachmentContent> {\n return readAttachment(this.clients, account, messageId, attachmentId);\n }\n\n // ---------- compose ----------\n\n async sendEmail(account: AccountRecord, msg: SendInput): Promise<{ id: string }> {\n return sendEmail(this.clients, account, msg);\n }\n\n async saveDraft(account: AccountRecord, msg: SendInput): Promise<{ id: string }> {\n return saveDraft(this.clients, account, msg);\n }\n\n async updateDraft(account: AccountRecord, id: string, update: DraftUpdateInput): Promise<{ id: string }> {\n return updateDraft(this.clients, account, id, update);\n }\n\n async moveEmail(account: AccountRecord, id: string, destinationId: string): Promise<void> {\n return moveEmail(this.clients, account, id, destinationId);\n }\n\n async sendDraft(account: AccountRecord, id: string): Promise<{ id: string }> {\n return sendDraft(this.clients, account, id);\n }\n\n async addAttachmentToDraft(\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n ): Promise<{ id: string; attachment: { id: string; name: string; contentType?: string } }> {\n return addAttachmentToDraft(this.clients, account, draftId, name, contentBytes, contentType);\n }\n\n // ---------- organize ----------\n\n async markRead(account: AccountRecord, id: string, isRead: boolean): Promise<void> {\n return markRead(this.clients, account, id, isRead);\n }\n\n // ---------- folders ----------\n\n async listFolders(account: AccountRecord, opts: ListFoldersOptions): Promise<FolderInfo[]> {\n return listFolders(this.clients, account, opts);\n }\n\n async createFolder(account: AccountRecord, input: CreateFolderInput): Promise<FolderInfo> {\n return createFolder(this.clients, account, input);\n }\n\n async renameFolder(account: AccountRecord, folderId: string, newName: string): Promise<FolderInfo> {\n return renameFolder(this.clients, account, folderId, newName);\n }\n\n async deleteFolder(account: AccountRecord, folderId: string): Promise<void> {\n return deleteFolder(this.clients, account, folderId);\n }\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport type { AccountStore, AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n EmailFull,\n EmailProvider,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n SendInput,\n} from \"../types.js\";\nimport {\n awaitDeviceCodeReady,\n beginDeviceCode,\n type SerializedGmailTokens,\n} from \"./auth.js\";\nimport { GmailClientFactory } from \"./client.js\";\nimport {\n listEmails,\n searchEmails,\n readEmail,\n readAttachment,\n listFolders,\n} from \"./read-ops.js\";\nimport {\n sendEmail,\n saveDraft,\n updateDraft,\n moveEmail,\n sendDraft,\n addAttachmentToDraft,\n markRead,\n createFolder,\n renameFolder,\n deleteFolder,\n} from \"./write-ops.js\";\n\n// ── pending flow (mirrors Outlook's PendingFlow pattern) ──\n\ninterface PendingFlow {\n begin: ReturnType<typeof beginDeviceCode>;\n emailHint?: string;\n startedAt: number;\n settled: \"pending\" | \"ready\" | \"error\" | \"expired\";\n account?: AccountRecord;\n error?: string;\n}\n\n// ── provider ──\n\nexport interface GmailProviderOptions {\n store: AccountStore;\n clientId?: string;\n clientSecret?: string;\n}\n\nexport class GmailProvider implements EmailProvider {\n readonly id = \"gmail\" as const;\n private readonly clients: GmailClientFactory;\n private readonly pending = new Map<string, PendingFlow>();\n private readonly clientId?: string;\n private readonly clientSecret?: string;\n\n constructor(private readonly opts: GmailProviderOptions) {\n this.clientId = opts.clientId;\n this.clientSecret = opts.clientSecret;\n this.clients = new GmailClientFactory(\n opts.store,\n opts.clientId,\n opts.clientSecret,\n );\n }\n\n // ── account lifecycle ──\n\n async addAccount(input: AddAccountInput): Promise<AddAccountResult> {\n const begin = beginDeviceCode(\n undefined,\n this.clientId,\n this.clientSecret,\n );\n await awaitDeviceCodeReady(begin);\n\n const handle = randomUUID();\n const flow: PendingFlow = {\n begin,\n emailHint: input.email,\n startedAt: Date.now(),\n settled: \"pending\",\n };\n this.pending.set(handle, flow);\n\n begin.result\n .then(async ({ tokens, email }) => {\n const resolvedEmail = (email || input.email || \"\").toLowerCase();\n if (!resolvedEmail) {\n flow.settled = \"error\";\n flow.error = \"no email returned from Google account\";\n return;\n }\n const rec: AccountRecord = {\n email: resolvedEmail,\n provider: \"gmail\",\n displayName: resolvedEmail,\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n };\n const saved = await this.opts.store.upsertAccount(rec);\n flow.account = saved;\n flow.settled = \"ready\";\n })\n .catch((err: unknown) => {\n flow.settled = \"error\";\n flow.error = err instanceof Error ? err.message : String(err);\n });\n\n return {\n status: \"pending\",\n handle,\n verification: {\n userCode: begin.userCode,\n verificationUri: begin.verificationUri,\n expiresAt: begin.expiresAt,\n message: begin.message,\n },\n };\n }\n\n async completeAddAccount(\n handle: string,\n ): Promise<CompleteAddAccountResult> {\n const flow = this.pending.get(handle);\n if (!flow) return { status: \"error\", error: \"unknown handle\" };\n if (\n Date.now() - flow.startedAt > 20 * 60_000 &&\n flow.settled === \"pending\"\n ) {\n flow.settled = \"expired\";\n flow.begin.cancel();\n }\n if (flow.settled === \"ready\" && flow.account) {\n this.pending.delete(handle);\n return { status: \"ready\", account: flow.account };\n }\n if (flow.settled === \"error\") {\n this.pending.delete(handle);\n return { status: \"error\", error: flow.error ?? \"unknown error\" };\n }\n if (flow.settled === \"expired\") {\n this.pending.delete(handle);\n return { status: \"expired\" };\n }\n return { status: \"pending\" };\n }\n\n // ── browse ──\n\n async listEmails(\n account: AccountRecord,\n opts: ListEmailsOptions,\n ): Promise<ListEmailsResult> {\n return listEmails(this.clients, account, opts);\n }\n\n async searchEmails(\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n ): Promise<EmailSummary[]> {\n return searchEmails(this.clients, account, query, opts);\n }\n\n async readEmail(account: AccountRecord, id: string): Promise<EmailFull> {\n return readEmail(this.clients, account, id);\n }\n\n async readAttachment(\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n ): Promise<AttachmentContent> {\n return readAttachment(this.clients, account, messageId, attachmentId);\n }\n\n // ── compose ──\n\n async sendEmail(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n return sendEmail(this.clients, account, msg);\n }\n\n async saveDraft(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n return saveDraft(this.clients, account, msg);\n }\n\n async updateDraft(\n account: AccountRecord,\n id: string,\n update: DraftUpdateInput,\n ): Promise<{ id: string }> {\n return updateDraft(this.clients, account, id, update);\n }\n\n async moveEmail(\n account: AccountRecord,\n id: string,\n destinationId: string,\n ): Promise<void> {\n return moveEmail(this.clients, account, id, destinationId);\n }\n\n async sendDraft(\n account: AccountRecord,\n id: string,\n ): Promise<{ id: string }> {\n return sendDraft(this.clients, account, id);\n }\n\n async addAttachmentToDraft(\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n ): Promise<{\n id: string;\n attachment: { id: string; name: string; contentType?: string };\n }> {\n return addAttachmentToDraft(\n this.clients,\n account,\n draftId,\n name,\n contentBytes,\n contentType,\n );\n }\n\n // ── organize ──\n\n async markRead(\n account: AccountRecord,\n id: string,\n isRead: boolean,\n ): Promise<void> {\n return markRead(this.clients, account, id, isRead);\n }\n\n // ── folders ──\n\n async listFolders(\n account: AccountRecord,\n opts: ListFoldersOptions,\n ): Promise<FolderInfo[]> {\n return listFolders(this.clients, account, opts);\n }\n\n async createFolder(\n account: AccountRecord,\n input: CreateFolderInput,\n ): Promise<FolderInfo> {\n return createFolder(this.clients, account, input);\n }\n\n async renameFolder(\n account: AccountRecord,\n folderId: string,\n newName: string,\n ): Promise<FolderInfo> {\n return renameFolder(this.clients, account, folderId, newName);\n }\n\n async deleteFolder(\n account: AccountRecord,\n folderId: string,\n ): Promise<void> {\n return deleteFolder(this.clients, account, folderId);\n }\n}\n","import { OAuth2Client } from \"google-auth-library\";\n\nconst GOOGLE_DEVICE_CODE_URL = \"https://oauth2.googleapis.com/device/code\";\nconst GOOGLE_TOKEN_URL = \"https://oauth2.googleapis.com/token\";\nconst GOOGLE_OAUTH2_REVOKE_URL = \"https://oauth2.googleapis.com/revoke\";\n\nconst DEFAULT_SCOPES = [\n \"https://www.googleapis.com/auth/gmail.modify\",\n];\n\nexport interface DeviceCodeBegin {\n userCode: string;\n verificationUri: string;\n message: string;\n expiresAt: string; // ISO\n /** Resolves with the tokens and email once the user completes the flow. */\n result: Promise<{ tokens: SerializedGmailTokens; email: string }>;\n /** Aborts the in-flight polling promise. */\n cancel(): void;\n}\n\nexport interface SerializedGmailTokens {\n /** Client ID used to authenticate this account. */\n clientId: string;\n /** Client secret, if any (optional for installed/TV apps). */\n clientSecret?: string;\n /** Current access token. */\n accessToken: string;\n /** Long-lived refresh token. */\n refreshToken: string;\n /** Expiry timestamp in milliseconds since epoch. */\n expiryDate: number;\n /** Scopes granted. */\n scopes: string[];\n /** Email address associated with this account. */\n email: string;\n}\n\n/** Type guard — validates that an unknown value has the shape of SerializedGmailTokens. */\nexport function isSerializedGmailTokens(\n obj: unknown,\n): obj is SerializedGmailTokens {\n if (typeof obj !== \"object\" || obj === null) return false;\n const o = obj as Record<string, unknown>;\n return (\n typeof o.clientId === \"string\" &&\n (o.clientSecret === undefined || typeof o.clientSecret === \"string\") &&\n typeof o.accessToken === \"string\" &&\n typeof o.refreshToken === \"string\" &&\n typeof o.expiryDate === \"number\" &&\n Array.isArray(o.scopes) &&\n typeof o.email === \"string\"\n );\n}\n\n/**\n * Build an {@link OAuth2Client} hydrated with stored tokens.\n * Returns a fresh client that can be used for silent refresh.\n */\nexport function buildOAuth2Client(\n tokens?: SerializedGmailTokens,\n): OAuth2Client {\n const client = new OAuth2Client({\n clientId: tokens?.clientId,\n clientSecret: tokens?.clientSecret,\n });\n if (tokens) {\n client.setCredentials({\n access_token: tokens.accessToken,\n refresh_token: tokens.refreshToken,\n expiry_date: tokens.expiryDate,\n scope: tokens.scopes.join(\" \"),\n });\n }\n return client;\n}\n\n/** Fetch the email address associated with an access token via the Gmail profile endpoint. */\nasync function getEmailFromToken(accessToken: string): Promise<string> {\n const res = await fetch(\n \"https://gmail.googleapis.com/gmail/v1/users/me/profile\",\n {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n },\n );\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(\n `Failed to get Gmail profile (${res.status}): ${body}`,\n );\n }\n const data = (await res.json()) as { emailAddress: string };\n return data.emailAddress;\n}\n\n/**\n * Start a Google OAuth 2.0 device-authorisation flow.\n *\n * The returned `result` promise resolves once the user has entered the code\n * and consented; callers should poll it (or await it) via `complete_add_account`.\n */\nexport function beginDeviceCode(\n scopes: string[] = DEFAULT_SCOPES,\n clientIdOverride?: string,\n clientSecretOverride?: string,\n): DeviceCodeBegin {\n const clientId = clientIdOverride || process.env.GOOGLE_CLIENT_ID;\n if (!clientId) {\n throw new Error(\n \"GOOGLE_CLIENT_ID is required for Gmail OAuth — set it in env or provider config\",\n );\n }\n const clientSecret =\n clientSecretOverride || process.env.GOOGLE_CLIENT_SECRET || undefined;\n\n let resolve!: (v: { tokens: SerializedGmailTokens; email: string }) => void;\n let reject!: (err: unknown) => void;\n const result = new Promise<{ tokens: SerializedGmailTokens; email: string }>(\n (res, rej) => {\n resolve = res;\n reject = rej;\n },\n );\n\n // Placeholders populated once the device-code HTTP call completes.\n let userCode = \"\";\n let verificationUri = \"\";\n let message = \"\";\n let expiresAt = new Date(Date.now() + 15 * 60_000).toISOString();\n let aborted = false;\n\n const ready = (async () => {\n try {\n // ── Step 1: request device code ──\n const dcParams = new URLSearchParams();\n dcParams.set(\"client_id\", clientId);\n if (clientSecret) dcParams.set(\"client_secret\", clientSecret);\n dcParams.set(\"scope\", scopes.join(\" \"));\n\n const dcRes = await fetch(GOOGLE_DEVICE_CODE_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: dcParams.toString(),\n });\n\n if (!dcRes.ok) {\n const errBody = (await dcRes.json().catch(() => ({}))) as {\n error?: string;\n error_description?: string;\n };\n throw new Error(\n `Google device-code request failed: ` +\n `${errBody.error_description ?? errBody.error ?? dcRes.statusText}`,\n );\n }\n\n const dcData = (await dcRes.json()) as {\n device_code: string;\n user_code: string;\n verification_url: string;\n expires_in: number;\n interval?: number;\n };\n\n userCode = dcData.user_code;\n verificationUri = dcData.verification_url;\n const deviceCode = dcData.device_code;\n let interval = dcData.interval ?? 5;\n if (dcData.expires_in) {\n expiresAt = new Date(\n Date.now() + dcData.expires_in * 1000,\n ).toISOString();\n }\n message = `Go to ${verificationUri} and enter code: ${userCode}`;\n\n // ── Step 2: poll for tokens ──\n const tokenParams = new URLSearchParams();\n tokenParams.set(\"client_id\", clientId);\n if (clientSecret) tokenParams.set(\"client_secret\", clientSecret);\n tokenParams.set(\"device_code\", deviceCode);\n tokenParams.set(\n \"grant_type\",\n \"urn:ietf:params:oauth:grant-type:device_code\",\n );\n\n const deadline = Date.now() + (dcData.expires_in * 1000);\n while (Date.now() < deadline && !aborted) {\n await new Promise((r) => setTimeout(r, interval * 1000));\n if (aborted) return;\n\n const tokenRes = await fetch(GOOGLE_TOKEN_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: tokenParams.toString(),\n });\n\n const tokenData = (await tokenRes.json()) as {\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n scope?: string;\n error?: string;\n };\n\n if (tokenData.access_token) {\n const email = await getEmailFromToken(tokenData.access_token);\n const tokens: SerializedGmailTokens = {\n clientId,\n clientSecret,\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token ?? \"\",\n expiryDate: tokenData.expires_in\n ? Date.now() + tokenData.expires_in * 1000\n : Date.now() + 3600_000,\n scopes: tokenData.scope\n ? tokenData.scope.split(\" \")\n : scopes,\n email,\n };\n resolve({ tokens, email });\n return;\n }\n\n switch (tokenData.error) {\n case \"authorization_pending\":\n break; // keep polling\n case \"slow_down\":\n interval += 1; // Google says to back off\n break;\n case \"expired_token\":\n throw new Error(\"Device code expired — please try again\");\n case \"access_denied\":\n throw new Error(\"User denied access\");\n default:\n throw new Error(\n `Token request failed: ${tokenData.error ?? \"unknown error\"}`,\n );\n }\n }\n\n if (!aborted) {\n throw new Error(\"Device code expired — please try again\");\n }\n } catch (err) {\n if (!aborted) reject(err);\n }\n })();\n\n return {\n get userCode() {\n return userCode;\n },\n get verificationUri() {\n return verificationUri;\n },\n get message() {\n return message;\n },\n get expiresAt() {\n return expiresAt;\n },\n result,\n cancel() {\n aborted = true;\n },\n ...({ _ready: ready } as Record<string, unknown>),\n } as DeviceCodeBegin;\n}\n\n/** Await `_ready` so the user-code fields are populated. */\nexport async function awaitDeviceCodeReady(b: DeviceCodeBegin): Promise<void> {\n const r = (b as unknown as { _ready: Promise<void> })._ready;\n await r;\n}\n\n/**\n * Acquire a fresh access token for a stored account, refreshing silently from\n * the persisted refresh token. Returns the (possibly-updated) tokens so the\n * caller can write them back to the store.\n */\nexport async function acquireAccessToken(\n tokens: SerializedGmailTokens,\n scopes: string[] = DEFAULT_SCOPES,\n): Promise<{ accessToken: string; tokens: SerializedGmailTokens }> {\n const client = buildOAuth2Client(tokens);\n const res = await client.getAccessToken();\n if (!res.token) {\n throw new Error(\n \"Failed to acquire access token — refresh token may be revoked; re-run add_account\",\n );\n }\n\n const creds = client.credentials;\n const next: SerializedGmailTokens = {\n ...tokens,\n accessToken: res.token,\n refreshToken: creds.refresh_token ?? tokens.refreshToken,\n expiryDate: creds.expiry_date ?? Date.now() + 3600_000,\n scopes,\n };\n return { accessToken: res.token, tokens: next };\n}\n\n/**\n * Revoke a refresh token so the stored account is fully de-authorized.\n * Best-effort — failures are swallowed since we'll delete the stored tokens\n * regardless.\n */\nexport async function revokeRefreshToken(\n tokens: SerializedGmailTokens,\n): Promise<void> {\n try {\n await fetch(GOOGLE_OAUTH2_REVOKE_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({ token: tokens.refreshToken }).toString(),\n });\n } catch {\n /* best-effort */\n }\n}\n","import { gmail_v1, google } from \"googleapis\";\n\nimport type { AccountStore, AccountRecord } from \"../../store/account-store.js\";\nimport {\n acquireAccessToken,\n buildOAuth2Client,\n isSerializedGmailTokens,\n type SerializedGmailTokens,\n} from \"./auth.js\";\n\n/**\n * Cached per-account entry: an OAuth2Client + a Gmail API instance.\n * The OAuth2Client handles token refresh automatically; we listen for token\n * events to persist refreshed credentials back to the AccountStore.\n */\ninterface GmailClientEntry {\n auth: ReturnType<typeof buildOAuth2Client>;\n gmail: gmail_v1.Gmail;\n}\n\n/**\n * Builds a Google `gmail_v1.Gmail` client bound to a stored account.\n * The client auto-refreshes access tokens via `google-auth-library` and\n * persists refreshed tokens back into the AccountStore.\n *\n * Clients are cached per email since the underlying library reuses connections.\n */\nexport class GmailClientFactory {\n private readonly cache = new Map<string, GmailClientEntry>();\n /** Serialize token-persist per email to prevent concurrent upsert races. */\n private readonly persistLocks = new Map<string, Promise<void>>();\n\n constructor(\n private readonly store: AccountStore,\n private readonly clientId?: string,\n private readonly clientSecret?: string,\n ) {}\n\n get(account: AccountRecord): GmailClientEntry {\n const key = account.email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) return existing;\n\n if (!isSerializedGmailTokens(account.tokens)) {\n throw new Error(\n \"Gmail account tokens are missing or corrupted — re-run add_account\",\n );\n }\n const tokens: SerializedGmailTokens = account.tokens;\n\n // Use stored clientId/clientSecret, falling back to constructor args\n const resolvedClientId = tokens.clientId || this.clientId;\n const resolvedSecret = tokens.clientSecret || this.clientSecret;\n\n const auth = buildOAuth2Client({\n ...tokens,\n clientId: resolvedClientId ?? tokens.clientId,\n clientSecret: resolvedSecret,\n });\n\n const store = this.store;\n const persistLocks = this.persistLocks;\n auth.on(\"tokens\", (updated) => {\n if (!updated.refresh_token && !updated.access_token) return;\n\n // Serialize persistence per email — two rapid token events can race\n // on the store read-modify-write cycle.\n const existing = persistLocks.get(key);\n const chain = (existing ?? Promise.resolve()).then(async () => {\n const fresh = store.getAccount(account.email) ?? account;\n const currentTokens = isSerializedGmailTokens(fresh.tokens)\n ? (fresh.tokens as unknown as SerializedGmailTokens)\n : tokens;\n\n const nextTokens: SerializedGmailTokens = {\n ...currentTokens,\n accessToken: updated.access_token ?? currentTokens.accessToken,\n refreshToken:\n updated.refresh_token ?? currentTokens.refreshToken,\n expiryDate:\n updated.expiry_date ?? currentTokens.expiryDate,\n scopes: updated.scope\n ? updated.scope.split(\" \")\n : currentTokens.scopes,\n };\n\n await store\n .upsertAccount({\n ...fresh,\n tokens: nextTokens as unknown as Record<string, unknown>,\n })\n .catch(() => {\n /* swallow — next call will refresh again */\n });\n });\n persistLocks.set(key, chain);\n chain.finally(() => {\n if (persistLocks.get(key) === chain) persistLocks.delete(key);\n });\n });\n\n const gmail = google.gmail({ version: \"v1\", auth });\n const entry: GmailClientEntry = { auth, gmail };\n this.cache.set(key, entry);\n return entry;\n }\n\n /** Drop a cached client (e.g. after removeAccount). */\n invalidate(email: string): void {\n this.cache.delete(email.toLowerCase());\n }\n}\n","import { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\n\nimport type { gmail_v1 } from \"googleapis\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AttachmentContent,\n EmailFull,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n EmailAddress,\n} from \"../types.js\";\nimport { GmailClientFactory } from \"./client.js\";\nimport {\n clampLimit,\n findHeader,\n mapHeaderAddr,\n mapSummary,\n mapFolder,\n parsePayload,\n pool,\n resolveLabel,\n type GmailMessageListEntry,\n} from \"./helpers.js\";\n\n/**\n * Browse operations for Gmail — list, search, read emails, attachments,\n * and folders.\n */\n\nexport async function listEmails(\n clients: GmailClientFactory,\n account: AccountRecord,\n opts: ListEmailsOptions,\n): Promise<ListEmailsResult> {\n const { gmail } = clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n const label = resolveLabel(opts.folder ?? \"inbox\");\n\n const params: gmail_v1.Params$Resource$Users$Messages$List = {\n userId: \"me\",\n labelIds: [label],\n maxResults: limit,\n };\n\n if (opts.unreadOnly) {\n params.q = \"is:unread\";\n }\n\n const allIds: GmailMessageListEntry[] = [];\n let pageToken: string | undefined;\n\n do {\n const res = await gmail.users.messages.list({ ...params, pageToken });\n if (res.data.messages) allIds.push(...res.data.messages);\n pageToken = res.data.nextPageToken ?? undefined;\n } while (pageToken && allIds.length < (opts.skip ?? 0) + limit);\n\n const skip = opts.skip ?? 0;\n const pageIds = allIds.slice(skip, skip + limit);\n const hasMore = skip + limit < allIds.length;\n\n if (pageIds.length === 0) {\n return { items: [], hasMore };\n }\n\n const items = await pool(pageIds, 10, async (entry) => {\n const msgId = entry.id ?? \"\";\n const msgRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msgId,\n format: \"metadata\",\n metadataHeaders: [\"From\", \"Subject\", \"To\", \"Date\"],\n });\n const msg = msgRes.data;\n return mapSummary(msgId, msg.payload?.headers ?? [], {\n labelIds: msg.labelIds,\n internalDate: msg.internalDate,\n });\n });\n\n return { items, hasMore };\n}\n\nexport async function searchEmails(\n clients: GmailClientFactory,\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n): Promise<EmailSummary[]> {\n const { gmail } = clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n\n const res = await gmail.users.messages.list({\n userId: \"me\",\n q: query,\n maxResults: limit,\n });\n\n const ids = res.data.messages ?? [];\n if (ids.length === 0) return [];\n\n const items = await pool(ids, 10, async (entry) => {\n const msgId = entry.id ?? \"\";\n const msgRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msgId,\n format: \"metadata\",\n metadataHeaders: [\"From\", \"Subject\", \"To\", \"Date\"],\n });\n const msg = msgRes.data;\n return mapSummary(msgId, msg.payload?.headers ?? [], {\n labelIds: msg.labelIds,\n internalDate: msg.internalDate,\n });\n });\n\n return items;\n}\n\nexport async function readEmail(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n): Promise<EmailFull> {\n const { gmail } = clients.get(account);\n\n const res = await gmail.users.messages.get({\n userId: \"me\",\n id,\n format: \"full\",\n });\n\n const msg = res.data;\n if (!msg) throw new Error(`message not found: ${id}`);\n\n const headers = msg.payload?.headers ?? [];\n const { bodyText, bodyHtml, attachments } = parsePayload(msg.payload ?? {});\n\n const summary = mapSummary(id, headers, {\n labelIds: msg.labelIds,\n internalDate: msg.internalDate,\n });\n\n return {\n ...summary,\n cc: mapHeaderAddr(findHeader(headers, \"Cc\")),\n bcc: mapHeaderAddr(findHeader(headers, \"Bcc\")),\n bodyText,\n bodyHtml,\n attachments: attachments.length > 0 ? attachments : undefined,\n hasAttachments: attachments.length > 0,\n };\n}\n\nexport async function readAttachment(\n clients: GmailClientFactory,\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n): Promise<AttachmentContent> {\n const { gmail } = clients.get(account);\n\n const msgRes = await gmail.users.messages.get({\n userId: \"me\",\n id: messageId,\n format: \"full\",\n });\n const { attachments } = parsePayload(msgRes.data.payload ?? {});\n const match = attachments.find((a) => a.id === attachmentId);\n\n const name = match?.name ?? \"attachment\";\n const contentType = match?.contentType;\n\n const attRes = await gmail.users.messages.attachments.get({\n userId: \"me\",\n messageId,\n id: attachmentId,\n });\n\n const data = attRes.data.data;\n if (!data) throw new Error(\"attachment data is empty\");\n\n const buf = Buffer.from(\n data.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n );\n\n const outPath = pathJoin(tmpdir(), name);\n writeFileSync(outPath, buf);\n\n return { name, contentType, path: outPath };\n}\n\nexport async function listFolders(\n clients: GmailClientFactory,\n account: AccountRecord,\n _opts: ListFoldersOptions,\n): Promise<FolderInfo[]> {\n const { gmail } = clients.get(account);\n const res = await gmail.users.labels.list({ userId: \"me\" });\n const labels = res.data.labels ?? [];\n return labels.map(mapFolder);\n}\n","import type { gmail_v1 } from \"googleapis\";\nimport MailComposer from \"nodemailer/lib/mail-composer/index.js\";\n\nimport { parseInlineImages } from \"../shared/inline-images.js\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AttachmentContent,\n EmailAddress,\n EmailFull,\n EmailSummary,\n FolderInfo,\n SendInput,\n} from \"../types.js\";\n\n// ── well-known folder ↔ Gmail label mapping ──\n\n/** Map a well-known folder name to its Gmail system-label id. */\nconst WELL_KNOWN_TO_LABEL: Record<string, string> = {\n inbox: \"INBOX\",\n sentitems: \"SENT\",\n drafts: \"DRAFT\",\n deleteditems: \"TRASH\",\n junkemail: \"SPAM\",\n outbox: \"\", // Gmail has no outbox; sendEmail handles this.\n};\n\nexport function resolveLabel(wellKnownOrId: string): string {\n const lower = wellKnownOrId.toLowerCase();\n return WELL_KNOWN_TO_LABEL[lower] ?? wellKnownOrId;\n}\n\n/**\n * For \"archive\" we must *remove* the INBOX label rather than add a\n * destination. Other well-known names map normally.\n */\nexport function resolveLabelsForMove(\n destinationId: string,\n): { addLabelIds: string[]; removeLabelIds: string[] } {\n if (destinationId.toLowerCase() === \"archive\") {\n return { addLabelIds: [], removeLabelIds: [\"INBOX\"] };\n }\n return { addLabelIds: [resolveLabel(destinationId)], removeLabelIds: [] };\n}\n\n// ── map Gmail API responses to shared types ──\n\nexport interface GmailMessageListEntry {\n id?: string | null;\n threadId?: string | null;\n}\n\nexport function mapHeaderAddr(\n raw: string | null | undefined,\n): EmailAddress[] {\n if (!raw) return [];\n const addrs = raw.split(\",\");\n return addrs.map((a) => {\n const trimmed = a.trim();\n const match = trimmed.match(/^(.+?)\\s*<(.+@.+)>$/);\n if (match) return { name: match[1]!.trim(), address: match[2]! };\n return { address: trimmed };\n });\n}\n\ntype GmailMessage = gmail_v1.Schema$Message;\ntype GmailMessagePart = gmail_v1.Schema$MessagePart;\n\nexport function findHeader(\n headers: GmailMessagePart[\"headers\"],\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n const h = headers.find(\n (h) => h.name?.toLowerCase() === name.toLowerCase(),\n );\n return h?.value ?? undefined;\n}\n\n/** Decode Gmail's base64url-encoded body part into a UTF-8 string. */\nexport function decodeBody(body: gmail_v1.Schema$MessagePartBody): string {\n if (!body?.data) return \"\";\n return Buffer.from(\n body.data.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n ).toString(\"utf-8\");\n}\n\ninterface ParsedPayload {\n bodyText?: string;\n bodyHtml?: string;\n attachments: NonNullable<EmailFull[\"attachments\"]>;\n}\n\n/** Walk the MIME part tree to extract text, HTML, and attachments. */\nexport function parsePayload(\n payload: GmailMessagePart,\n prefix = \"\",\n): ParsedPayload {\n let bodyText: string | undefined;\n let bodyHtml: string | undefined;\n const attachments: NonNullable<EmailFull[\"attachments\"]> = [];\n\n function walk(part: GmailMessagePart, partPrefix: string): void {\n const mime = part.mimeType ?? \"\";\n\n if (mime === \"text/plain\" && bodyText === undefined) {\n bodyText = decodeBody(part.body ?? {});\n return;\n }\n if (mime === \"text/html\" && bodyHtml === undefined) {\n bodyHtml = decodeBody(part.body ?? {});\n return;\n }\n\n if (part.parts) {\n for (let i = 0; i < part.parts.length; i++) {\n walk(part.parts[i]!, (partPrefix ? `${partPrefix}.` : \"\") + String(i));\n }\n return;\n }\n\n const topType = mime.split(\"/\")[0] ?? \"\";\n const hasFilename = !!part.filename || !!part.body?.attachmentId;\n const isAttachment =\n hasFilename ||\n (!!mime && topType !== \"text\" && topType !== \"multipart\");\n\n if (isAttachment && part.body?.attachmentId) {\n attachments.push({\n id: part.body.attachmentId,\n name: part.filename ?? part.partId ?? \"attachment\",\n contentType: mime || undefined,\n size: part.body.size != null ? Number(part.body.size) : undefined,\n });\n }\n }\n\n walk(payload, prefix);\n return { bodyText, bodyHtml, attachments };\n}\n\nexport function mapSummary(\n id: string,\n headers: GmailMessagePart[\"headers\"],\n flags: { labelIds?: (string | null)[] | null; internalDate?: string | null },\n): EmailSummary {\n return {\n id,\n subject: findHeader(headers, \"Subject\") ?? \"\",\n from: mapHeaderAddr(findHeader(headers, \"From\"))[0],\n to: mapHeaderAddr(findHeader(headers, \"To\")),\n receivedAt: flags.internalDate\n ? new Date(Number(flags.internalDate)).toISOString()\n : undefined,\n preview: undefined,\n isRead: !(flags.labelIds?.includes(\"UNREAD\") ?? false),\n hasAttachments: false,\n };\n}\n\nexport function mapFolder(label: gmail_v1.Schema$Label): FolderInfo {\n return {\n id: label.id ?? \"\",\n displayName: label.name ?? \"\",\n parentFolderId: undefined,\n childFolderCount: 0,\n totalItemCount: label.messagesTotal ?? 0,\n unreadItemCount: label.messagesUnread ?? 0,\n };\n}\n\n// ── limit clamping ──\n\nexport function clampLimit(\n v: number | undefined,\n dflt: number,\n max: number,\n): number {\n if (!v || v <= 0) return dflt;\n return Math.min(v, max);\n}\n\n/** Run an async function over items with limited concurrency. */\nexport async function pool<T, R>(\n items: T[],\n concurrency: number,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = new Array(items.length);\n let idx = 0;\n async function worker(): Promise<void> {\n while (idx < items.length) {\n const i = idx++;\n results[i] = await fn(items[i]!);\n }\n }\n const workers = Array.from(\n { length: Math.min(concurrency, items.length) },\n () => worker(),\n );\n await Promise.all(workers);\n return results;\n}\n\n// ── RFC 2822 message building (reuses nodemailer) ──\n\nexport function base64urlEncode(buf: Buffer): string {\n return buf\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/**\n * Build a raw RFC 2822 message string from send/draft input.\n * Uses nodemailer's MailComposer for MIME construction, then\n * base64url-encodes the result for the Gmail API `raw` field.\n */\nexport async function buildRawMessage(\n account: AccountRecord,\n msg: SendInput,\n messageId?: string,\n): Promise<{ raw: string; threadId?: string }> {\n const { body: transformed, images } = parseInlineImages(msg.body);\n\n const mailOptions: Record<string, unknown> = {\n from: `${account.displayName ?? \"\"} <${account.email}>`,\n to: msg.to\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \"),\n subject: msg.subject,\n attachDataUrls: true,\n };\n\n if (msg.isHtml) {\n mailOptions.html = transformed;\n } else {\n mailOptions.text = transformed;\n }\n\n if (msg.cc && msg.cc.length > 0) {\n mailOptions.cc = msg.cc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n if (msg.bcc && msg.bcc.length > 0) {\n mailOptions.bcc = msg.bcc\n .map((a) => (a.name ? `\"${a.name}\" <${a.address}>` : a.address))\n .join(\", \");\n }\n\n if (images.length > 0) {\n mailOptions.attachments = images.map((img) => ({\n filename: img.filename,\n content: Buffer.from(img.contentBytes, \"base64\"),\n contentType: img.contentType,\n cid: img.cid,\n }));\n }\n\n if (messageId) {\n mailOptions.messageId = messageId;\n }\n\n const rawStr = await new Promise<string>((resolve, reject) => {\n const mc = new MailComposer(mailOptions);\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf.toString(\"utf-8\"));\n });\n });\n\n return { raw: base64urlEncode(Buffer.from(rawStr, \"utf-8\")) };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { Buffer } from \"node:buffer\";\n\nimport MailComposer from \"nodemailer/lib/mail-composer/index.js\";\n\nimport type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n CreateFolderInput,\n DraftUpdateInput,\n EmailAddress,\n FolderInfo,\n SendInput,\n} from \"../types.js\";\nimport {\n GmailClientFactory,\n} from \"./client.js\";\nimport {\n base64urlEncode,\n buildRawMessage,\n mapFolder,\n mapHeaderAddr,\n findHeader,\n resolveLabel,\n resolveLabelsForMove,\n} from \"./helpers.js\";\n\n/**\n * Write operations for Gmail — send, draft, move, mark, folders.\n */\n\nexport async function sendEmail(\n clients: GmailClientFactory,\n account: AccountRecord,\n msg: SendInput,\n): Promise<{ id: string }> {\n const { gmail } = clients.get(account);\n\n let threadId: string | undefined;\n let rawBody: { raw: string };\n\n if (msg.forwardMessageId) {\n const fwdRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msg.forwardMessageId,\n format: \"raw\",\n });\n threadId = fwdRes.data.threadId ?? undefined;\n const fwdRaw = fwdRes.data.raw;\n if (fwdRaw) {\n const fwdStr = Buffer.from(\n fwdRaw.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n ).toString(\"utf-8\");\n\n const divider =\n '\\n\\n<div style=\"line-height:12px\"><br></div>\\n\\n' +\n '<div style=\"border-left:2px solid #ccc; padding-left:8px; ' +\n 'margin-left:0; color:#666\">\\n' +\n \"---------- Forwarded message ---------<br>\" +\n fwdStr +\n \"\\n</div>\";\n\n const combinedMsg = { ...msg, body: msg.body + divider };\n rawBody = await buildRawMessage(account, combinedMsg);\n } else {\n rawBody = await buildRawMessage(account, msg);\n }\n } else {\n rawBody = await buildRawMessage(account, msg);\n\n if (msg.inReplyTo) {\n try {\n const refRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msg.inReplyTo,\n format: \"minimal\",\n });\n threadId = refRes.data.threadId ?? undefined;\n } catch {\n /* proceed without threading */\n }\n }\n }\n\n const sendRes = await gmail.users.messages.send({\n userId: \"me\",\n requestBody: {\n raw: rawBody.raw,\n threadId,\n },\n });\n\n return { id: sendRes.data.id ?? \"\" };\n}\n\nexport async function saveDraft(\n clients: GmailClientFactory,\n account: AccountRecord,\n msg: SendInput,\n): Promise<{ id: string }> {\n const { gmail } = clients.get(account);\n const { raw } = await buildRawMessage(account, msg);\n\n let threadId: string | undefined;\n if (msg.inReplyTo) {\n try {\n const refRes = await gmail.users.messages.get({\n userId: \"me\",\n id: msg.inReplyTo,\n format: \"minimal\",\n });\n threadId = refRes.data.threadId ?? undefined;\n } catch {\n /* proceed without threading */\n }\n }\n\n const draftRes = await gmail.users.drafts.create({\n userId: \"me\",\n requestBody: {\n message: { raw, threadId },\n },\n });\n\n return { id: draftRes.data.message?.id ?? draftRes.data.id ?? \"\" };\n}\n\nexport async function updateDraft(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n update: DraftUpdateInput,\n): Promise<{ id: string }> {\n const { gmail } = clients.get(account);\n\n const draftRes = await gmail.users.drafts.get({\n userId: \"me\",\n id,\n format: \"raw\",\n });\n\n const existingMessage = draftRes.data.message;\n if (!existingMessage?.raw) {\n throw new Error(`draft not found: ${id}`);\n }\n\n const existingHeaders = existingMessage.payload?.headers ?? [];\n const origSubject = findHeader(existingHeaders, \"Subject\") ?? \"\";\n\n const rawStr = Buffer.from(\n existingMessage.raw.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n ).toString(\"utf-8\");\n\n // Extract existing To/CC recipients from headers\n const existingTo = update.to ?? mapHeaderAddr(findHeader(existingHeaders, \"To\"));\n const existingCc = update.cc ?? mapHeaderAddr(findHeader(existingHeaders, \"Cc\"));\n const existingBcc = update.bcc ?? mapHeaderAddr(findHeader(existingHeaders, \"Bcc\"));\n\n const { raw } = await buildRawMessage(account, {\n to: existingTo,\n subject: update.subject ?? origSubject,\n body: update.body ?? \"\",\n isHtml: update.isHtml,\n cc: existingCc.length > 0 ? existingCc : undefined,\n bcc: existingBcc.length > 0 ? existingBcc : undefined,\n });\n\n const updated = await gmail.users.drafts.update({\n userId: \"me\",\n id,\n requestBody: {\n message: {\n raw,\n threadId: existingMessage.threadId ?? undefined,\n },\n },\n });\n\n return { id: updated.data.message?.id ?? updated.data.id ?? id };\n}\n\nexport async function moveEmail(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n destinationId: string,\n): Promise<void> {\n const { gmail } = clients.get(account);\n const { addLabelIds, removeLabelIds } =\n resolveLabelsForMove(destinationId);\n\n await gmail.users.messages.modify({\n userId: \"me\",\n id,\n requestBody: { addLabelIds, removeLabelIds },\n });\n}\n\nexport async function sendDraft(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n): Promise<{ id: string }> {\n const { gmail } = clients.get(account);\n const res = await gmail.users.drafts.send({\n userId: \"me\",\n requestBody: { id },\n });\n return { id: res.data.id ?? id };\n}\n\nexport async function addAttachmentToDraft(\n clients: GmailClientFactory,\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n): Promise<{\n id: string;\n attachment: { id: string; name: string; contentType?: string };\n}> {\n const { gmail } = clients.get(account);\n\n const draftRes = await gmail.users.drafts.get({\n userId: \"me\",\n id: draftId,\n format: \"raw\",\n });\n\n const existingMessage = draftRes.data.message;\n if (!existingMessage?.raw) {\n throw new Error(`draft not found: ${draftId}`);\n }\n\n const rawStr = Buffer.from(\n existingMessage.raw.replace(/-/g, \"+\").replace(/_/g, \"/\"),\n \"base64\",\n ).toString(\"utf-8\");\n\n const newRawStr = await new Promise<string>((resolve, reject) => {\n const mc = new MailComposer({\n raw: rawStr,\n attachments: [\n {\n filename: name,\n content: Buffer.from(contentBytes, \"base64\"),\n contentType: contentType ?? \"application/octet-stream\",\n },\n ],\n });\n mc.compile().build((err: Error | null, buf: Buffer) => {\n if (err) reject(err);\n else resolve(buf.toString(\"utf-8\"));\n });\n });\n\n const updated = await gmail.users.drafts.update({\n userId: \"me\",\n id: draftId,\n requestBody: {\n message: {\n raw: base64urlEncode(Buffer.from(newRawStr, \"utf-8\")),\n threadId: existingMessage.threadId ?? undefined,\n },\n },\n });\n\n return {\n id: updated.data.message?.id ?? updated.data.id ?? draftId,\n attachment: {\n id: randomUUID(),\n name,\n contentType: contentType ?? \"application/octet-stream\",\n },\n };\n}\n\nexport async function markRead(\n clients: GmailClientFactory,\n account: AccountRecord,\n id: string,\n isRead: boolean,\n): Promise<void> {\n const { gmail } = clients.get(account);\n await gmail.users.messages.modify({\n userId: \"me\",\n id,\n requestBody: {\n removeLabelIds: isRead ? [\"UNREAD\"] : undefined,\n addLabelIds: isRead ? undefined : [\"UNREAD\"],\n },\n });\n}\n\nexport async function createFolder(\n clients: GmailClientFactory,\n account: AccountRecord,\n input: CreateFolderInput,\n): Promise<FolderInfo> {\n const { gmail } = clients.get(account);\n const created = await gmail.users.labels.create({\n userId: \"me\",\n requestBody: {\n name: input.displayName,\n messageListVisibility: \"show\",\n labelListVisibility: \"labelShow\",\n },\n });\n return mapFolder(created.data);\n}\n\nexport async function renameFolder(\n clients: GmailClientFactory,\n account: AccountRecord,\n folderId: string,\n newName: string,\n): Promise<FolderInfo> {\n const { gmail } = clients.get(account);\n const updated = await gmail.users.labels.patch({\n userId: \"me\",\n id: folderId,\n requestBody: { name: newName },\n });\n return mapFolder(updated.data);\n}\n\nexport async function deleteFolder(\n clients: GmailClientFactory,\n account: AccountRecord,\n folderId: string,\n): Promise<void> {\n const { gmail } = clients.get(account);\n await gmail.users.labels.delete({\n userId: \"me\",\n id: folderId,\n });\n}\n","import type { AccountStore, AccountRecord } from \"../store/account-store.js\";\nimport type { EmailProvider, ProviderId } from \"./types.js\";\nimport type { ProvidersConfig } from \"../config.js\";\nimport { OutlookProvider } from \"./outlook/index.js\";\nimport { ImapProvider } from \"./imap/index.js\";\nimport { GmailProvider } from \"./gmail/index.js\";\n\nexport interface Registry {\n get(id: ProviderId): EmailProvider;\n resolveByEmail(email: string): { provider: EmailProvider; account: AccountRecord };\n list(): EmailProvider[];\n}\n\nexport interface BuildRegistryOptions {\n store: AccountStore;\n providers?: ProvidersConfig;\n}\n\nexport function buildRegistry(opts: BuildRegistryOptions): Registry {\n const outlookCfg = opts.providers?.outlook;\n const providers = new Map<ProviderId, EmailProvider>();\n providers.set(\"outlook\", new OutlookProvider({\n store: opts.store,\n clientId: outlookCfg?.clientId,\n tenantId: outlookCfg?.tenantId,\n }));\n providers.set(\"imap\", new ImapProvider(opts.store));\n const gmailCfg = opts.providers?.gmail;\n providers.set(\"gmail\", new GmailProvider({\n store: opts.store,\n clientId: gmailCfg?.clientId,\n clientSecret: gmailCfg?.clientSecret,\n }));\n\n function get(id: ProviderId): EmailProvider {\n const p = providers.get(id);\n if (!p) throw new Error(`unknown provider: ${id}`);\n return p;\n }\n\n function resolveByEmail(email: string): {\n provider: EmailProvider;\n account: AccountRecord;\n } {\n const account = opts.store.getAccount(email);\n if (!account) {\n throw new Error(\n `no account registered for \"${email}\". Call add_account first.`,\n );\n }\n return { provider: get(account.provider), account };\n }\n\n return {\n get,\n resolveByEmail,\n list: () => Array.from(providers.values()),\n };\n}\n","import { z } from \"zod\";\nimport type { ResolvedTools } from \"../config.js\";\nimport { markdownToHtml } from \"../markdown-to-html.js\";\n\n/** JSON-stringify a value into a single MCP text content block. */\nexport function ok(\n data: unknown,\n structuredContent?: Record<string, unknown>,\n) {\n const result: {\n content: Array<{ type: \"text\"; text: string }>;\n structuredContent?: Record<string, unknown>;\n } = {\n content: [{ type: \"text\" as const, text: JSON.stringify(data, null, 2) }],\n };\n if (structuredContent !== undefined) {\n result.structuredContent = structuredContent;\n }\n return result;\n}\n\nexport function fail(message: string) {\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: message }],\n };\n}\n\nexport function errMsg(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\n// ── shared schemas ──\n\n/** Enum matching {@link import(\"../providers/types.js\").ProviderId}. */\nexport const providerIdEnum = z.enum([\"outlook\", \"imap\", \"gmail\"]);\n\nexport const emailAddrSchema = z.object({\n address: z.string().email(),\n name: z.string().optional(),\n});\n\nexport const emailAddrOutputSchema = z.object({\n name: z.string().optional(),\n address: z.string(),\n});\n\nexport const accountSummaryOutputSchema = z.object({\n email: z.string(),\n provider: providerIdEnum,\n displayName: z.string().optional(),\n addedAt: z.string(),\n hasSignature: z.boolean(),\n hasStyle: z.boolean(),\n});\n\nexport const styleOutputSchema = z.object({\n fontFamily: z.string().optional(),\n fontSize: z.string().optional(),\n fontColor: z.string().optional(),\n});\n\n/** Full account record including tokens, signature, and style. */\nexport const accountFullOutputSchema = z.object({\n email: z.string(),\n provider: providerIdEnum,\n displayName: z.string().optional(),\n tokens: z.record(z.string(), z.unknown()),\n addedAt: z.string(),\n signature: z.string().optional(),\n style: styleOutputSchema.optional(),\n});\n\nexport const emailSummaryOutputSchema = z.object({\n id: z.string(),\n subject: z.string(),\n from: emailAddrOutputSchema.optional(),\n to: z.array(emailAddrOutputSchema).optional(),\n receivedAt: z.string().optional(),\n preview: z.string().optional(),\n isRead: z.boolean().optional(),\n hasAttachments: z.boolean().optional(),\n folder: z.string().optional(),\n});\n\nexport const attachmentMetaOutputSchema = z.object({\n id: z.string(),\n name: z.string(),\n contentType: z.string().optional(),\n size: z.number().optional(),\n});\n\nexport const folderInfoOutputSchema = z.object({\n id: z.string(),\n displayName: z.string(),\n parentFolderId: z.string().optional(),\n childFolderCount: z.number(),\n totalItemCount: z.number(),\n unreadItemCount: z.number(),\n});\n\n// ── body composition helpers ──\n\nexport interface ComposeBodyInput {\n body: string;\n format: \"html\" | \"markdown\";\n signature?: string;\n style?: { fontFamily?: string; fontSize?: string; fontColor?: string };\n includeSignature: boolean;\n}\n\nexport function composeBody(\n input: ComposeBodyInput,\n): { body: string; isHtml: boolean } {\n const { body, format, signature, style, includeSignature } = input;\n\n // Convert markdown to HTML first, then proceed as HTML\n const htmlBody = format === \"markdown\" ? markdownToHtml(body) : body;\n\n const hasSignature = includeSignature && !!signature;\n const hasStyle = !!(\n style &&\n (style.fontFamily || style.fontSize || style.fontColor)\n );\n\n if (!hasSignature && !hasStyle) {\n return { body: htmlBody, isHtml: true };\n }\n\n const styleAttr = hasStyle ? buildStyleAttr(style!) : \"\";\n let result = hasStyle\n ? `<div style=\"${styleAttr}\">${htmlBody}</div>`\n : htmlBody;\n if (hasSignature) result += `\\n<div class=\"signature\">${signature}</div>`;\n return { body: result, isHtml: true };\n}\n\nexport function buildStyleAttr(style: {\n fontFamily?: string;\n fontSize?: string;\n fontColor?: string;\n}): string {\n const parts: string[] = [];\n if (style.fontFamily) parts.push(`font-family: ${style.fontFamily}`);\n if (style.fontSize) parts.push(`font-size: ${style.fontSize}`);\n if (style.fontColor) parts.push(`color: ${style.fontColor}`);\n return parts.join(\"; \");\n}\n\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/\\n/g, \"<br>\");\n}\n\n// ── tool filtering ──\n\n/** Returns true when `name` should be registered given the tool filtering config. */\nexport function shouldRegister(\n name: string,\n tools: ResolvedTools,\n): boolean {\n if (tools.enabledTools) {\n return tools.enabledTools.has(name);\n }\n if (tools.disabledTools) {\n return !tools.disabledTools.has(name);\n }\n return true;\n}\n","import { marked } from \"marked\";\n\n/** Convert Markdown string to HTML. */\nexport function markdownToHtml(md: string): string {\n return marked.parse(md, { async: false }) as string;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { promises as fs } from \"node:fs\";\nimport { z } from \"zod\";\n\nimport type { AccountStore } from \"../store/account-store.js\";\nimport type { AgentStore } from \"../store/agent-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ProviderId } from \"../providers/types.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport {\n checkAccountAccess,\n checkProvisioning,\n} from \"./agent-context.js\";\nimport {\n ok,\n fail,\n errMsg,\n providerIdEnum,\n accountSummaryOutputSchema,\n accountFullOutputSchema,\n styleOutputSchema,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerAccountTools(\n server: McpServer,\n ctx: {\n store: AccountStore;\n agentStore?: AgentStore;\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { store, registry, tools, agentContext, agentStore } = ctx;\n\n // ---------- list_accounts ----------\n\n const listAccountsOutputSchema = z.object({\n accounts: z.array(accountSummaryOutputSchema),\n });\n\n if (shouldRegister(\"list_accounts\", tools)) {\n server.registerTool(\n \"list_accounts\",\n {\n description:\n \"List all email accounts known to this server (no secrets). \" +\n \"Use the returned `email` value as the `account` argument to other tools.\",\n inputSchema: z.object({}),\n outputSchema: listAccountsOutputSchema,\n },\n async () => {\n const rows = store.listAccounts().map((a) => ({\n email: a.email,\n provider: a.provider,\n displayName: a.displayName,\n addedAt: a.addedAt,\n hasSignature: !!a.signature,\n hasStyle: !!(\n a.style &&\n (a.style.fontFamily || a.style.fontSize || a.style.fontColor)\n ),\n }));\n const data = { accounts: rows };\n return ok(data, data);\n },\n );\n }\n\n // ---------- add_account ----------\n\n const addAccountOutputSchema = z.object({\n status: z.enum([\"pending\", \"ready\"]),\n handle: z.string().optional(),\n verification: z\n .object({\n userCode: z.string(),\n verificationUri: z.string(),\n expiresAt: z.string(),\n message: z.string(),\n })\n .optional(),\n account: accountFullOutputSchema.optional(),\n });\n\n if (shouldRegister(\"add_account\", tools)) {\n server.registerTool(\n \"add_account\",\n {\n description:\n \"Start adding an email account. For Outlook this returns a device code \" +\n \"the user must enter at the verification URL; then call `complete_add_account` \" +\n \"with the returned `handle` to finalize. Disabled in --read-only mode.\",\n inputSchema: z.object({\n provider: providerIdEnum.describe(\"Email backend. 'outlook' (Microsoft Graph) and 'imap' are fully implemented.\"),\n email: z\n .string()\n .email()\n .optional()\n .describe(\n \"Optional hint — the provider will verify it against the auth result.\",\n ),\n config: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"Provider-specific config (e.g. IMAP host/port). Unused for Outlook.\",\n ),\n }),\n outputSchema: addAccountOutputSchema,\n },\n async (args) => {\n const permErr = checkProvisioning(agentContext ?? null);\n if (permErr) return fail(permErr);\n const provider = registry.get(args.provider as ProviderId);\n try {\n const res = await provider.addAccount({\n email: args.email,\n config: args.config,\n });\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- complete_add_account ----------\n\n const completeAddAccountOutputSchema = z.object({\n status: z.enum([\"pending\", \"ready\", \"expired\", \"error\"]),\n account: accountFullOutputSchema.optional(),\n error: z.string().optional(),\n });\n\n if (shouldRegister(\"complete_add_account\", tools)) {\n server.registerTool(\n \"complete_add_account\",\n {\n description:\n \"Poll/finalize a pending add_account flow. Returns `pending` until the user \" +\n \"completes the device-code step, then `ready` with the persisted account.\",\n inputSchema: z.object({\n provider: providerIdEnum,\n handle: z.string().min(1),\n }),\n outputSchema: completeAddAccountOutputSchema,\n },\n async (args) => {\n const permErr = checkProvisioning(agentContext ?? null);\n if (permErr) return fail(permErr);\n const provider = registry.get(args.provider as ProviderId);\n if (!provider.completeAddAccount) {\n return fail(\n `provider ${args.provider} has no async add-account flow`,\n );\n }\n try {\n const res = await provider.completeAddAccount(args.handle);\n // Auto-assign the newly provisioned account to the calling agent.\n if (res.status === \"ready\" && res.account && agentContext && agentStore) {\n agentStore\n .assignAccount(agentContext.agentId, res.account.email)\n .catch(() => {\n /* best-effort — account is provisioned either way */\n });\n }\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- account settings ----------\n\n const accountSettingsOutputSchema = z.object({\n signature: z.string().nullable(),\n style: styleOutputSchema.nullable(),\n });\n\n if (shouldRegister(\"get_account_settings\", tools)) {\n server.registerTool(\n \"get_account_settings\",\n {\n description:\n \"Get signature (HTML) and style preferences for an account.\",\n inputSchema: z.object({ account: z.string().email() }),\n outputSchema: accountSettingsOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const acct = store.getAccount(args.account);\n if (!acct)\n return fail(`no account registered for \"${args.account}\"`);\n const data = {\n signature: acct.signature ?? null,\n style: acct.style ?? null,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n if (shouldRegister(\"set_account_settings\", tools)) {\n server.registerTool(\n \"set_account_settings\",\n {\n description:\n \"Set signature (HTML snippet) and/or style preferences for an account. \" +\n \"Use `signaturePath` to load a signature from a file (useful for signatures with base64 images). \" +\n \"`signature` and `signaturePath` are mutually exclusive. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: z\n .object({\n account: z.string().email(),\n signature: z\n .string()\n .optional()\n .describe(\n \"HTML snippet — may contain formatting, images, links. \" +\n \"Pass an empty string to clear. \" +\n \"Mutually exclusive with `signaturePath`.\",\n ),\n signaturePath: z\n .string()\n .optional()\n .describe(\n \"Path to a file containing the signature HTML. \" +\n \"The file content is read and stored as the signature. \" +\n \"Useful when the signature contains large base64 images. \" +\n \"Mutually exclusive with `signature`.\",\n ),\n style: z\n .object({\n fontFamily: z.string().optional(),\n fontSize: z.string().optional(),\n fontColor: z.string().optional(),\n })\n .optional()\n .describe(\n \"Font preferences applied to outgoing HTML emails. Pass null to clear.\",\n ),\n })\n .refine(\n (data) => !(data.signature !== undefined && data.signaturePath),\n {\n message:\n \"signature and signaturePath are mutually exclusive — use one or the other\",\n },\n ),\n outputSchema: accountSettingsOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const acct = store.getAccount(args.account);\n if (!acct)\n return fail(`no account registered for \"${args.account}\"`);\n let resolvedSignature: string | undefined = acct.signature;\n if (args.signaturePath) {\n resolvedSignature = await fs.readFile(args.signaturePath, \"utf-8\");\n } else if (args.signature !== undefined) {\n resolvedSignature = args.signature || undefined;\n }\n const updated = await store.upsertAccount({\n ...acct,\n signature: resolvedSignature,\n style: args.style ?? acct.style,\n });\n const data = {\n signature: updated.signature ?? null,\n style: updated.style ?? null,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- remove_account ----------\n\n const removeAccountOutputSchema = z.object({\n removed: z.boolean(),\n email: z.string(),\n });\n\n if (shouldRegister(\"remove_account\", tools)) {\n server.registerTool(\n \"remove_account\",\n {\n description:\n \"Forget an account and delete its stored tokens. Disabled in --read-only mode.\",\n inputSchema: z.object({ email: z.string().email() }),\n outputSchema: removeAccountOutputSchema,\n },\n async (args) => {\n const permErr = checkProvisioning(agentContext ?? null);\n if (permErr) return fail(permErr);\n const removed = await store.removeAccount(args.email);\n const data = { removed, email: args.email };\n return ok(data, data);\n },\n );\n }\n}\n","/**\n * Agent identity carried through the tool pipeline in HTTP multi-tenant mode.\n * In stdio mode this is `null` (unrestricted access).\n */\nexport interface AgentContext {\n /** Human-readable agent id from agents.yaml. */\n agentId: string;\n /** Email addresses this agent is authorized to access. */\n accounts: string[];\n /** Whether this agent can provision/remove accounts. */\n provisioning: boolean;\n}\n\n/**\n * Check that an agent is authorized to operate on the given email account.\n * In stdio mode (agentContext is null), access is unrestricted.\n *\n * Returns an error message string if denied, or `null` if allowed.\n */\nexport function checkAccountAccess(\n agentContext: AgentContext | null,\n accountEmail: string,\n): string | null {\n if (!agentContext) return null; // stdio mode — unrestricted\n const norm = accountEmail.trim().toLowerCase();\n if (agentContext.accounts.some((a) => a.toLowerCase() === norm)) {\n return null;\n }\n return `Agent \"${agentContext.agentId}\" is not authorized for account \"${accountEmail}\"`;\n}\n\n/**\n * Check that an agent has provisioning permission.\n * In stdio mode (agentContext is null), provisioning is unrestricted.\n *\n * Returns an error message string if denied, or `null` if allowed.\n */\nexport function checkProvisioning(\n agentContext: AgentContext | null,\n): string | null {\n if (!agentContext) return null; // stdio mode — unrestricted\n if (agentContext.provisioning) return null;\n return `Agent \"${agentContext.agentId}\" does not have provisioning permission`;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { checkAccountAccess } from \"./agent-context.js\";\nimport { selectBody } from \"../html-to-markdown.js\";\nimport {\n ok,\n fail,\n errMsg,\n emailAddrOutputSchema,\n emailSummaryOutputSchema,\n attachmentMetaOutputSchema,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerBrowseTools(\n server: McpServer,\n ctx: {\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { registry, tools, agentContext } = ctx;\n\n // ---------- email ops ----------\n\n const emailListOutputSchema = z.object({\n account: z.string(),\n count: z.number(),\n items: z.array(emailSummaryOutputSchema),\n skip: z.number(),\n hasMore: z.boolean(),\n });\n\n const searchEmailsOutputSchema = z.object({\n account: z.string(),\n count: z.number(),\n items: z.array(emailSummaryOutputSchema),\n });\n\n if (shouldRegister(\"list_emails\", tools)) {\n server.registerTool(\n \"list_emails\",\n {\n description:\n \"List recent emails in a folder of the given account. Pass the user's email \" +\n \"address as `account`; the server routes to the correct backend automatically.\",\n inputSchema: z.object({\n account: z.string().email(),\n folder: z.string().default(\"inbox\").optional(),\n limit: z.number().int().positive().max(100).optional(),\n unreadOnly: z.boolean().optional(),\n skip: z.number().int().min(0).optional(),\n }),\n outputSchema: emailListOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const { items, hasMore } = await provider.listEmails(account, {\n folder: args.folder,\n limit: args.limit,\n unreadOnly: args.unreadOnly,\n skip: args.skip,\n });\n const data = {\n account: account.email,\n count: items.length,\n items,\n skip: args.skip ?? 0,\n hasMore,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n if (shouldRegister(\"search_emails\", tools)) {\n server.registerTool(\n \"search_emails\",\n {\n description:\n \"Search emails by free-text query (KQL on Outlook). Returns lightweight summaries.\",\n inputSchema: z.object({\n account: z.string().email(),\n query: z.string().min(1),\n limit: z.number().int().positive().max(100).optional(),\n }),\n outputSchema: searchEmailsOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const items = await provider.searchEmails(account, args.query, {\n limit: args.limit,\n });\n const data = {\n account: account.email,\n count: items.length,\n items,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n const readEmailOutputSchema = z.object({\n id: z.string(),\n subject: z.string(),\n from: emailAddrOutputSchema.optional(),\n to: z.array(emailAddrOutputSchema).optional(),\n cc: z.array(emailAddrOutputSchema).optional(),\n bcc: z.array(emailAddrOutputSchema).optional(),\n receivedAt: z.string().optional(),\n preview: z.string().optional(),\n isRead: z.boolean().optional(),\n hasAttachments: z.boolean().optional(),\n folder: z.string().optional(),\n attachments: z.array(attachmentMetaOutputSchema).optional(),\n body: z.string(),\n bodyFormat: z.enum([\"markdown\", \"html\", \"text\"]),\n });\n\n if (shouldRegister(\"read_email\", tools)) {\n server.registerTool(\n \"read_email\",\n {\n description:\n \"Fetch a single email with full body and recipients by id. \" +\n \"Body is returned as `body` with `bodyFormat` indicating the format. \" +\n \"Default format is 'markdown' — HTML is automatically converted to save context tokens.\",\n inputSchema: z.object({\n account: z.string().email(),\n id: z.string().min(1),\n format: z\n .enum([\"markdown\", \"html\", \"text\"])\n .default(\"markdown\")\n .optional()\n .describe(\n \"Output body format. 'markdown' converts HTML to Markdown (default), \" +\n \"'html' returns the raw HTML, 'text' returns plain text.\",\n ),\n }),\n outputSchema: readEmailOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const msg = await provider.readEmail(account, args.id);\n const format = args.format ?? \"markdown\";\n const body = selectBody(msg, format);\n const data = {\n id: msg.id,\n subject: msg.subject,\n from: msg.from,\n to: msg.to,\n cc: msg.cc,\n bcc: msg.bcc,\n receivedAt: msg.receivedAt,\n preview: msg.preview,\n isRead: msg.isRead,\n hasAttachments: msg.hasAttachments,\n folder: msg.folder,\n attachments: msg.attachments,\n body,\n bodyFormat: format,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n const readAttachmentOutputSchema = z.object({\n name: z.string(),\n contentType: z.string().optional(),\n path: z.string(),\n });\n\n if (shouldRegister(\"read_attachment\", tools)) {\n server.registerTool(\n \"read_attachment\",\n {\n description:\n \"Download an email attachment to a temporary file and return its path. \" +\n \"Use messageId and attachmentId from a prior read_email call.\",\n inputSchema: z.object({\n account: z.string().email(),\n messageId: z.string().min(1),\n attachmentId: z.string().min(1),\n }),\n outputSchema: readAttachmentOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.readAttachment(\n account,\n args.messageId,\n args.attachmentId,\n );\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import TurndownService from \"turndown\";\n\nconst turndown = new TurndownService();\n\n/** Light wrapper — callers just pass HTML, get markdown back. */\nexport function htmlToMarkdown(html: string): string {\n return turndown.turndown(html);\n}\n\n/** Pick the right body for the requested format. */\nexport function selectBody(\n msg: { bodyHtml?: string; bodyText?: string },\n format: \"markdown\" | \"html\" | \"text\",\n): string {\n switch (format) {\n case \"markdown\": {\n if (msg.bodyHtml) return htmlToMarkdown(msg.bodyHtml);\n if (msg.bodyText) return msg.bodyText;\n return \"\";\n }\n case \"html\": {\n if (msg.bodyHtml) return msg.bodyHtml;\n if (msg.bodyText) return msg.bodyText;\n return \"\";\n }\n case \"text\": {\n if (msg.bodyText) return msg.bodyText;\n if (msg.bodyHtml) return msg.bodyHtml.replace(/<[^>]*>/g, \"\");\n return \"\";\n }\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { checkAccountAccess } from \"./agent-context.js\";\nimport {\n ok,\n fail,\n errMsg,\n folderInfoOutputSchema,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerFolderTools(\n server: McpServer,\n ctx: {\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { registry, tools, agentContext } = ctx;\n\n // ---------- list_folders ----------\n\n const listFoldersOutputSchema = z.object({\n account: z.string(),\n count: z.number(),\n items: z.array(folderInfoOutputSchema),\n });\n\n if (shouldRegister(\"list_folders\", tools)) {\n server.registerTool(\n \"list_folders\",\n {\n description:\n \"List available mail folders. Returns top-level folders by default, \" +\n \"or child folders of the given parent when `parentFolderId` is provided.\",\n inputSchema: z.object({\n account: z.string().email(),\n parentFolderId: z\n .string()\n .optional()\n .describe(\n \"When provided, lists child folders of this folder. \" +\n \"When omitted, lists top-level folders (children of the root).\",\n ),\n }),\n outputSchema: listFoldersOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const items = await provider.listFolders(account, {\n parentFolderId: args.parentFolderId,\n });\n const data = {\n account: account.email,\n count: items.length,\n items,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- create_folder ----------\n\n const createFolderOutputSchema = z.object({\n created: z.literal(true),\n folder: folderInfoOutputSchema,\n });\n\n if (shouldRegister(\"create_folder\", tools)) {\n server.registerTool(\n \"create_folder\",\n {\n description:\n \"Create a new mail folder. Creates under the root folder by default, \" +\n \"or under the specified parent when `parentFolderId` is provided. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: z.object({\n account: z.string().email(),\n displayName: z\n .string()\n .min(1)\n .describe(\"Name of the new folder\"),\n parentFolderId: z\n .string()\n .optional()\n .describe(\n \"When provided, creates the folder as a child of this folder. \" +\n \"When omitted, creates under the root folder.\",\n ),\n }),\n outputSchema: createFolderOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const folder = await provider.createFolder(account, {\n displayName: args.displayName,\n parentFolderId: args.parentFolderId,\n });\n const data = { created: true as const, folder };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- delete_folder ----------\n\n const deleteFolderOutputSchema = z.object({\n deleted: z.literal(true),\n id: z.string(),\n });\n\n if (shouldRegister(\"delete_folder\", tools)) {\n server.registerTool(\n \"delete_folder\",\n {\n description:\n \"Delete a mail folder by ID. Disabled in --read-only mode.\",\n inputSchema: z.object({\n account: z.string().email(),\n folderId: z\n .string()\n .min(1)\n .describe(\"ID of the folder to delete\"),\n }),\n outputSchema: deleteFolderOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.deleteFolder(account, args.folderId);\n const data = { deleted: true as const, id: args.folderId };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- rename_folder ----------\n\n const renameFolderOutputSchema = z.object({\n renamed: z.literal(true),\n folder: folderInfoOutputSchema,\n });\n\n if (shouldRegister(\"rename_folder\", tools)) {\n server.registerTool(\n \"rename_folder\",\n {\n description:\n \"Rename an existing mail folder. Disabled in --read-only mode.\",\n inputSchema: z.object({\n account: z.string().email(),\n folderId: z\n .string()\n .min(1)\n .describe(\"ID of the folder to rename\"),\n newName: z\n .string()\n .min(1)\n .describe(\"New display name for the folder\"),\n }),\n outputSchema: renameFolderOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const folder = await provider.renameFolder(\n account,\n args.folderId,\n args.newName,\n );\n const data = { renamed: true as const, folder };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { checkAccountAccess } from \"./agent-context.js\";\nimport { ok, fail, errMsg, shouldRegister } from \"./shared.js\";\n\nexport function registerOrganizeTools(\n server: McpServer,\n ctx: {\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { registry, tools, agentContext } = ctx;\n\n // Shared helpers — extract the resolved-account lookup and error handling\n // so archive/trash/mark_read/mark_unread handlers stay minimal.\n\n async function moveToWellKnown(\n args: { account: string; id: string },\n destination: string,\n resultKey: string,\n ) {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, destination);\n const data: Record<string, unknown> = { id: args.id };\n data[resultKey] = true;\n return ok(data, data);\n }\n\n async function markReadState(\n args: { account: string; id: string },\n isRead: boolean,\n ) {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.markRead(account, args.id, isRead);\n const data = { marked: true as const, id: args.id, isRead };\n return ok(data, data);\n }\n\n // ---------- archive ----------\n\n const archiveMoveSchema = z.object({\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to move\"),\n });\n\n const archiveOutputSchema = z.object({\n archived: z.literal(true),\n id: z.string(),\n });\n\n if (shouldRegister(\"archive_email\", tools)) {\n server.registerTool(\n \"archive_email\",\n {\n description:\n \"Move a message to the Archive folder. Disabled in --read-only mode.\",\n inputSchema: archiveMoveSchema,\n outputSchema: archiveOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n return await moveToWellKnown(args, \"archive\", \"archived\");\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- trash ----------\n\n const trashOutputSchema = z.object({\n trashed: z.literal(true),\n id: z.string(),\n });\n\n if (shouldRegister(\"trash_email\", tools)) {\n server.registerTool(\n \"trash_email\",\n {\n description:\n \"Move a message to the Deleted Items (trash) folder. Disabled in --read-only mode.\",\n inputSchema: archiveMoveSchema,\n outputSchema: trashOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n return await moveToWellKnown(args, \"deleteditems\", \"trashed\");\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- move ----------\n\n const moveEmailOutputSchema = z.object({\n moved: z.literal(true),\n id: z.string(),\n destination: z.string(),\n });\n\n if (shouldRegister(\"move_email\", tools)) {\n server.registerTool(\n \"move_email\",\n {\n description:\n \"Move a message to any folder by well-known name (e.g. 'inbox', 'drafts', \" +\n \"'junkemail', 'sentitems', 'outbox') or custom folder ID. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: z.object({\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to move\"),\n destination: z\n .string()\n .min(1)\n .describe(\n \"Destination folder — a well-known folder name \" +\n \"('archive', 'deleteditems', 'inbox', 'drafts', 'junkemail', \" +\n \"'sentitems', 'outbox') or a raw folder ID.\",\n ),\n }),\n outputSchema: moveEmailOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, args.destination);\n const data = {\n moved: true as const,\n id: args.id,\n destination: args.destination,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- mark_read / mark_unread ----------\n\n const markReadInputSchema = z.object({\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to mark as read\"),\n });\n\n const markReadOutputSchema = z.object({\n marked: z.literal(true),\n id: z.string(),\n isRead: z.boolean(),\n });\n\n if (shouldRegister(\"mark_read\", tools)) {\n server.registerTool(\n \"mark_read\",\n {\n description:\n \"Mark a message as read. Disabled in --read-only mode.\",\n inputSchema: markReadInputSchema,\n outputSchema: markReadOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n return await markReadState(args, true);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n if (shouldRegister(\"mark_unread\", tools)) {\n server.registerTool(\n \"mark_unread\",\n {\n description:\n \"Mark a message as unread. Disabled in --read-only mode.\",\n inputSchema: markReadInputSchema,\n outputSchema: markReadOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n return await markReadState(args, false);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { AccountRecord, AccountStore } from \"../store/account-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { EmailProvider, SendInput } from \"../providers/types.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { checkAccountAccess } from \"./agent-context.js\";\nimport {\n ok,\n fail,\n errMsg,\n emailAddrSchema,\n composeBody,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerComposeTools(\n server: McpServer,\n ctx: {\n store: AccountStore;\n registry: Registry;\n tools: ResolvedTools;\n agentContext?: AgentContext | null;\n },\n): void {\n const { store, registry, tools, agentContext } = ctx;\n\n const sendEmailSchema = z.object({\n account: z.string().email(),\n to: z.array(emailAddrSchema).min(1),\n cc: z.array(emailAddrSchema).optional(),\n bcc: z.array(emailAddrSchema).optional(),\n subject: z.string(),\n body: z.string(),\n format: z\n .enum([\"html\", \"markdown\"])\n .describe(\n \"Body format. 'html' sends the body as-is (must be valid HTML). \" +\n \"'markdown' converts the body from Markdown to HTML for clean rendering on the recipient side.\",\n ),\n include_signature: z\n .boolean()\n .describe(\n \"Whether to append the account's saved HTML signature to the email. \" +\n \"If true, don't include a signature in the body param to avoid double signature. \" +\n \"Returns an error if true but no signature is configured for this account.\",\n ),\n inReplyTo: z\n .string()\n .optional()\n .describe(\n \"Message ID to reply to. When set, sends as a threaded reply \" +\n \"which includes the quoted thread history automatically.\",\n ),\n replyAll: z\n .boolean()\n .default(false)\n .optional()\n .describe(\n \"When true and `inReplyTo` is set, reply to all recipients \" +\n \"instead of just the sender.\",\n ),\n forwardMessageId: z\n .string()\n .optional()\n .describe(\n \"Message ID to forward. When set, sends as a forward of the \" +\n \"specified message, preserving the original content. \" +\n \"Mutually exclusive with `inReplyTo`.\",\n ),\n });\n\n type SendEmailArgs = z.infer<typeof sendEmailSchema>;\n\n async function handleSendOrDraft(\n args: SendEmailArgs,\n action: (\n provider: EmailProvider,\n account: AccountRecord,\n msg: SendInput,\n ) => Promise<{ id: string }>,\n resultKey: string,\n toolName: string,\n ) {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n if (args.include_signature && !account.signature) {\n return fail(\n \"include_signature is true but no signature is configured for this account. \" +\n \"Set up a signature first with set_account_settings.\",\n );\n }\n const composed = composeBody({\n body: args.body,\n format: args.format,\n signature: account.signature,\n style: account.style,\n includeSignature: args.include_signature,\n });\n if (args.inReplyTo && args.forwardMessageId) {\n return fail(\n \"inReplyTo and forwardMessageId are mutually exclusive — use one or the other\",\n );\n }\n const res = await action(provider, account, {\n to: args.to,\n cc: args.cc,\n bcc: args.bcc,\n subject: args.subject,\n body: composed.body,\n isHtml: composed.isHtml,\n inReplyTo: args.inReplyTo,\n replyAll: args.replyAll,\n forwardMessageId: args.forwardMessageId,\n });\n const result: Record<string, unknown> = { [resultKey]: true, ...res };\n if (toolName === \"draft_email\" && res.id) {\n const draft = await provider.readEmail(account, res.id);\n result.draftHtml = draft.bodyHtml;\n }\n return ok(result, result);\n } catch (err) {\n return fail(errMsg(err));\n }\n }\n\n // ---------- send_email ----------\n\n const sendEmailOutputSchema = {\n sent: z.literal(true),\n id: z.string(),\n };\n\n if (shouldRegister(\"send_email\", tools)) {\n server.registerTool(\n \"send_email\",\n {\n description:\n \"Send an email from the given account. Appends the \" +\n \"account's signature (HTML) and applies style preferences when \" +\n \"`include_signature` is true. Returns an error if \" +\n \"`include_signature` is true but no signature is configured. \" +\n \"When `inReplyTo` is set, sends as a reply (or reply-all) which \" +\n \"preserves thread history and conversation threading. \" +\n \"When `forwardMessageId` is set, sends as a forward of the \" +\n \"specified message, preserving the original content. \" +\n \"`inReplyTo` and `forwardMessageId` are mutually exclusive. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: sendEmailSchema,\n outputSchema: sendEmailOutputSchema,\n },\n async (args) =>\n handleSendOrDraft(\n args as SendEmailArgs,\n (p, a, m) => p.sendEmail(a, m),\n \"sent\",\n \"send_email\",\n ),\n );\n }\n\n // ---------- draft_email ----------\n\n const draftEmailOutputSchema = {\n draft: z.literal(true),\n id: z.string(),\n draftHtml: z.string().optional(),\n };\n\n if (shouldRegister(\"draft_email\", tools)) {\n server.registerTool(\n \"draft_email\",\n {\n description:\n \"Create a draft email from the given account without sending it. \" +\n \"Works identically to send_email — appends signature when \" +\n \"`include_signature` is true, applies style, and supports replies \" +\n \"and forwards — but saves the message to the Drafts folder \" +\n \"instead of sending. Returns the draft message ID and the draft's \" +\n \"HTML body content (`draftHtml`). Before sending the draft, \" +\n \"inspect `draftHtml` to verify the draft looks correct: no \" +\n \"duplicate signature blocks, no broken or missing inline images, \" +\n \"no malformed HTML, and no other formatting issues. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: sendEmailSchema,\n outputSchema: draftEmailOutputSchema,\n },\n async (args) =>\n handleSendOrDraft(\n args as SendEmailArgs,\n (p, a, m) => p.saveDraft(a, m),\n \"draft\",\n \"draft_email\",\n ),\n );\n }\n\n // ---------- edit_draft ----------\n\n const editDraftSchema = z.object({\n account: z.string().email(),\n id: z.string().min(1).describe(\"Draft message ID to edit\"),\n to: z.array(emailAddrSchema).optional(),\n cc: z.array(emailAddrSchema).optional(),\n bcc: z.array(emailAddrSchema).optional(),\n subject: z.string().optional(),\n body: z.string().optional(),\n format: z\n .enum([\"html\", \"markdown\"])\n .optional()\n .describe(\n \"Body format. Only meaningful when `body` is also provided. \" +\n \"'html' sends the body as-is (must be valid HTML). \" +\n \"'markdown' converts the body from Markdown to HTML for clean rendering on the recipient side.\",\n ),\n include_signature: z\n .boolean()\n .optional()\n .describe(\n \"Whether to re-apply the account's saved HTML signature to the body. \" +\n \"If true, don't include a signature in the body param. \" +\n \"Only meaningful when `body` is also provided. \" +\n \"Returns an error if true but no signature is configured for this account.\",\n ),\n });\n\n type EditDraftArgs = z.infer<typeof editDraftSchema>;\n\n const editDraftOutputSchema = {\n edited: z.literal(true),\n id: z.string(),\n draftHtml: z.string().optional(),\n };\n\n if (shouldRegister(\"edit_draft\", tools)) {\n server.registerTool(\n \"edit_draft\",\n {\n description:\n \"Edit an existing draft email by ID. Only the fields you provide \" +\n \"are updated — unmentioned fields stay unchanged. When `body` is \" +\n \"provided and `include_signature` is true, the account's signature \" +\n \"is re-applied. Returns the draft ID and the draft's updated HTML \" +\n \"body content (`draftHtml`). Before sending, inspect `draftHtml` \" +\n \"to verify the draft looks correct. \" +\n \"Does not support changing `inReplyTo` or `forwardMessageId` — \" +\n \"those are set at creation time via `draft_email`. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: editDraftSchema,\n outputSchema: editDraftOutputSchema,\n },\n async (args) => {\n const a = args as EditDraftArgs;\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, a.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(a.account);\n if (a.include_signature && !account.signature) {\n return fail(\n \"include_signature is true but no signature is configured for this account. \" +\n \"Set up a signature first with set_account_settings.\",\n );\n }\n let bodyPayload: string | undefined;\n let isHtmlPayload: boolean | undefined;\n if (a.body !== undefined) {\n const composed = composeBody({\n body: a.body,\n format: a.format ?? \"html\",\n signature: account.signature,\n style: account.style,\n includeSignature: !!a.include_signature,\n });\n bodyPayload = composed.body;\n isHtmlPayload = composed.isHtml;\n }\n const res = await provider.updateDraft(account, a.id, {\n to: a.to,\n cc: a.cc,\n bcc: a.bcc,\n subject: a.subject,\n body: bodyPayload,\n isHtml: isHtmlPayload,\n });\n const draft = await provider.readEmail(account, res.id);\n const result: Record<string, unknown> = {\n edited: true as const,\n id: res.id,\n draftHtml: draft.bodyHtml,\n };\n return ok(result, result);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- send_draft ----------\n\n const sendDraftOutputSchema = {\n sent: z.literal(true),\n id: z.string(),\n };\n\n if (shouldRegister(\"send_draft\", tools)) {\n server.registerTool(\n \"send_draft\",\n {\n description:\n \"Send an existing draft email by ID. \" +\n \"Use this with draft IDs returned by `draft_email` or `edit_draft`. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Draft message ID to send\"),\n },\n outputSchema: sendDraftOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.sendDraft(account, args.id);\n const data = { sent: true as const, id: res.id };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- add_attachment_to_draft ----------\n\n const addAttachmentOutputSchema = {\n attached: z.literal(true),\n id: z.string(),\n attachment: z.object({\n id: z.string(),\n name: z.string(),\n contentType: z.string().optional(),\n }),\n };\n\n if (shouldRegister(\"add_attachment_to_draft\", tools)) {\n server.registerTool(\n \"add_attachment_to_draft\",\n {\n description:\n \"Add a file attachment to an existing draft email by ID. \" +\n \"`contentBytes` must be base64-encoded file content. \" +\n \"`contentType` is the MIME type (e.g. 'application/pdf'); \" +\n \"defaults to 'application/octet-stream' if omitted. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Draft message ID\"),\n name: z\n .string()\n .min(1)\n .describe(\"Attachment filename (e.g. 'report.pdf')\"),\n contentBytes: z\n .string()\n .min(1)\n .describe(\"Base64-encoded file content\"),\n contentType: z\n .string()\n .optional()\n .describe(\"MIME type (e.g. 'application/pdf')\"),\n },\n outputSchema: addAttachmentOutputSchema,\n },\n async (args) => {\n try {\n const accessErr = checkAccountAccess(agentContext ?? null, args.account);\n if (accessErr) return fail(accessErr);\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.addAttachmentToDraft(\n account,\n args.id,\n args.name,\n args.contentBytes,\n args.contentType,\n );\n const data = {\n attached: true as const,\n id: res.id,\n attachment: res.attachment,\n };\n return ok(data, data as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { ResolvedTools } from \"../config.js\";\nimport type { WatchNotification } from \"../watcher/index.js\";\nimport type { AgentContext } from \"./agent-context.js\";\nimport { ok, fail, errMsg, shouldRegister } from \"./shared.js\";\n\nexport interface NotificationToolContext {\n tools: ResolvedTools;\n /** Shared buffer the watcher writes to. Draining is the tool's job. */\n notificationBuffer: WatchNotification[];\n agentContext?: AgentContext | null;\n}\n\nexport function registerNotificationTools(\n server: McpServer,\n ctx: NotificationToolContext,\n): void {\n const { tools, notificationBuffer, agentContext } = ctx;\n\n const notifyOutputSchema = z.object({\n count: z.number(),\n items: z.array(\n z.object({\n type: z.enum([\"new_emails\", \"auth_failure\"]),\n account: z.string(),\n emails: z.array(z.unknown()).optional(),\n error: z.string().optional(),\n timestamp: z.string(),\n }),\n ),\n });\n\n if (shouldRegister(\"check_notifications\", tools)) {\n server.registerTool(\n \"check_notifications\",\n {\n description:\n \"Check for pending email watch notifications. \" +\n \"Returns new-email alerts and auth-failure warnings that the inbox watcher \" +\n \"has accumulated since the last call. Drains the notification buffer on read.\",\n inputSchema: z.object({}),\n outputSchema: notifyOutputSchema,\n },\n async () => {\n try {\n // Drain atomically — splice returns removed items and clears them\n // from the array in one operation.\n const pending = notificationBuffer.splice(0);\n // Scope to agent's accounts in HTTP mode; unrestricted in stdio.\n const filtered = agentContext\n ? pending.filter((n) =>\n agentContext.accounts.some(\n (a) => a.toLowerCase() === n.account.toLowerCase(),\n ),\n )\n : pending;\n const data = { count: filtered.length, items: filtered };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\nimport type { AccountStore } from \"../store/account-store.js\";\nimport type { AgentStore } from \"../store/agent-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport type { AgentContext } from \"./agent-context.js\";\n\n// Re-export compose helpers for tests\nexport { composeBody, escapeHtml, buildStyleAttr } from \"./shared.js\";\nexport { markdownToHtml } from \"../markdown-to-html.js\";\n\n// Submodule registration functions\nimport { registerAccountTools } from \"./accounts.js\";\nimport { registerBrowseTools } from \"./browse.js\";\nimport { registerFolderTools } from \"./folders.js\";\nimport { registerOrganizeTools } from \"./organize.js\";\nimport { registerComposeTools } from \"./compose.js\";\nimport { registerNotificationTools } from \"./notifications.js\";\nimport type { WatchNotification } from \"../watcher/index.js\";\n\nexport interface RegisterToolsOptions {\n store: AccountStore;\n agentStore?: AgentStore;\n registry: Registry;\n tools: ResolvedTools;\n notificationBuffer?: WatchNotification[];\n /** Agent identity for access control. null = stdio mode (unrestricted). */\n agentContext?: AgentContext | null;\n}\n\nexport function registerTools(\n server: McpServer,\n opts: RegisterToolsOptions,\n): void {\n const { store, registry, tools, agentContext, agentStore } = opts;\n\n registerAccountTools(server, { store, registry, tools, agentContext, agentStore });\n registerBrowseTools(server, { registry, tools, agentContext });\n registerFolderTools(server, { registry, tools, agentContext });\n registerOrganizeTools(server, { registry, tools, agentContext });\n registerComposeTools(server, { store, registry, tools, agentContext });\n if (opts.notificationBuffer) {\n registerNotificationTools(server, {\n tools,\n notificationBuffer: opts.notificationBuffer,\n agentContext,\n });\n }\n}\n","{\n \"name\": \"hypermail-mcp\",\n \"version\": \"0.6.2\",\n \"description\": \"Unified email MCP server — operate any inbox (Outlook now, IMAP/Gmail later) by passing an email address.\",\n \"type\": \"module\",\n \"bin\": {\n \"hypermail-mcp\": \"dist/cli.js\"\n },\n \"main\": \"dist/cli.js\",\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"dev:http\": \"tsup && node dist/cli.js --http --config hypermail-config.http.json\",\n \"start\": \"node dist/cli.js\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"prepublishOnly\": \"pnpm build && pnpm test\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"keywords\": [\n \"mcp\",\n \"model-context-protocol\",\n \"email\",\n \"outlook\",\n \"microsoft-graph\",\n \"imap\"\n ],\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/mateotiedra/hypermail-mcp.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/mateotiedra/hypermail-mcp/issues\"\n },\n \"dependencies\": {\n \"@azure/msal-node\": \"^2.16.2\",\n \"@microsoft/microsoft-graph-client\": \"^3.0.7\",\n \"@modelcontextprotocol/sdk\": \"^1.0.4\",\n \"google-auth-library\": \"^9.15.1\",\n \"googleapis\": \"^144.0.0\",\n \"imapflow\": \"^1.3.3\",\n \"isomorphic-fetch\": \"^3.0.0\",\n \"js-yaml\": \"^4.2.0\",\n \"marked\": \"^18.0.4\",\n \"nodemailer\": \"^8.0.8\",\n \"turndown\": \"^7.2.4\",\n \"zod\": \"^4.4.3\"\n },\n \"optionalDependencies\": {\n \"keytar\": \"^7.9.0\"\n },\n \"devDependencies\": {\n \"@types/isomorphic-fetch\": \"^0.0.39\",\n \"@types/js-yaml\": \"^4.0.9\",\n \"@types/node\": \"^22.10.2\",\n \"@types/nodemailer\": \"^8.0.0\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"vitest\": \"^2.1.8\"\n }\n}\n","import pkg from \"../package.json\" with { type: \"json\" };\nexport const VERSION: string = pkg.version;\n","import { readFileSync } from \"node:fs\";\nimport { z } from \"zod\";\n\n// ── Schema ──\n\nconst httpConfigSchema = z.object({\n enabled: z.boolean().default(false),\n port: z.number().int().min(1).max(65535).default(3000),\n host: z.string().default(\"127.0.0.1\"),\n});\n\nconst toolsConfigSchema = z.object({\n disabled: z.array(z.string()).optional(),\n enabled: z.array(z.string()).optional(),\n});\n\nconst outlookProviderSchema = z.object({\n clientId: z.string().optional(),\n tenantId: z.string().optional(),\n});\n\nconst gmailProviderSchema = z.object({\n clientId: z.string().optional(),\n clientSecret: z.string().optional(),\n});\n\nconst providersConfigSchema = z.object({\n outlook: outlookProviderSchema.optional(),\n gmail: gmailProviderSchema.optional(),\n});\n\nconst watchConfigSchema = z.object({\n enabled: z.boolean().default(true),\n pollIntervalSeconds: z.number().int().min(10).max(3600).default(60),\n});\n\nconst rawConfigSchema = z.object({\n dataDir: z.string().optional(),\n http: httpConfigSchema.optional(),\n tools: toolsConfigSchema.optional(),\n providers: providersConfigSchema.optional(),\n watch: watchConfigSchema.optional(),\n});\n\n// ── Types ──\n\nexport interface HttpConfig {\n enabled: boolean;\n port: number;\n host: string;\n}\n\nexport interface ToolsConfig {\n disabled?: string[];\n enabled?: string[];\n}\n\nexport interface OutlookProviderConfig {\n clientId?: string;\n tenantId?: string;\n}\n\nexport interface GmailProviderConfig {\n clientId?: string;\n clientSecret?: string;\n}\n\nexport interface ProvidersConfig {\n outlook?: OutlookProviderConfig;\n gmail?: GmailProviderConfig;\n}\n\nexport interface WatchConfig {\n enabled: boolean;\n pollIntervalSeconds: number;\n}\n\n/** Fully resolved application configuration (after ${VAR} expansion and CLI merge). */\nexport interface AppConfig {\n dataDir?: string;\n http: HttpConfig;\n tools?: ToolsConfig;\n providers?: ProvidersConfig;\n watch?: WatchConfig;\n /** Path to agents.yaml for HTTP multi-tenant mode. Only used when http.enabled is true. */\n agentsConfigPath?: string;\n}\n\n/** CLI flags that can override config file values. */\nexport interface CliOverrides {\n http?: boolean;\n port?: number;\n host?: string;\n dataDir?: string;\n agentsConfig?: string;\n}\n\n// ── Known tool names ──\n\n/**\n * Every tool that {@link registerTools} may register.\n * Used for validation — typos in tools.disabled / tools.enabled are caught at startup.\n */\nexport const KNOWN_TOOLS = [\n \"list_accounts\",\n \"add_account\",\n \"complete_add_account\",\n \"get_account_settings\",\n \"set_account_settings\",\n \"remove_account\",\n \"list_emails\",\n \"search_emails\",\n \"read_email\",\n \"read_attachment\",\n \"archive_email\",\n \"trash_email\",\n \"move_email\",\n \"mark_read\",\n \"mark_unread\",\n \"list_folders\",\n \"create_folder\",\n \"delete_folder\",\n \"rename_folder\",\n \"send_email\",\n \"draft_email\",\n \"edit_draft\",\n \"send_draft\",\n \"add_attachment_to_draft\",\n \"check_notifications\",\n] as const;\n\n// ── ${VAR} resolution ──\n\nconst ENV_VAR_RE = /\\$\\{([A-Z_][A-Z0-9_]*)\\}/g;\n\nfunction resolveEnvVars(value: string): string {\n return value.replace(ENV_VAR_RE, (_match, name: string) => {\n return process.env[name] ?? \"\";\n });\n}\n\n/** Recursively resolve `${VAR}` placeholders in all string values. */\nfunction deepResolve(obj: unknown): unknown {\n if (typeof obj === \"string\") return resolveEnvVars(obj);\n if (Array.isArray(obj)) return obj.map(deepResolve);\n if (obj && typeof obj === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(obj as Record<string, unknown>)) {\n out[key] = deepResolve(val);\n }\n return out;\n }\n return obj;\n}\n\n// ── Validation ──\n\nfunction validateToolNames(\n toolNames: string[] | undefined,\n listName: string,\n): void {\n if (!toolNames || toolNames.length === 0) return;\n const known = new Set<string>(KNOWN_TOOLS as readonly string[]);\n for (const name of toolNames) {\n if (!known.has(name)) {\n throw new Error(\n `Unknown tool \"${name}\" in ${listName}. Known tools: ${KNOWN_TOOLS.join(\", \")}`,\n );\n }\n }\n}\n\n// ── Loading ──\n\n/**\n * Load and validate `hypermail-config.json`.\n *\n * @param configPath File path, or `undefined` to use defaults.\n * @param cliOverrides CLI flags that take precedence over config file values.\n * @returns A fully resolved {@link AppConfig}.\n */\nexport function loadConfig(\n configPath: string | undefined,\n cliOverrides: CliOverrides = {},\n): AppConfig {\n let raw: Record<string, unknown> = {};\n\n if (configPath) {\n try {\n raw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch (err) {\n const detail =\n err instanceof SyntaxError\n ? \"Invalid JSON\"\n : err instanceof Error\n ? err.message\n : String(err);\n throw new Error(`Failed to read config file \"${configPath}\": ${detail}`);\n }\n }\n\n // Resolve ${VAR} before zod validation so env-var references become real values.\n raw = deepResolve(raw) as Record<string, unknown>;\n\n // Validate structure\n const parsed = rawConfigSchema.parse(raw);\n\n // Manual validations that go beyond zod's capabilities\n if (parsed.tools) {\n if (parsed.tools.disabled && parsed.tools.enabled) {\n throw new Error(\n \"tools.disabled and tools.enabled are mutually exclusive — use one or the other\",\n );\n }\n if (parsed.tools.enabled !== undefined && parsed.tools.enabled.length === 0) {\n throw new Error(\n \"tools.enabled is empty — at least one tool must be listed. \" +\n \"To enable all tools, omit the tools section entirely.\",\n );\n }\n validateToolNames(parsed.tools.disabled, \"tools.disabled\");\n validateToolNames(parsed.tools.enabled, \"tools.enabled\");\n }\n\n // Merge CLI overrides on top of config file values\n const http: HttpConfig = {\n enabled: cliOverrides.http ?? parsed.http?.enabled ?? false,\n port: cliOverrides.port ?? parsed.http?.port ?? 3000,\n host: cliOverrides.host ?? parsed.http?.host ?? \"127.0.0.1\",\n };\n\n return {\n dataDir:\n cliOverrides.dataDir ??\n parsed.dataDir ??\n process.env.HYPERMAIL_MCP_DATA_DIR,\n http,\n tools: parsed.tools\n ? { disabled: parsed.tools.disabled, enabled: parsed.tools.enabled }\n : undefined,\n providers: parsed.providers as ProvidersConfig | undefined,\n watch: parsed.watch as WatchConfig | undefined,\n agentsConfigPath:\n cliOverrides.agentsConfig ??\n process.env.HYPERMAIL_AGENTS_CONFIG,\n };\n}\n\n// ── Helpers ──\n\n/** Extracted tool filtering state for {@link registerTools}. */\nexport interface ResolvedTools {\n /** If set, only these tools are registered (allowlist mode). */\n enabledTools: Set<string> | null;\n /** If set, these tools are NOT registered (blocklist mode). */\n disabledTools: Set<string> | null;\n}\n\n/** Convert {@link AppConfig.tools} into the sets that {@link registerTools} consumes. */\nexport function resolveTools(config: AppConfig): ResolvedTools {\n if (!config.tools) {\n return { enabledTools: null, disabledTools: null };\n }\n return {\n enabledTools: config.tools.enabled\n ? new Set(config.tools.enabled)\n : null,\n disabledTools: config.tools.disabled\n ? new Set(config.tools.disabled)\n : null,\n };\n}\n","import type { AccountStore, AccountRecord } from \"../store/account-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { EmailSummary } from \"../providers/types.js\";\n\n// ── types ──\n\nexport interface WatchNotification {\n type: \"new_emails\" | \"auth_failure\";\n account: string;\n /** New emails since last poll. Only present for type: \"new_emails\". */\n emails?: EmailSummary[];\n /** Error message. Only present for type: \"auth_failure\". */\n error?: string;\n /** ISO timestamp of when this notification was created. */\n timestamp: string;\n}\n\nexport interface WatcherManagerOptions {\n registry: Registry;\n store: AccountStore;\n /** Polling interval per account, in seconds. */\n pollIntervalSeconds: number;\n /**\n * Called when a push notification should be sent to the connected client.\n * May be called even when no SSE session is active — the callback should\n * handle that gracefully (e.g. by catching send errors).\n */\n onNotification: (notification: WatchNotification) => void;\n /**\n * Shared in-memory buffer of pending notifications. The watcher appends\n * new entries; the check_notifications tool drains them via splice(0).\n */\n buffer: WatchNotification[];\n /**\n * Optional list of email addresses to watch. When provided, only these\n * accounts are polled. When omitted, all stored accounts are polled\n * (stdio mode / legacy behavior).\n */\n accountFilter?: string[];\n}\n\n// ── manager ──\n\nexport class WatcherManager {\n private readonly opts: WatcherManagerOptions;\n private timers: ReturnType<typeof setInterval>[] = [];\n private running = false;\n /** Per-account inflight guards to prevent overlapping polls. */\n private readonly inflight = new Map<string, boolean>();\n /** Accounts with active polling timers (lowercased email). */\n private readonly tracked = new Set<string>();\n\n constructor(opts: WatcherManagerOptions) {\n this.opts = opts;\n }\n\n start(): void {\n if (this.running) return;\n this.running = true;\n\n // Initial scan — schedule polling for all matching accounts.\n this.scanAccounts();\n\n // Periodic re-scan to pick up accounts added after start().\n const rescanTimer = setInterval(() => {\n if (!this.running) return;\n this.scanAccounts();\n }, this.opts.pollIntervalSeconds * 1000);\n this.timers.push(rescanTimer);\n }\n\n stop(): void {\n this.running = false;\n for (const t of this.timers) clearInterval(t);\n this.timers = [];\n this.tracked.clear();\n }\n\n // ── internals ──\n\n private scanAccounts(): void {\n let accounts = this.opts.store.listAccounts();\n if (this.opts.accountFilter) {\n const filter = new Set(this.opts.accountFilter.map((e) => e.toLowerCase()));\n accounts = accounts.filter((a) => filter.has(a.email.toLowerCase()));\n }\n for (const account of accounts) {\n this.schedulePoll(account);\n }\n }\n\n private schedulePoll(account: AccountRecord): void {\n const key = account.email.toLowerCase();\n if (this.tracked.has(key)) return;\n this.tracked.add(key);\n\n // Run immediately on start, then on interval.\n this.pollAccount(account).catch(() => {\n /* errors surfaced via notifications */\n });\n\n const timer = setInterval(() => {\n if (!this.running) return;\n this.pollAccount(account).catch(() => {\n /* errors surfaced via notifications */\n });\n }, this.opts.pollIntervalSeconds * 1000);\n\n this.timers.push(timer);\n }\n\n private async pollAccount(account: AccountRecord): Promise<void> {\n const key = account.email.toLowerCase();\n if (this.inflight.get(key)) return;\n this.inflight.set(key, true);\n\n try {\n const { provider } = this.opts.registry.resolveByEmail(account.email);\n const seenIds = new Set(account.lastSeenIds ?? []);\n const isFirstPoll = !account.lastSeenAt && !account.lastSeenIds?.length;\n const limit = 25;\n const MAX_PAGES = 5;\n let skip = 0;\n let pageCount = 0;\n const newEmails: EmailSummary[] = [];\n let newestTimestamp = account.lastSeenAt ?? \"\";\n\n // Paginate through inbox until we hit a previously seen email ID\n // or exhaust available pages.\n let hitBoundary = false;\n while (pageCount < MAX_PAGES) {\n const { items, hasMore } = await provider.listEmails(account, {\n folder: \"inbox\",\n limit,\n skip,\n });\n pageCount++;\n\n for (const item of items) {\n if (!item.receivedAt) continue;\n if (seenIds.has(item.id)) {\n hitBoundary = true;\n break;\n }\n newEmails.push(item);\n if (item.receivedAt > newestTimestamp) {\n newestTimestamp = item.receivedAt;\n }\n }\n\n if (hitBoundary || !hasMore) break;\n skip += limit;\n }\n\n // First poll: set baseline silently. Subsequent polls: notify.\n if (!isFirstPoll && newEmails.length > 0) {\n this.enqueue({\n type: \"new_emails\",\n account: account.email,\n emails: newEmails,\n timestamp: new Date().toISOString(),\n });\n }\n\n // Persist updated state: prepend new IDs to lastSeenIds (cap 200),\n // update lastSeenAt. On empty-inbox first poll, mark current time\n // as baseline so future polls exit first-poll mode.\n if (isFirstPoll && newEmails.length === 0 && !newestTimestamp) {\n newestTimestamp = new Date().toISOString();\n }\n const newIds = newEmails.map((e) => e.id);\n const updatedLastSeenIds = [\n ...newIds,\n ...(account.lastSeenIds ?? []),\n ].slice(0, 200);\n\n try {\n await this.opts.store.upsertAccount({\n ...account,\n lastSeenAt: newestTimestamp || undefined,\n lastSeenIds: updatedLastSeenIds,\n });\n } catch (storeErr) {\n // eslint-disable-next-line no-console\n console.error(\n \"[hypermail-mcp] failed to persist poll state for\",\n account.email,\n \":\",\n storeErr instanceof Error ? storeErr.message : String(storeErr),\n );\n }\n } catch (err: unknown) {\n this.enqueue({\n type: \"auth_failure\",\n account: account.email,\n error: err instanceof Error ? err.message : String(err),\n timestamp: new Date().toISOString(),\n });\n } finally {\n this.inflight.delete(key);\n }\n }\n\n private enqueue(notification: WatchNotification): void {\n this.opts.buffer.push(notification);\n // Also try push delivery — may fail silently if no SSE connection.\n try {\n this.opts.onNotification(notification);\n } catch {\n /* push not available; tool-based polling fallback will deliver it */\n }\n }\n}\n","import { readFileSync, watch, type FSWatcher } from \"node:fs\";\nimport { load as loadYaml } from \"js-yaml\";\nimport { z } from \"zod\";\n\nimport type { AgentStore } from \"../store/agent-store.js\";\n\n// ── Schema ──\n\nconst agentDefSchema = z.object({\n id: z\n .string()\n .min(1)\n .regex(\n /^[a-z0-9_-]+$/,\n \"agent id must contain only lowercase letters, digits, hyphens, and underscores\",\n ),\n api_key: z\n .string()\n .min(1)\n .regex(\n /^hm_sk_[a-f0-9]{64}$/,\n \"api_key must match hm_sk_ prefix + 64 hex chars (use `hypermail-mcp generate-key`)\",\n ),\n name: z.string().min(1),\n accounts: z.array(z.string().email()).optional().default([]),\n provisioning: z.boolean().optional().default(false),\n});\n\nconst emailAccountDefSchema = z.object({\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n display_name: z.string().optional(),\n});\n\nconst agentsConfigSchema = z.object({\n agents: z.array(agentDefSchema).optional().default([]),\n email_accounts: z\n .record(z.string().email(), emailAccountDefSchema)\n .optional()\n .default({}),\n});\n\n// ── Types ──\n\nexport interface AgentDef {\n id: string;\n api_key: string;\n name: string;\n accounts: string[];\n provisioning: boolean;\n}\n\nexport interface EmailAccountDef {\n provider: \"outlook\" | \"imap\" | \"gmail\";\n display_name?: string;\n}\n\nexport interface AgentsConfig {\n agents: AgentDef[];\n email_accounts: Record<string, EmailAccountDef>;\n}\n\n// ── Loading ──\n\n/**\n * Load and validate `agents.yaml`.\n *\n * @param configPath Absolute or relative path to the YAML file.\n * @returns The parsed and validated {@link AgentsConfig}.\n */\nexport function loadAgentsConfig(configPath: string): AgentsConfig {\n let raw: unknown;\n try {\n raw = loadYaml(readFileSync(configPath, \"utf-8\"));\n } catch (err) {\n if (err instanceof Error && \"code\" in err && (err as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new Error(\n `Agents config file not found: ${configPath}. ` +\n \"Create an agents.yaml with at least one agent to enable HTTP multi-tenant mode.\",\n );\n }\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to parse agents config \"${configPath}\": ${detail}`);\n }\n\n const parsed = agentsConfigSchema.parse(raw ?? {});\n\n // Validate: no duplicate agent ids\n const ids = new Set<string>();\n for (const a of parsed.agents) {\n if (ids.has(a.id)) {\n throw new Error(`Duplicate agent id \"${a.id}\" in agents config`);\n }\n ids.add(a.id);\n }\n\n return {\n agents: parsed.agents.map((a) => ({\n id: a.id,\n api_key: a.api_key,\n name: a.name,\n accounts: a.accounts,\n provisioning: a.provisioning,\n })),\n email_accounts: parsed.email_accounts as Record<string, EmailAccountDef>,\n };\n}\n\n// ── Syncing ──\n\n/**\n * Sync agent definitions from the parsed YAML config into the AgentStore.\n *\n * - New agents (in config but not in store) are upserted with their plaintext API key hashed.\n * - Existing agents (in both) are updated (name, accounts, provisioning). API key hash is\n * NOT touched unless the plaintext key changed — avoids re-hashing on every reload.\n * - Stale agents (in store but not in config) are removed.\n * - Auto-assigned accounts (added via `add_account` tool) are preserved — they are merged\n * with the YAML-defined assignments per agent.\n *\n * @returns The list of agent ids that were removed (so their sessions can be invalidated).\n */\nexport async function syncAgentsToStore(\n config: AgentsConfig,\n store: AgentStore,\n): Promise<string[]> {\n const configAgentIds = new Set(config.agents.map((a) => a.id));\n const storedAgents = store.listAgents();\n\n // Upsert config-defined agents\n for (const def of config.agents) {\n await store.upsertAgent({\n id: def.id,\n plaintextApiKey: def.api_key,\n name: def.name,\n accounts: def.accounts,\n provisioning: def.provisioning,\n });\n }\n\n // Remove agents not in config anymore\n const removed: string[] = [];\n for (const stored of storedAgents) {\n if (!configAgentIds.has(stored.id)) {\n await store.removeAgent(stored.id);\n removed.push(stored.id);\n }\n }\n\n return removed;\n}\n\n// ── Live reload ──\n\nexport interface LiveReloadHandle {\n /** Stop watching for changes. */\n close(): void;\n}\n\n/**\n * Watch `agents.yaml` for changes and sync into the AgentStore on every\n * modification. Debounces rapid writes (e.g. editor atomic saves).\n *\n * @param configPath Absolute path to agents.yaml.\n * @param store The AgentStore to sync into.\n * @param onChange Called after each sync with the list of removed agent ids.\n * @param onError Called on parse/sync errors (logged, not fatal).\n */\nexport function watchAgentsConfig(\n configPath: string,\n store: AgentStore,\n onChange: (removedIds: string[]) => void,\n onError: (err: Error) => void,\n): LiveReloadHandle {\n let timer: ReturnType<typeof setTimeout> | null = null;\n let watcher: FSWatcher | null = null;\n\n const reload = async () => {\n try {\n const config = loadAgentsConfig(configPath);\n const removed = await syncAgentsToStore(config, store);\n onChange(removed);\n } catch (err) {\n onError(err instanceof Error ? err : new Error(String(err)));\n }\n };\n\n // Initial load\n reload().catch((err) => onError(err));\n\n // Watch for changes\n try {\n watcher = watch(configPath, (_eventType) => {\n // Debounce: coalesce rapid successive events into one reload.\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = null;\n reload().catch((err) => onError(err));\n }, 200);\n });\n } catch (err) {\n // fs.watch may fail on some platforms (e.g. network mounts) — not fatal;\n // config can still be loaded once at startup.\n }\n\n return {\n close() {\n if (timer) clearTimeout(timer);\n if (watcher) watcher.close();\n },\n };\n}\n"],"mappings":"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","names":["randomBytes","randomUUID","path","fs","path","fs","path","path","fs","FILE_NAME","fs","path","randomUUID","existing","randomUUID","tmpdir","pathJoin","clampLimit","mapSummary","clampLimit","mapSummary","pathJoin","tmpdir","randomUUID","randomUUID","path","randomUUID","DEFAULT_SCOPES","beginDeviceCode","awaitDeviceCodeReady","existing","writeFileSync","tmpdir","pathJoin","MailComposer","h","mapSummary","mapFolder","clampLimit","buildRawMessage","MailComposer","listEmails","clampLimit","mapSummary","searchEmails","readEmail","readAttachment","pathJoin","tmpdir","writeFileSync","listFolders","mapFolder","randomUUID","Buffer","MailComposer","sendEmail","Buffer","buildRawMessage","saveDraft","updateDraft","moveEmail","sendDraft","addAttachmentToDraft","MailComposer","randomUUID","markRead","createFolder","mapFolder","renameFolder","deleteFolder","beginDeviceCode","awaitDeviceCodeReady","randomUUID","listEmails","searchEmails","readEmail","readAttachment","sendEmail","saveDraft","updateDraft","moveEmail","sendDraft","addAttachmentToDraft","markRead","listFolders","createFolder","renameFolder","deleteFolder","fs","z","z","fs","z","z","z","z","z","z","z","z","z","z","z","readFileSync","z","path","randomUUID","randomBytes"]}
|