read-email-mcp 1.0.0 → 2.0.0

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/dist/config.js CHANGED
@@ -1,8 +1,13 @@
1
1
  import crypto from "node:crypto";
2
+ import { execSync } from "node:child_process";
3
+ import fs from "node:fs";
2
4
  import os from "node:os";
3
5
  import path from "node:path";
6
+ import { detectProvider, findProvider, PROVIDER_PRESETS } from "./providers.js";
4
7
  export const DEFAULT_IMAP_PORT = 993;
5
8
  export const DEFAULT_IMAP_SECURE = true;
9
+ export const DEFAULT_ACCOUNTS_FILENAME = "accounts.json";
10
+ export const DEFAULT_ENV_FILENAME = ".env";
6
11
  export function hashAccount(email) {
7
12
  return crypto
8
13
  .createHash("sha256")
@@ -10,8 +15,64 @@ export function hashAccount(email) {
10
15
  .digest("hex")
11
16
  .slice(0, 16);
12
17
  }
18
+ export function defaultAccountsPath(baseDir) {
19
+ return path.join(baseDir, DEFAULT_ACCOUNTS_FILENAME);
20
+ }
13
21
  export function loadConfig(env = process.env, options = {}) {
14
22
  const args = options.args ?? process.argv.slice(2);
23
+ const baseDir = options.dataDir ?? path.join(os.homedir(), ".read-email-mcp");
24
+ loadEnvFiles(env, args, baseDir);
25
+ const explicitAccountsFile = getArgValue(args, "--accounts") ?? env.ACCOUNTS_FILE;
26
+ const legacyEmail = getArgValue(args, "--email") ?? env.EMAIL;
27
+ const defaultFile = defaultAccountsPath(baseDir);
28
+ const accountsFile = explicitAccountsFile ?? (!legacyEmail && fs.existsSync(defaultFile) ? defaultFile : undefined);
29
+ const accounts = accountsFile
30
+ ? loadAccountsFile(accountsFile, env, baseDir)
31
+ : [loadSingleAccount(env, args, baseDir)];
32
+ assertUniqueAccounts(accounts);
33
+ return { accounts, baseDir };
34
+ }
35
+ function loadEnvFiles(env, args, baseDir) {
36
+ const explicit = getArgValue(args, "--env-file") ?? env.ENV_FILE;
37
+ if (explicit) {
38
+ applyEnvFile(path.resolve(explicit), env, true);
39
+ return;
40
+ }
41
+ applyEnvFile(path.join(process.cwd(), DEFAULT_ENV_FILENAME), env, false);
42
+ applyEnvFile(path.join(baseDir, DEFAULT_ENV_FILENAME), env, false);
43
+ }
44
+ function applyEnvFile(filePath, env, required) {
45
+ let contents;
46
+ try {
47
+ contents = fs.readFileSync(filePath, "utf8");
48
+ }
49
+ catch (error) {
50
+ if (required) {
51
+ throw new Error(`Could not read env file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
52
+ }
53
+ return;
54
+ }
55
+ for (const line of contents.split(/\r?\n/)) {
56
+ const trimmed = line.trim();
57
+ if (!trimmed || trimmed.startsWith("#")) {
58
+ continue;
59
+ }
60
+ const match = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_.]*)\s*=\s*(.*)$/.exec(trimmed);
61
+ if (!match) {
62
+ continue;
63
+ }
64
+ const key = match[1];
65
+ let value = match[2].trim();
66
+ const quote = value[0];
67
+ if ((quote === '"' || quote === "'") && value.endsWith(quote) && value.length >= 2) {
68
+ value = value.slice(1, -1);
69
+ }
70
+ if (env[key] === undefined) {
71
+ env[key] = value;
72
+ }
73
+ }
74
+ }
75
+ function loadSingleAccount(env, args, baseDir) {
15
76
  const argEmail = getArgValue(args, "--email");
16
77
  const argPassword = getArgValue(args, "--password");
17
78
  const argImapHost = getArgValue(args, "--imap-host");
@@ -26,39 +87,182 @@ export function loadConfig(env = process.env, options = {}) {
26
87
  if (!password) {
27
88
  throw new Error("Missing required credential: provide --password or PASSWORD");
28
89
  }
29
- const host = (argImapHost ?? env.IMAP_HOST)?.trim();
90
+ const detected = detectProvider(email);
91
+ const host = (argImapHost ?? env.IMAP_HOST)?.trim() ?? detected?.imapHost;
30
92
  if (!host) {
31
- throw new Error("Missing required IMAP setting: provide --imap-host or IMAP_HOST (for example imap.gmail.com)");
93
+ throw new Error(`Missing required IMAP setting: provide --imap-host or IMAP_HOST (for example imap.gmail.com). ` +
94
+ `No provider preset matched the domain of ${email}.`);
32
95
  }
33
- const port = parsePort(argImapPort ?? env.IMAP_PORT ?? DEFAULT_IMAP_PORT);
34
- const secure = parseBoolean(argImapSecure ?? env.IMAP_SECURE, DEFAULT_IMAP_SECURE);
96
+ const port = parsePort(argImapPort ?? env.IMAP_PORT ?? detected?.imapPort ?? DEFAULT_IMAP_PORT);
97
+ const secure = parseBoolean(argImapSecure ?? env.IMAP_SECURE, detected?.imapSecure ?? DEFAULT_IMAP_SECURE);
35
98
  const customImapUser = argImapUser ?? env.IMAP_USER;
36
99
  const authUser = customImapUser && customImapUser.trim() ? customImapUser.trim() : email;
37
- const accountHash = hashAccount(email);
38
- const baseDir = options.dataDir ?? path.join(os.homedir(), ".read-email-mcp");
39
- const accountDir = path.join(baseDir, accountHash);
40
- return {
41
- account: {
100
+ const tlsRejectUnauthorized = parseBoolean(env.IMAP_TLS_REJECT_UNAUTHORIZED, true);
101
+ return buildAccountConfig({
102
+ name: email,
103
+ email,
104
+ password,
105
+ host,
106
+ port,
107
+ secure,
108
+ authUser,
109
+ baseDir,
110
+ provider: detectProvider(email)?.id ?? null,
111
+ groups: [],
112
+ tlsRejectUnauthorized
113
+ });
114
+ }
115
+ function loadAccountsFile(filePath, env, baseDir) {
116
+ const resolved = path.resolve(filePath);
117
+ let parsed;
118
+ try {
119
+ parsed = JSON.parse(fs.readFileSync(resolved, "utf8"));
120
+ }
121
+ catch (error) {
122
+ throw new Error(`Could not read accounts file ${resolved}: ${error instanceof Error ? error.message : String(error)}`);
123
+ }
124
+ if (!Array.isArray(parsed.accounts) || parsed.accounts.length === 0) {
125
+ throw new Error(`Accounts file ${resolved} must contain a non-empty "accounts" array`);
126
+ }
127
+ return parsed.accounts.map((entry, index) => {
128
+ const label = entry.name ?? entry.email ?? `account #${index + 1}`;
129
+ const email = entry.email?.trim().toLowerCase();
130
+ if (!email) {
131
+ throw new Error(`Accounts file ${resolved}: ${label} is missing "email"`);
132
+ }
133
+ const preset = resolvePreset(entry, resolved, label);
134
+ const password = resolvePassword(entry, env, resolved, label);
135
+ const host = entry.imapHost?.trim() ?? preset?.imapHost;
136
+ if (!host) {
137
+ throw new Error(`Accounts file ${resolved}: ${label} is missing "imapHost" and no provider preset matched ` +
138
+ `(set "provider" to one of: ${PROVIDER_PRESETS.map((p) => p.id).join(", ")}, or provide "imapHost")`);
139
+ }
140
+ const port = parsePort(entry.imapPort ?? preset?.imapPort ?? DEFAULT_IMAP_PORT);
141
+ const secure = typeof entry.imapSecure === "boolean"
142
+ ? entry.imapSecure
143
+ : parseBoolean(entry.imapSecure, preset?.imapSecure ?? DEFAULT_IMAP_SECURE);
144
+ const authUser = entry.imapUser?.trim() ? entry.imapUser.trim() : email;
145
+ const tlsRejectUnauthorized = typeof entry.imapTlsRejectUnauthorized === "boolean"
146
+ ? entry.imapTlsRejectUnauthorized
147
+ : parseBoolean(entry.imapTlsRejectUnauthorized, true);
148
+ return buildAccountConfig({
149
+ name: entry.name?.trim() || email,
42
150
  email,
43
- accountHash
44
- },
45
- imap: {
151
+ password,
46
152
  host,
47
153
  port,
48
154
  secure,
155
+ authUser,
156
+ baseDir,
157
+ provider: preset?.id ?? null,
158
+ groups: normalizeGroups(entry.groups),
159
+ tlsRejectUnauthorized
160
+ });
161
+ });
162
+ }
163
+ function resolvePreset(entry, filePath, label) {
164
+ if (entry.provider) {
165
+ const preset = findProvider(entry.provider);
166
+ if (!preset) {
167
+ throw new Error(`Accounts file ${filePath}: ${label} has unknown provider "${entry.provider}". ` +
168
+ `Known providers: ${PROVIDER_PRESETS.map((p) => p.id).join(", ")}`);
169
+ }
170
+ return preset;
171
+ }
172
+ return detectProvider(entry.email ?? "");
173
+ }
174
+ function normalizeGroups(groups) {
175
+ if (!Array.isArray(groups)) {
176
+ return [];
177
+ }
178
+ return [...new Set(groups.map((group) => String(group).trim().toLowerCase()).filter(Boolean))];
179
+ }
180
+ export function resolvePassword(entry, env, filePath, label) {
181
+ if (entry.passwordEnv) {
182
+ const password = env[entry.passwordEnv];
183
+ if (!password) {
184
+ throw new Error(`Accounts file ${filePath}: ${label} references passwordEnv "${entry.passwordEnv}" but that environment variable is not set`);
185
+ }
186
+ return password;
187
+ }
188
+ if (entry.passwordCommand) {
189
+ return runPasswordCommand(entry.passwordCommand, filePath, label);
190
+ }
191
+ if (entry.password) {
192
+ return entry.password;
193
+ }
194
+ throw new Error(`Accounts file ${filePath}: ${label} needs one of "passwordEnv" (env var name), ` +
195
+ `"passwordCommand" (shell command that prints the password), or "password" (inline, discouraged)`);
196
+ }
197
+ function runPasswordCommand(command, filePath, label) {
198
+ let output;
199
+ try {
200
+ output = execSync(command, {
201
+ encoding: "utf8",
202
+ timeout: 15_000,
203
+ windowsHide: true,
204
+ stdio: ["ignore", "pipe", "pipe"],
205
+ maxBuffer: 64 * 1024
206
+ });
207
+ }
208
+ catch (error) {
209
+ throw new Error(`Accounts file ${filePath}: ${label} passwordCommand failed: ` +
210
+ `${error instanceof Error ? error.message : String(error)}`);
211
+ }
212
+ const password = output
213
+ .split(/\r?\n/)
214
+ .map((line) => line.trim())
215
+ .find((line) => line.length > 0);
216
+ if (!password) {
217
+ throw new Error(`Accounts file ${filePath}: ${label} passwordCommand produced no output`);
218
+ }
219
+ return password;
220
+ }
221
+ function buildAccountConfig(input) {
222
+ const accountHash = hashAccount(input.email);
223
+ const accountDir = path.join(input.baseDir, accountHash);
224
+ return {
225
+ account: {
226
+ name: input.name,
227
+ email: input.email,
228
+ accountHash,
229
+ provider: input.provider,
230
+ groups: input.groups
231
+ },
232
+ imap: {
233
+ host: input.host,
234
+ port: input.port,
235
+ secure: input.secure,
236
+ ...(input.tlsRejectUnauthorized ? {} : { tls: { rejectUnauthorized: false } }),
49
237
  auth: {
50
- user: authUser,
51
- pass: password
238
+ user: input.authUser,
239
+ pass: input.password
52
240
  }
53
241
  },
54
242
  storage: {
55
- baseDir,
243
+ baseDir: input.baseDir,
56
244
  accountDir,
57
245
  databasePath: path.join(accountDir, "emails.sqlite"),
58
246
  rawDir: path.join(accountDir, "raw")
59
247
  }
60
248
  };
61
249
  }
250
+ function assertUniqueAccounts(accounts) {
251
+ const names = new Set();
252
+ const emails = new Set();
253
+ for (const account of accounts) {
254
+ const name = account.account.name.toLowerCase();
255
+ const email = account.account.email;
256
+ if (names.has(name)) {
257
+ throw new Error(`Duplicate account name "${account.account.name}" — account names must be unique`);
258
+ }
259
+ if (emails.has(email)) {
260
+ throw new Error(`Duplicate account email "${email}" — each account needs a distinct email address`);
261
+ }
262
+ names.add(name);
263
+ emails.add(email);
264
+ }
265
+ }
62
266
  function parsePort(value) {
63
267
  if (value === undefined || value === "") {
64
268
  return DEFAULT_IMAP_PORT;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { type ProviderPreset } from "./providers.js";
2
+ export interface DiscoveredImap {
3
+ host: string;
4
+ port: number;
5
+ secure: boolean;
6
+ user: string | null;
7
+ providerId: string | null;
8
+ source: "autoconfig" | "dns-srv" | "mx" | "guess";
9
+ }
10
+ export interface DiscoveryDeps {
11
+ resolveSrv: (name: string) => Promise<Array<{
12
+ name: string;
13
+ port: number;
14
+ priority: number;
15
+ weight: number;
16
+ }>>;
17
+ resolveMx: (domain: string) => Promise<Array<{
18
+ exchange: string;
19
+ priority: number;
20
+ }>>;
21
+ fetchText: (url: string) => Promise<string>;
22
+ probeTcp: (host: string, port: number) => Promise<boolean>;
23
+ lookupProvider: (id: string) => ProviderPreset | null;
24
+ }
25
+ /**
26
+ * Parse a Mozilla autoconfig XML document for the first IMAP incomingServer
27
+ * block. Returns null when no usable IMAP section is present.
28
+ */
29
+ export declare function parseAutoconfigXml(xml: string, email: string): {
30
+ host: string;
31
+ port: number;
32
+ secure: boolean;
33
+ user: string | null;
34
+ } | null;
35
+ /**
36
+ * Infer a known provider from a domain's MX records. Returns the preset when
37
+ * the mail is actually hosted by Gmail, Microsoft 365, etc.
38
+ */
39
+ export declare function inferProviderFromMx(mxHosts: string[], lookupProvider?: (id: string) => ProviderPreset | null): ProviderPreset | null;
40
+ /**
41
+ * Best-effort IMAP settings discovery for an email address whose domain has no
42
+ * preset. Order: Mozilla autoconfig, DNS SRV (RFC 6186), MX-based provider
43
+ * inference, then probing imap./mail. hostnames. Returns null on total failure.
44
+ * Never throws — every step fails soft.
45
+ */
46
+ export declare function discoverImapSettings(email: string, deps?: Partial<DiscoveryDeps>): Promise<DiscoveredImap | null>;
47
+ /**
48
+ * True when an IMAP/TLS failure looks like a self-signed or otherwise
49
+ * unverifiable certificate — the case where imapTlsRejectUnauthorized: false
50
+ * is the fix.
51
+ */
52
+ export declare function isSelfSignedCertError(message: string): boolean;
@@ -0,0 +1,207 @@
1
+ import dns from "node:dns/promises";
2
+ import net from "node:net";
3
+ import { findProvider } from "./providers.js";
4
+ const DISCOVERY_TIMEOUT_MS = 3_000;
5
+ const PROBE_TIMEOUT_MS = 2_500;
6
+ // MX hostname suffixes that reveal the real provider behind a custom domain
7
+ // (e.g. a company domain hosted on Google Workspace or Microsoft 365).
8
+ const MX_PROVIDER_SUFFIXES = [
9
+ { suffix: ".google.com", provider: "gmail" },
10
+ { suffix: ".googlemail.com", provider: "gmail" },
11
+ { suffix: ".outlook.com", provider: "outlook" },
12
+ { suffix: ".protection.outlook.com", provider: "outlook" },
13
+ { suffix: ".yahoodns.net", provider: "yahoo" },
14
+ { suffix: ".aol.com", provider: "aol" },
15
+ { suffix: ".mail.icloud.com", provider: "icloud" },
16
+ { suffix: ".icloud.com", provider: "icloud" },
17
+ { suffix: ".messagingengine.com", provider: "fastmail" },
18
+ { suffix: ".zoho.com", provider: "zoho" },
19
+ { suffix: ".zoho.eu", provider: "zoho" },
20
+ { suffix: ".gmx.net", provider: "gmx" },
21
+ { suffix: ".gmx.com", provider: "gmx" },
22
+ { suffix: ".protonmail.ch", provider: "proton" },
23
+ { suffix: ".protonmail.com", provider: "proton" },
24
+ { suffix: ".yandex.net", provider: "yandex" },
25
+ { suffix: ".yandex.ru", provider: "yandex" },
26
+ { suffix: ".mail.com", provider: "mailcom" }
27
+ ];
28
+ function defaultDeps() {
29
+ return {
30
+ resolveSrv: (name) => dns.resolveSrv(name),
31
+ resolveMx: (domain) => dns.resolveMx(domain),
32
+ fetchText: async (url) => {
33
+ const response = await fetch(url, {
34
+ signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS),
35
+ redirect: "follow"
36
+ });
37
+ if (!response.ok) {
38
+ throw new Error(`HTTP ${response.status}`);
39
+ }
40
+ return response.text();
41
+ },
42
+ probeTcp: (host, port) => new Promise((resolve) => {
43
+ const socket = net.connect({ host, port, timeout: PROBE_TIMEOUT_MS });
44
+ socket.once("connect", () => {
45
+ socket.destroy();
46
+ resolve(true);
47
+ });
48
+ socket.once("timeout", () => {
49
+ socket.destroy();
50
+ resolve(false);
51
+ });
52
+ socket.once("error", () => resolve(false));
53
+ }),
54
+ lookupProvider: findProvider
55
+ };
56
+ }
57
+ function withTimeout(promise, ms) {
58
+ return Promise.race([
59
+ promise,
60
+ new Promise((_resolve, reject) => setTimeout(() => reject(new Error("timed out")), ms))
61
+ ]);
62
+ }
63
+ /**
64
+ * Parse a Mozilla autoconfig XML document for the first IMAP incomingServer
65
+ * block. Returns null when no usable IMAP section is present.
66
+ */
67
+ export function parseAutoconfigXml(xml, email) {
68
+ const serverBlock = /<incomingServer\s+type="imap"[^>]*>([\s\S]*?)<\/incomingServer>/i.exec(xml) ??
69
+ // Some files omit the type attribute ordering or use single quotes.
70
+ /<incomingServer[^>]*type=["']imap["'][^>]*>([\s\S]*?)<\/incomingServer>/i.exec(xml);
71
+ if (!serverBlock) {
72
+ return null;
73
+ }
74
+ const block = serverBlock[1];
75
+ const text = (tag) => new RegExp(`<${tag}>([^<]+)</${tag}>`, "i").exec(block)?.[1]?.trim() ?? null;
76
+ const host = text("hostname");
77
+ if (!host) {
78
+ return null;
79
+ }
80
+ const port = Number(text("port") ?? "993");
81
+ const socketType = (text("socketType") ?? "SSL").toUpperCase();
82
+ const secure = socketType !== "STARTTLS" && socketType !== "PLAIN";
83
+ const rawUser = text("username");
84
+ const localpart = email.split("@")[0] ?? email;
85
+ const user = rawUser === null || rawUser === "%EMAILADDRESS%"
86
+ ? null // null means "use the full email address" (the default)
87
+ : rawUser === "%EMAILLOCALPART%"
88
+ ? localpart
89
+ : rawUser.replace(/%EMAILADDRESS%/g, email).replace(/%EMAILLOCALPART%/g, localpart);
90
+ return { host, port: Number.isInteger(port) && port > 0 ? port : 993, secure, user };
91
+ }
92
+ /**
93
+ * Infer a known provider from a domain's MX records. Returns the preset when
94
+ * the mail is actually hosted by Gmail, Microsoft 365, etc.
95
+ */
96
+ export function inferProviderFromMx(mxHosts, lookupProvider = findProvider) {
97
+ for (const host of mxHosts) {
98
+ const normalized = host.trim().toLowerCase().replace(/\.$/, "");
99
+ for (const { suffix, provider } of MX_PROVIDER_SUFFIXES) {
100
+ if (normalized.endsWith(suffix) || normalized === suffix.slice(1)) {
101
+ return lookupProvider(provider);
102
+ }
103
+ }
104
+ }
105
+ return null;
106
+ }
107
+ /**
108
+ * Best-effort IMAP settings discovery for an email address whose domain has no
109
+ * preset. Order: Mozilla autoconfig, DNS SRV (RFC 6186), MX-based provider
110
+ * inference, then probing imap./mail. hostnames. Returns null on total failure.
111
+ * Never throws — every step fails soft.
112
+ */
113
+ export async function discoverImapSettings(email, deps = {}) {
114
+ const domain = email.split("@")[1]?.trim().toLowerCase();
115
+ if (!domain) {
116
+ return null;
117
+ }
118
+ const { resolveSrv, resolveMx, fetchText, probeTcp, lookupProvider } = { ...defaultDeps(), ...deps };
119
+ // 1. Mozilla autoconfig (what Thunderbird uses; cPanel/Dovecot publish it).
120
+ const autoconfigUrls = [
121
+ `https://autoconfig.${domain}/mail/config-v1.3.xml?emailaddress=${encodeURIComponent(email)}`,
122
+ `https://${domain}/.well-known/autoconfig/mail/config-v1.3.xml`,
123
+ `https://autoconfig.thunderbird.net/v1.3/${domain}`
124
+ ];
125
+ for (const url of autoconfigUrls) {
126
+ try {
127
+ const xml = await fetchText(url);
128
+ const parsed = parseAutoconfigXml(xml, email);
129
+ if (parsed) {
130
+ return { ...parsed, providerId: null, source: "autoconfig" };
131
+ }
132
+ }
133
+ catch {
134
+ // try the next URL
135
+ }
136
+ }
137
+ // 2. DNS SRV (RFC 6186): _imaps._tcp for TLS, _imap._tcp for STARTTLS.
138
+ const srvAttempts = [
139
+ { name: `_imaps._tcp.${domain}`, secure: true },
140
+ { name: `_imap._tcp.${domain}`, secure: false }
141
+ ];
142
+ for (const attempt of srvAttempts) {
143
+ try {
144
+ const records = await withTimeout(resolveSrv(attempt.name), DISCOVERY_TIMEOUT_MS);
145
+ const best = records
146
+ .slice()
147
+ .sort((a, b) => a.priority - b.priority || b.weight - a.weight)[0];
148
+ if (best?.name && best.name !== ".") {
149
+ return {
150
+ host: best.name.replace(/\.$/, ""),
151
+ port: best.port,
152
+ secure: attempt.secure,
153
+ user: null,
154
+ providerId: null,
155
+ source: "dns-srv"
156
+ };
157
+ }
158
+ }
159
+ catch {
160
+ // no SRV record — continue
161
+ }
162
+ }
163
+ // 3. MX inference: a custom domain hosted on Google Workspace/M365 still
164
+ // answers IMAP via the provider's servers.
165
+ try {
166
+ const mxRecords = await withTimeout(resolveMx(domain), DISCOVERY_TIMEOUT_MS);
167
+ const preset = inferProviderFromMx(mxRecords.map((record) => record.exchange), lookupProvider);
168
+ if (preset) {
169
+ return {
170
+ host: preset.imapHost,
171
+ port: preset.imapPort,
172
+ secure: preset.imapSecure,
173
+ user: null,
174
+ providerId: preset.id,
175
+ source: "mx"
176
+ };
177
+ }
178
+ }
179
+ catch {
180
+ // no MX — continue
181
+ }
182
+ // 4. Guess-and-probe: imap./mail. subdomains on the standard ports.
183
+ const candidates = [
184
+ { host: `imap.${domain}`, port: 993, secure: true },
185
+ { host: `mail.${domain}`, port: 993, secure: true },
186
+ { host: `imap.${domain}`, port: 143, secure: false },
187
+ { host: `mail.${domain}`, port: 143, secure: false }
188
+ ];
189
+ const probes = await Promise.all(candidates.map(async (candidate) => ({
190
+ candidate,
191
+ open: await probeTcp(candidate.host, candidate.port)
192
+ })));
193
+ const hit = probes.find((probe) => probe.open)?.candidate;
194
+ if (hit) {
195
+ return { host: hit.host, port: hit.port, secure: hit.secure, user: null, providerId: null, source: "guess" };
196
+ }
197
+ return null;
198
+ }
199
+ /**
200
+ * True when an IMAP/TLS failure looks like a self-signed or otherwise
201
+ * unverifiable certificate — the case where imapTlsRejectUnauthorized: false
202
+ * is the fix.
203
+ */
204
+ export function isSelfSignedCertError(message) {
205
+ return /self[- ]signed|DEPTH_ZERO_SELF_SIGNED|SELF_SIGNED_CERT_IN_CHAIN|UNABLE_TO_VERIFY_LEAF|unable to verify|certificate verify|CERT_HAS_EXPIRED|ERR_TLS_CERT/i.test(message);
206
+ }
207
+ //# sourceMappingURL=imap-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imap-discovery.js","sourceRoot":"","sources":["../src/imap-discovery.ts"],"names":[],"mappings":"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"}
package/dist/imap.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { AppConfig } from "./config.js";
1
+ import type { AccountConfig } from "./config.js";
2
2
  import type { EmailStore } from "./store.js";
3
- import type { SyncResultRecord } from "./types.js";
3
+ import type { ImapSearchCriteria, SyncResultRecord } from "./types.js";
4
4
  export interface ImapMailboxInfo {
5
5
  path: string;
6
6
  delimiter?: string;
@@ -8,7 +8,7 @@ export interface ImapMailboxInfo {
8
8
  }
9
9
  export interface ImapFetchMessage {
10
10
  uid: number;
11
- source: Buffer | Uint8Array | string;
11
+ source?: Buffer | Uint8Array | string;
12
12
  internalDate?: Date | string;
13
13
  flags?: Iterable<string>;
14
14
  size?: number;
@@ -33,28 +33,64 @@ export interface ImapClientLike {
33
33
  release(): void;
34
34
  }>;
35
35
  fetch(range: string, query?: unknown, options?: unknown): AsyncIterable<ImapFetchMessage>;
36
+ search?(query: Record<string, unknown>, options?: {
37
+ uid?: boolean;
38
+ }): Promise<number[] | false | Iterable<number>> | AsyncIterable<number> | Iterable<number>;
36
39
  }
37
- export type ImapClientFactory = (config: AppConfig["imap"]) => ImapClientLike;
40
+ export type ImapClientFactory = (config: AccountConfig["imap"]) => ImapClientLike;
38
41
  export interface EmailSyncServiceOptions {
39
- imap: AppConfig["imap"];
42
+ imap: AccountConfig["imap"];
40
43
  rawDir: string;
41
44
  store: EmailStore;
42
45
  clientFactory?: ImapClientFactory;
43
46
  }
44
47
  export interface SyncOptions {
45
48
  mailbox?: string;
49
+ mailboxes?: string[];
50
+ excludeMailboxes?: string[];
51
+ excludeFlags?: string[];
46
52
  limit?: number;
47
53
  since?: string;
54
+ uids?: string;
55
+ search?: ImapSearchCriteria;
56
+ refreshFlags?: boolean;
57
+ pruneExpunged?: boolean;
58
+ resetMailbox?: boolean;
59
+ }
60
+ export interface MailboxSyncError {
61
+ mailbox: string;
62
+ message: string;
63
+ }
64
+ export interface ConnectivityResult {
65
+ ok: boolean;
66
+ host: string;
67
+ mailboxCount: number;
68
+ mailboxes: string[];
69
+ error?: string;
48
70
  }
49
71
  export interface SyncResult extends SyncResultRecord {
72
+ mode: "incremental" | "targeted";
50
73
  mailboxes: string[];
74
+ refreshedFlags: number;
75
+ prunedMessages: number;
76
+ errors: MailboxSyncError[];
51
77
  }
52
78
  export declare class EmailSyncService {
53
79
  private readonly options;
54
80
  private readonly clientFactory;
55
81
  constructor(options: EmailSyncServiceOptions);
82
+ check(): Promise<ConnectivityResult>;
56
83
  sync(syncOptions?: SyncOptions): Promise<SyncResult>;
84
+ private buildResult;
57
85
  private selectMailboxes;
58
86
  private syncMailbox;
87
+ private syncIncremental;
88
+ private syncTargeted;
89
+ private resolveTargetUids;
90
+ private runServerSideSearch;
91
+ private ingestFetched;
92
+ private refreshMailboxFlags;
59
93
  private writeRawEmail;
94
+ private removeRawFiles;
60
95
  }
96
+ export declare function checkConnectivity(imap: AccountConfig["imap"], clientFactory?: ImapClientFactory): Promise<ConnectivityResult>;