read-email-mcp 1.0.0 → 2.0.1
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/LICENSE +21 -21
- package/README.md +177 -34
- package/dist/accounts-cli.d.ts +1 -0
- package/dist/accounts-cli.js +530 -0
- package/dist/accounts-cli.js.map +1 -0
- package/dist/config.d.ts +30 -2
- package/dist/config.js +219 -15
- package/dist/config.js.map +1 -1
- package/dist/imap-discovery.d.ts +52 -0
- package/dist/imap-discovery.js +207 -0
- package/dist/imap-discovery.js.map +1 -0
- package/dist/imap.d.ts +41 -5
- package/dist/imap.js +332 -64
- package/dist/imap.js.map +1 -1
- package/dist/index.js +28 -8
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +12 -0
- package/dist/providers.js +122 -0
- package/dist/providers.js.map +1 -0
- package/dist/server.d.ts +3 -6
- package/dist/server.js +10 -8
- package/dist/server.js.map +1 -1
- package/dist/store.d.ts +31 -2
- package/dist/store.js +300 -153
- package/dist/store.js.map +1 -1
- package/dist/tools.d.ts +189 -174
- package/dist/tools.js +714 -60
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +44 -1
- package/docs/production-readiness.md +84 -70
- package/package.json +10 -9
- package/scripts/smoke-mcp.mjs +8 -1
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import readline from "node:readline";
|
|
5
|
+
import { defaultAccountsPath, loadConfig, resolvePassword, DEFAULT_ENV_FILENAME } from "./config.js";
|
|
6
|
+
import { checkConnectivity } from "./imap.js";
|
|
7
|
+
import { discoverImapSettings, isSelfSignedCertError } from "./imap-discovery.js";
|
|
8
|
+
import { detectProvider, findProvider, PROVIDER_PRESETS } from "./providers.js";
|
|
9
|
+
export async function runCli(argv) {
|
|
10
|
+
const [command, sub, ...rest] = argv;
|
|
11
|
+
if (command === "init") {
|
|
12
|
+
return cmdInit(parseFlags(argv.slice(1)));
|
|
13
|
+
}
|
|
14
|
+
if (command === "accounts") {
|
|
15
|
+
const flags = parseFlags(rest);
|
|
16
|
+
switch (sub) {
|
|
17
|
+
case "add":
|
|
18
|
+
return cmdAccountAdd(flags);
|
|
19
|
+
case "list":
|
|
20
|
+
return cmdAccountList(flags);
|
|
21
|
+
case "remove":
|
|
22
|
+
return cmdAccountRemove(flags);
|
|
23
|
+
case "test":
|
|
24
|
+
return cmdAccountTest(flags);
|
|
25
|
+
case "discover":
|
|
26
|
+
return cmdAccountDiscover(flags);
|
|
27
|
+
default:
|
|
28
|
+
process.stderr.write(`Unknown accounts subcommand "${sub ?? ""}".\n\n`);
|
|
29
|
+
printUsage();
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
printUsage();
|
|
34
|
+
return command === "help" || command === "--help" || command === "-h" ? 0 : 1;
|
|
35
|
+
}
|
|
36
|
+
function printUsage() {
|
|
37
|
+
process.stdout.write(`read-email-mcp — read-only IMAP email mirror for MCP clients
|
|
38
|
+
|
|
39
|
+
Usage:
|
|
40
|
+
read-email-mcp [server options] Start the MCP server (stdio)
|
|
41
|
+
read-email-mcp accounts add Add an account interactively (or via flags)
|
|
42
|
+
read-email-mcp accounts list List configured accounts
|
|
43
|
+
read-email-mcp accounts remove <name> Remove an account by name or email
|
|
44
|
+
read-email-mcp accounts test [name] Test IMAP connectivity for one or all accounts
|
|
45
|
+
read-email-mcp accounts discover <email> Auto-detect IMAP settings for a domain
|
|
46
|
+
read-email-mcp init Print MCP client config snippet
|
|
47
|
+
|
|
48
|
+
Options:
|
|
49
|
+
--accounts <path> Accounts file (default: ~/.read-email-mcp/accounts.json)
|
|
50
|
+
--env-file <path> Env file for passwordEnv vars (auto-loads ./.env and ~/.read-email-mcp/.env)
|
|
51
|
+
--data-dir <path> Base storage directory (default: ~/.read-email-mcp)
|
|
52
|
+
|
|
53
|
+
accounts add flags (all optional — you'll be prompted for what's missing):
|
|
54
|
+
--name, --email, --provider (${PROVIDER_PRESETS.map((preset) => preset.id).join(", ")}),
|
|
55
|
+
--imap-host, --imap-port, --imap-secure, --imap-user, --group (repeatable),
|
|
56
|
+
--password-env <VAR>, --password-command <cmd>, --password <value>,
|
|
57
|
+
--allow-self-signed (skip TLS certificate verification), --test, --no-test
|
|
58
|
+
|
|
59
|
+
For custom/self-hosted domains the wizard auto-detects IMAP settings via
|
|
60
|
+
Mozilla autoconfig, DNS SRV records, MX-based provider inference, and probing
|
|
61
|
+
imap./mail. hostnames — run 'accounts discover <email>' to see what it finds.
|
|
62
|
+
`);
|
|
63
|
+
}
|
|
64
|
+
function parseFlags(args) {
|
|
65
|
+
const values = new Map();
|
|
66
|
+
const multi = new Map();
|
|
67
|
+
const positionals = [];
|
|
68
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
69
|
+
const arg = args[index];
|
|
70
|
+
if (!arg.startsWith("--")) {
|
|
71
|
+
positionals.push(arg);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const eq = arg.indexOf("=");
|
|
75
|
+
const key = eq === -1 ? arg.slice(2) : arg.slice(2, eq);
|
|
76
|
+
const next = args[index + 1];
|
|
77
|
+
const value = eq === -1 ? (next !== undefined && !next.startsWith("--") ? args[++index] : undefined) : arg.slice(eq + 1);
|
|
78
|
+
if (value === undefined) {
|
|
79
|
+
values.set(key, "true");
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (key === "group") {
|
|
83
|
+
multi.set(key, [...(multi.get(key) ?? []), value]);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
values.set(key, value);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { values, multi, positionals };
|
|
90
|
+
}
|
|
91
|
+
function accountsFilePath(flags) {
|
|
92
|
+
const baseDir = flags.values.get("data-dir") ?? path.join(os.homedir(), ".read-email-mcp");
|
|
93
|
+
return flags.values.get("accounts") ?? process.env.ACCOUNTS_FILE ?? defaultAccountsPath(baseDir);
|
|
94
|
+
}
|
|
95
|
+
function readAccountsFile(filePath) {
|
|
96
|
+
try {
|
|
97
|
+
const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
98
|
+
return { accounts: Array.isArray(parsed.accounts) ? parsed.accounts : [] };
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return { accounts: [] };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function writeAccountsFile(filePath, data) {
|
|
105
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
106
|
+
fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, { mode: 0o600 });
|
|
107
|
+
}
|
|
108
|
+
function appendEnvVar(filePath, key, value) {
|
|
109
|
+
const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : "";
|
|
110
|
+
const alreadySet = existing
|
|
111
|
+
.split(/\r?\n/)
|
|
112
|
+
.some((line) => new RegExp(`^\\s*(?:export\\s+)?${key}\\s*=`).test(line));
|
|
113
|
+
if (alreadySet) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
117
|
+
const needsNewline = existing.length > 0 && !existing.endsWith("\n");
|
|
118
|
+
const rendered = /[\s"'#\\]/.test(value)
|
|
119
|
+
? `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`
|
|
120
|
+
: value;
|
|
121
|
+
fs.appendFileSync(filePath, `${needsNewline ? "\n" : ""}${key}=${rendered}\n`, { mode: 0o600 });
|
|
122
|
+
}
|
|
123
|
+
class Prompter {
|
|
124
|
+
rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
125
|
+
ask(question, fallback) {
|
|
126
|
+
const suffix = fallback !== undefined ? ` [${fallback}]` : "";
|
|
127
|
+
return new Promise((resolve) => {
|
|
128
|
+
this.rl.question(`${question}${suffix}: `, (answer) => {
|
|
129
|
+
resolve(answer.trim() || (fallback ?? ""));
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async askHidden(question) {
|
|
134
|
+
this.rl.pause();
|
|
135
|
+
const stdin = process.stdin;
|
|
136
|
+
process.stdout.write(`${question}: `);
|
|
137
|
+
return new Promise((resolve) => {
|
|
138
|
+
let value = "";
|
|
139
|
+
const cleanup = () => {
|
|
140
|
+
stdin.setRawMode?.(false);
|
|
141
|
+
stdin.off("data", onData);
|
|
142
|
+
this.rl.resume();
|
|
143
|
+
};
|
|
144
|
+
const onData = (chunk) => {
|
|
145
|
+
for (const char of chunk.toString("utf8")) {
|
|
146
|
+
if (char === "\u0003") {
|
|
147
|
+
cleanup();
|
|
148
|
+
process.stdout.write("\n");
|
|
149
|
+
resolve("");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (char === "\r" || char === "\n") {
|
|
153
|
+
cleanup();
|
|
154
|
+
process.stdout.write("\n");
|
|
155
|
+
resolve(value);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (char === "\u007f" || char === "\b") {
|
|
159
|
+
value = value.slice(0, -1);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
value += char;
|
|
163
|
+
process.stdout.write("*");
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
stdin.setRawMode?.(true);
|
|
167
|
+
stdin.resume();
|
|
168
|
+
stdin.on("data", onData);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
close() {
|
|
172
|
+
this.rl.close();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async function cmdAccountAdd(flags) {
|
|
176
|
+
const filePath = accountsFilePath(flags);
|
|
177
|
+
const interactive = process.stdin.isTTY === true;
|
|
178
|
+
const prompter = new Prompter();
|
|
179
|
+
const get = async (key, question, fallback) => {
|
|
180
|
+
const fromFlags = flags.values.get(key);
|
|
181
|
+
if (fromFlags !== undefined) {
|
|
182
|
+
return fromFlags;
|
|
183
|
+
}
|
|
184
|
+
if (!interactive) {
|
|
185
|
+
return fallback ?? "";
|
|
186
|
+
}
|
|
187
|
+
return prompter.ask(question, fallback);
|
|
188
|
+
};
|
|
189
|
+
try {
|
|
190
|
+
const email = (await get("email", "Email address")).toLowerCase();
|
|
191
|
+
if (!email || !email.includes("@")) {
|
|
192
|
+
throw new Error("An email address is required (pass --email or run interactively)");
|
|
193
|
+
}
|
|
194
|
+
const detected = detectProvider(email);
|
|
195
|
+
if (detected) {
|
|
196
|
+
process.stdout.write(`Detected provider: ${detected.label} (${detected.imapHost}:${detected.imapPort})\n`);
|
|
197
|
+
for (const hint of detected.hints) {
|
|
198
|
+
process.stdout.write(` ! ${hint}\n`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Custom/self-hosted domain: try to discover the IMAP settings instead of
|
|
202
|
+
// making the user look them up. Skipped when --imap-host was given.
|
|
203
|
+
let discovered = null;
|
|
204
|
+
if (!detected && !flags.values.has("imap-host")) {
|
|
205
|
+
process.stdout.write("No known provider for this domain — auto-detecting IMAP settings...\n");
|
|
206
|
+
discovered = await discoverImapSettings(email);
|
|
207
|
+
if (discovered) {
|
|
208
|
+
const via = discovered.source === "autoconfig"
|
|
209
|
+
? "autoconfig"
|
|
210
|
+
: discovered.source === "dns-srv"
|
|
211
|
+
? "DNS SRV record"
|
|
212
|
+
: discovered.source === "mx"
|
|
213
|
+
? "MX records (hosted by a known provider)"
|
|
214
|
+
: "hostname probe";
|
|
215
|
+
process.stdout.write(`Found via ${via}: ${discovered.host}:${discovered.port} (${discovered.secure ? "TLS" : "STARTTLS"})\n`);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
process.stdout.write("Could not auto-detect — enter the settings manually.\n");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const name = await get("name", "Account name", email);
|
|
222
|
+
const providerInput = await get("provider", "Provider preset", detected?.id ?? discovered?.providerId ?? "");
|
|
223
|
+
const preset = providerInput ? findProvider(providerInput) : detected;
|
|
224
|
+
if (providerInput && !preset) {
|
|
225
|
+
throw new Error(`Unknown provider "${providerInput}". Known: ${PROVIDER_PRESETS.map((p) => p.id).join(", ")}`);
|
|
226
|
+
}
|
|
227
|
+
const imapHost = await get("imap-host", "IMAP host", preset?.imapHost ?? discovered?.host);
|
|
228
|
+
if (!imapHost) {
|
|
229
|
+
throw new Error("An IMAP host is required (no provider preset or auto-detection matched)");
|
|
230
|
+
}
|
|
231
|
+
const imapPort = await get("imap-port", "IMAP port", String(preset?.imapPort ?? discovered?.port ?? 993));
|
|
232
|
+
const imapSecure = await get("imap-secure", "IMAP TLS/SSL (true/false)", String(preset?.imapSecure ?? discovered?.secure ?? true));
|
|
233
|
+
const imapUser = await get("imap-user", "IMAP username", discovered?.user ?? email);
|
|
234
|
+
const groupFlag = flags.multi.get("group") ?? [];
|
|
235
|
+
const groups = groupFlag.length > 0
|
|
236
|
+
? groupFlag
|
|
237
|
+
: interactive
|
|
238
|
+
? (await prompter.ask("Groups (comma-separated, optional)", ""))
|
|
239
|
+
.split(",")
|
|
240
|
+
.map((group) => group.trim())
|
|
241
|
+
.filter(Boolean)
|
|
242
|
+
: [];
|
|
243
|
+
const allowSelfSigned = flags.values.has("allow-self-signed");
|
|
244
|
+
const entry = {
|
|
245
|
+
name,
|
|
246
|
+
email,
|
|
247
|
+
...(providerInput ? { provider: providerInput } : {}),
|
|
248
|
+
imapHost,
|
|
249
|
+
imapPort: Number(imapPort),
|
|
250
|
+
imapSecure: imapSecure !== "false",
|
|
251
|
+
...(imapUser !== email ? { imapUser } : {}),
|
|
252
|
+
...(allowSelfSigned ? { imapTlsRejectUnauthorized: false } : {}),
|
|
253
|
+
...(groups.length ? { groups } : {})
|
|
254
|
+
};
|
|
255
|
+
const password = flags.values.get("password");
|
|
256
|
+
const passwordEnv = flags.values.get("password-env");
|
|
257
|
+
const passwordCommand = flags.values.get("password-command");
|
|
258
|
+
if (password) {
|
|
259
|
+
entry.password = password;
|
|
260
|
+
process.stderr.write("Warning: storing the password inline in the accounts file. Prefer --password-env or --password-command.\n");
|
|
261
|
+
}
|
|
262
|
+
else if (passwordEnv) {
|
|
263
|
+
entry.passwordEnv = passwordEnv;
|
|
264
|
+
}
|
|
265
|
+
else if (passwordCommand) {
|
|
266
|
+
entry.passwordCommand = passwordCommand;
|
|
267
|
+
}
|
|
268
|
+
else if (interactive) {
|
|
269
|
+
const method = await prompter.ask("Password method — [e]nv var (recommended), [c]ommand (password manager), [i]nline", "e");
|
|
270
|
+
if (method.startsWith("c")) {
|
|
271
|
+
entry.passwordCommand = await prompter.ask('Command that prints the password (e.g. "op read op://Private/Email/password")');
|
|
272
|
+
}
|
|
273
|
+
else if (method.startsWith("i")) {
|
|
274
|
+
entry.password = await prompter.askHidden("Password (stored inline in the accounts file)");
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
const suggested = `READ_EMAIL_MCP_${name.replace(/[^a-zA-Z0-9]/g, "_").toUpperCase()}_PASSWORD`;
|
|
278
|
+
const envName = await prompter.ask("Environment variable name", suggested);
|
|
279
|
+
entry.passwordEnv = envName;
|
|
280
|
+
const baseDir = flags.values.get("data-dir") ?? path.join(os.homedir(), ".read-email-mcp");
|
|
281
|
+
const envFile = flags.values.get("env-file") ?? path.join(baseDir, DEFAULT_ENV_FILENAME);
|
|
282
|
+
if ((await prompter.ask(`Save the password to ${envFile} now? (y/n)`, "y")).startsWith("y")) {
|
|
283
|
+
const secret = await prompter.askHidden("Password/app-password");
|
|
284
|
+
if (secret) {
|
|
285
|
+
appendEnvVar(envFile, envName, secret);
|
|
286
|
+
process.env[envName] = secret;
|
|
287
|
+
process.stdout.write(`Saved ${envName} to ${envFile}\n`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
process.stdout.write(`Remember to set ${envName} in the environment before starting the server.\n`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
throw new Error("No password method given — pass --password-env, --password-command, or --password");
|
|
297
|
+
}
|
|
298
|
+
// Verify the credentials actually connect before writing the file.
|
|
299
|
+
// Interactive mode tests by default (--no-test skips); scripts opt in with --test.
|
|
300
|
+
const wantTest = flags.values.has("test") || (interactive && !flags.values.has("no-test"));
|
|
301
|
+
if (wantTest) {
|
|
302
|
+
const saved = await testEntry(entry, filePath, name, interactive ? prompter : null, flags.values.has("test"));
|
|
303
|
+
if (!saved) {
|
|
304
|
+
return 1;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const data = readAccountsFile(filePath);
|
|
308
|
+
const existing = data.accounts.findIndex((candidate) => String(candidate.email ?? "").toLowerCase() === email || String(candidate.name ?? "").toLowerCase() === name.toLowerCase());
|
|
309
|
+
if (existing >= 0) {
|
|
310
|
+
data.accounts[existing] = entry;
|
|
311
|
+
process.stdout.write(`Updated existing account "${name}" in ${filePath}\n`);
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
data.accounts.push(entry);
|
|
315
|
+
process.stdout.write(`Added account "${name}" to ${filePath}\n`);
|
|
316
|
+
}
|
|
317
|
+
writeAccountsFile(filePath, data);
|
|
318
|
+
process.stdout.write(`Test it with: read-email-mcp accounts test ${name}\n`);
|
|
319
|
+
return 0;
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
323
|
+
return 1;
|
|
324
|
+
}
|
|
325
|
+
finally {
|
|
326
|
+
prompter.close();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Verify a freshly-built account entry connects before saving it. Returns true
|
|
331
|
+
* when the entry should be written. With a Prompter (interactive) it offers a
|
|
332
|
+
* self-signed retry on certificate errors and a "save anyway" fallback;
|
|
333
|
+
* non-interactive --test fails hard on any connection failure.
|
|
334
|
+
*/
|
|
335
|
+
async function testEntry(entry, filePath, label, prompter, testRequired) {
|
|
336
|
+
let pass;
|
|
337
|
+
try {
|
|
338
|
+
pass = resolvePassword(entry, process.env, filePath, label);
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
if (testRequired) {
|
|
342
|
+
process.stderr.write(`Cannot test the connection: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
process.stdout.write(`Skipping connection test: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
const attempt = () => checkConnectivity({
|
|
349
|
+
host: String(entry.imapHost),
|
|
350
|
+
port: Number(entry.imapPort ?? 993),
|
|
351
|
+
secure: entry.imapSecure !== false,
|
|
352
|
+
...(entry.imapTlsRejectUnauthorized === false ? { tls: { rejectUnauthorized: false } } : {}),
|
|
353
|
+
auth: { user: String(entry.imapUser ?? entry.email), pass }
|
|
354
|
+
});
|
|
355
|
+
process.stdout.write(`Testing connection to ${entry.imapHost}:${entry.imapPort ?? 993}...\n`);
|
|
356
|
+
let result = await attempt();
|
|
357
|
+
if (!result.ok &&
|
|
358
|
+
prompter &&
|
|
359
|
+
entry.imapTlsRejectUnauthorized !== false &&
|
|
360
|
+
isSelfSignedCertError(result.error ?? "")) {
|
|
361
|
+
const retry = await prompter.ask("Certificate verification failed (self-signed cert?). Retry without verifying it? (y/n)", "y");
|
|
362
|
+
if (retry.startsWith("y")) {
|
|
363
|
+
entry.imapTlsRejectUnauthorized = false;
|
|
364
|
+
result = await attempt();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
if (result.ok) {
|
|
368
|
+
process.stdout.write(`Connected — ${result.mailboxCount} mailboxes found.\n`);
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
process.stderr.write(`Connection test failed: ${result.error}\n`);
|
|
372
|
+
if (prompter) {
|
|
373
|
+
return (await prompter.ask("Save the account anyway? (y/n)", "n")).startsWith("y");
|
|
374
|
+
}
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
async function cmdAccountDiscover(flags) {
|
|
378
|
+
const email = flags.positionals[0]?.toLowerCase();
|
|
379
|
+
if (!email || !email.includes("@")) {
|
|
380
|
+
process.stderr.write("Usage: read-email-mcp accounts discover <email>\n");
|
|
381
|
+
return 1;
|
|
382
|
+
}
|
|
383
|
+
const preset = detectProvider(email);
|
|
384
|
+
if (preset) {
|
|
385
|
+
process.stdout.write(`${email} — provider preset "${preset.id}": ${preset.imapHost}:${preset.imapPort} (${preset.imapSecure ? "TLS" : "STARTTLS"})\n`);
|
|
386
|
+
for (const hint of preset.hints) {
|
|
387
|
+
process.stdout.write(` ! ${hint}\n`);
|
|
388
|
+
}
|
|
389
|
+
return 0;
|
|
390
|
+
}
|
|
391
|
+
process.stdout.write(`No provider preset — probing ${email.split("@")[1]}...\n`);
|
|
392
|
+
const found = await discoverImapSettings(email);
|
|
393
|
+
if (!found) {
|
|
394
|
+
process.stdout.write("Nothing found. Check your provider's docs or DNS (autoconfig, _imaps._tcp SRV) and pass --imap-host to 'accounts add'.\n");
|
|
395
|
+
return 1;
|
|
396
|
+
}
|
|
397
|
+
process.stdout.write(`Found via ${found.source}: host=${found.host} port=${found.port} ` +
|
|
398
|
+
`secure=${found.secure}${found.user ? ` user=${found.user}` : ""}` +
|
|
399
|
+
`${found.providerId ? ` provider=${found.providerId}` : ""}\n`);
|
|
400
|
+
return 0;
|
|
401
|
+
}
|
|
402
|
+
async function cmdAccountList(flags) {
|
|
403
|
+
const filePath = accountsFilePath(flags);
|
|
404
|
+
const data = readAccountsFile(filePath);
|
|
405
|
+
if (data.accounts.length === 0) {
|
|
406
|
+
process.stdout.write(`No accounts in ${filePath}. Add one with: read-email-mcp accounts add\n`);
|
|
407
|
+
return 0;
|
|
408
|
+
}
|
|
409
|
+
for (const entry of data.accounts) {
|
|
410
|
+
const secret = entry.passwordEnv
|
|
411
|
+
? `env:${entry.passwordEnv}`
|
|
412
|
+
: entry.passwordCommand
|
|
413
|
+
? "passwordCommand"
|
|
414
|
+
: entry.password
|
|
415
|
+
? "inline password"
|
|
416
|
+
: "no password configured";
|
|
417
|
+
const groups = Array.isArray(entry.groups) && entry.groups.length ? ` groups=[${entry.groups.join(",")}]` : "";
|
|
418
|
+
process.stdout.write(`${entry.name ?? "?"} <${entry.email ?? "?"}> — ${entry.imapHost ?? "auto"}:${entry.imapPort ?? 993}` +
|
|
419
|
+
`${groups} (${secret})\n`);
|
|
420
|
+
}
|
|
421
|
+
process.stdout.write(`File: ${filePath}\n`);
|
|
422
|
+
return 0;
|
|
423
|
+
}
|
|
424
|
+
async function cmdAccountRemove(flags) {
|
|
425
|
+
const query = flags.positionals[0];
|
|
426
|
+
if (!query) {
|
|
427
|
+
process.stderr.write("Usage: read-email-mcp accounts remove <name-or-email>\n");
|
|
428
|
+
return 1;
|
|
429
|
+
}
|
|
430
|
+
const filePath = accountsFilePath(flags);
|
|
431
|
+
const data = readAccountsFile(filePath);
|
|
432
|
+
const needle = query.toLowerCase();
|
|
433
|
+
const index = data.accounts.findIndex((entry) => String(entry.name ?? "").toLowerCase() === needle || String(entry.email ?? "").toLowerCase() === needle);
|
|
434
|
+
if (index === -1) {
|
|
435
|
+
process.stderr.write(`No account named "${query}" in ${filePath}\n`);
|
|
436
|
+
return 1;
|
|
437
|
+
}
|
|
438
|
+
const [removed] = data.accounts.splice(index, 1);
|
|
439
|
+
writeAccountsFile(filePath, data);
|
|
440
|
+
process.stdout.write(`Removed account "${removed.name ?? removed.email}" from ${filePath}\n`);
|
|
441
|
+
return 0;
|
|
442
|
+
}
|
|
443
|
+
async function cmdAccountTest(flags) {
|
|
444
|
+
const args = [];
|
|
445
|
+
const accountsPath = flags.values.get("accounts");
|
|
446
|
+
if (accountsPath) {
|
|
447
|
+
args.push("--accounts", accountsPath);
|
|
448
|
+
}
|
|
449
|
+
const envFile = flags.values.get("env-file");
|
|
450
|
+
if (envFile) {
|
|
451
|
+
args.push("--env-file", envFile);
|
|
452
|
+
}
|
|
453
|
+
let config;
|
|
454
|
+
try {
|
|
455
|
+
config = loadConfig(process.env, {
|
|
456
|
+
args,
|
|
457
|
+
...(flags.values.get("data-dir") ? { dataDir: flags.values.get("data-dir") } : {})
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
catch (error) {
|
|
461
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
462
|
+
return 1;
|
|
463
|
+
}
|
|
464
|
+
const needle = flags.positionals[0]?.toLowerCase();
|
|
465
|
+
const targets = needle
|
|
466
|
+
? config.accounts.filter((account) => account.account.name.toLowerCase() === needle || account.account.email.toLowerCase() === needle)
|
|
467
|
+
: config.accounts;
|
|
468
|
+
if (targets.length === 0) {
|
|
469
|
+
process.stderr.write(`No account matching "${flags.positionals[0]}"\n`);
|
|
470
|
+
return 1;
|
|
471
|
+
}
|
|
472
|
+
let failures = 0;
|
|
473
|
+
for (const account of targets) {
|
|
474
|
+
const result = await checkConnectivity(account.imap);
|
|
475
|
+
if (result.ok) {
|
|
476
|
+
process.stdout.write(`OK ${account.account.name} <${account.account.email}> — ${result.host} (${result.mailboxCount} mailboxes)\n`);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
failures += 1;
|
|
480
|
+
process.stdout.write(`FAIL ${account.account.name} <${account.account.email}> — ${result.host}: ${result.error}\n`);
|
|
481
|
+
if (isSelfSignedCertError(result.error ?? "")) {
|
|
482
|
+
process.stdout.write(' hint: certificate verification failed — for a self-signed cert set "imapTlsRejectUnauthorized": false on this account\n');
|
|
483
|
+
}
|
|
484
|
+
if (account.account.provider) {
|
|
485
|
+
const preset = PROVIDER_PRESETS.find((p) => p.id === account.account.provider);
|
|
486
|
+
for (const hint of preset?.hints ?? []) {
|
|
487
|
+
process.stdout.write(` hint: ${hint}\n`);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return failures === 0 ? 0 : 1;
|
|
493
|
+
}
|
|
494
|
+
async function cmdInit(flags) {
|
|
495
|
+
const filePath = accountsFilePath(flags);
|
|
496
|
+
const hasAccounts = readAccountsFile(filePath).accounts.length > 0;
|
|
497
|
+
const accountsArgs = hasAccounts ? `, "--accounts", "${filePath.replace(/\\/g, "\\\\")}"` : "";
|
|
498
|
+
process.stdout.write(`Add this to your MCP client configuration (e.g. claude_desktop_config.json):
|
|
499
|
+
|
|
500
|
+
{
|
|
501
|
+
"mcpServers": {
|
|
502
|
+
"read-email": {
|
|
503
|
+
"command": "npx",
|
|
504
|
+
"args": ["-y", "read-email-mcp"${accountsArgs}]
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
For opencode (opencode.json / .opencode.json), the equivalent is:
|
|
510
|
+
|
|
511
|
+
{
|
|
512
|
+
"mcp": {
|
|
513
|
+
"read-email": {
|
|
514
|
+
"type": "local",
|
|
515
|
+
"command": ["npx", "-y", "read-email-mcp"${accountsArgs}],
|
|
516
|
+
"enabled": true
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
`);
|
|
521
|
+
if (!hasAccounts) {
|
|
522
|
+
process.stdout.write(`\nNo accounts file found at ${filePath} yet.\n` +
|
|
523
|
+
`Create one with: read-email-mcp accounts add\n` +
|
|
524
|
+
`Or configure a single account via env vars in the client config:\n\n` +
|
|
525
|
+
` "env": { "EMAIL": "you@example.com", "PASSWORD": "app-password" }\n` +
|
|
526
|
+
`(IMAP host auto-detects for common providers: ${PROVIDER_PRESETS.map((p) => p.id).join(", ")})\n`);
|
|
527
|
+
}
|
|
528
|
+
return 0;
|
|
529
|
+
}
|
|
530
|
+
//# sourceMappingURL=accounts-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts-cli.js","sourceRoot":"","sources":["../src/accounts-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface AccountConfig {
|
|
2
2
|
account: {
|
|
3
|
+
name: string;
|
|
3
4
|
email: string;
|
|
4
5
|
accountHash: string;
|
|
6
|
+
provider: string | null;
|
|
7
|
+
groups: string[];
|
|
5
8
|
};
|
|
6
9
|
imap: {
|
|
7
10
|
host: string;
|
|
8
11
|
port: number;
|
|
9
12
|
secure: boolean;
|
|
13
|
+
tls?: {
|
|
14
|
+
rejectUnauthorized?: boolean;
|
|
15
|
+
};
|
|
10
16
|
auth: {
|
|
11
17
|
user: string;
|
|
12
18
|
pass: string;
|
|
@@ -19,12 +25,34 @@ export interface AppConfig {
|
|
|
19
25
|
rawDir: string;
|
|
20
26
|
};
|
|
21
27
|
}
|
|
28
|
+
export interface ServerConfig {
|
|
29
|
+
accounts: AccountConfig[];
|
|
30
|
+
baseDir: string;
|
|
31
|
+
}
|
|
22
32
|
interface LoadConfigOptions {
|
|
23
33
|
dataDir?: string;
|
|
24
34
|
args?: string[];
|
|
25
35
|
}
|
|
36
|
+
export interface AccountsFileEntry {
|
|
37
|
+
name?: string;
|
|
38
|
+
email?: string;
|
|
39
|
+
provider?: string;
|
|
40
|
+
password?: string;
|
|
41
|
+
passwordEnv?: string;
|
|
42
|
+
passwordCommand?: string;
|
|
43
|
+
imapHost?: string;
|
|
44
|
+
imapPort?: number | string;
|
|
45
|
+
imapSecure?: boolean | string;
|
|
46
|
+
imapUser?: string;
|
|
47
|
+
imapTlsRejectUnauthorized?: boolean | string;
|
|
48
|
+
groups?: string[];
|
|
49
|
+
}
|
|
26
50
|
export declare const DEFAULT_IMAP_PORT = 993;
|
|
27
51
|
export declare const DEFAULT_IMAP_SECURE = true;
|
|
52
|
+
export declare const DEFAULT_ACCOUNTS_FILENAME = "accounts.json";
|
|
53
|
+
export declare const DEFAULT_ENV_FILENAME = ".env";
|
|
28
54
|
export declare function hashAccount(email: string): string;
|
|
29
|
-
export declare function
|
|
55
|
+
export declare function defaultAccountsPath(baseDir: string): string;
|
|
56
|
+
export declare function loadConfig(env?: NodeJS.ProcessEnv, options?: LoadConfigOptions): ServerConfig;
|
|
57
|
+
export declare function resolvePassword(entry: AccountsFileEntry, env: NodeJS.ProcessEnv, filePath: string, label: string): string;
|
|
30
58
|
export {};
|