better-email-mcp 0.1.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.
@@ -0,0 +1,374 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JmapBackend = exports.JmapError = void 0;
4
+ class JmapError extends Error {
5
+ type;
6
+ description;
7
+ constructor(type, description) {
8
+ super(`JMAP error [${type}]: ${description}`);
9
+ this.type = type;
10
+ this.description = description;
11
+ this.name = "JmapError";
12
+ }
13
+ }
14
+ exports.JmapError = JmapError;
15
+ const DEFAULT_SESSION_URL = "https://api.fastmail.com/.well-known/jmap";
16
+ const USING = [
17
+ "urn:ietf:params:jmap:core",
18
+ "urn:ietf:params:jmap:mail",
19
+ "urn:ietf:params:jmap:submission",
20
+ ];
21
+ const LIST_PROPERTIES = [
22
+ "id",
23
+ "subject",
24
+ "from",
25
+ "to",
26
+ "cc",
27
+ "receivedAt",
28
+ "preview",
29
+ "keywords",
30
+ "mailboxIds",
31
+ "hasAttachment",
32
+ ];
33
+ const FULL_PROPERTIES = [
34
+ ...LIST_PROPERTIES,
35
+ "textBody",
36
+ "htmlBody",
37
+ "bodyValues",
38
+ ];
39
+ class JmapBackend {
40
+ config;
41
+ session = null;
42
+ identity = null;
43
+ mailboxCache = new Map(); // id → path
44
+ mailboxNameToId = new Map(); // path → id
45
+ constructor(config) {
46
+ this.config = config;
47
+ }
48
+ async connect() {
49
+ // 1. Discover session
50
+ const sessionUrl = this.config.sessionUrl ?? DEFAULT_SESSION_URL;
51
+ const sessionRes = await fetch(sessionUrl, {
52
+ headers: { Authorization: `Bearer ${this.config.token}` },
53
+ });
54
+ if (!sessionRes.ok) {
55
+ throw new Error(`JMAP session discovery failed: ${sessionRes.status} ${sessionRes.statusText}`);
56
+ }
57
+ const sessionData = await sessionRes.json();
58
+ this.session = {
59
+ apiUrl: sessionData.apiUrl,
60
+ accountId: sessionData.primaryAccounts["urn:ietf:params:jmap:mail"],
61
+ };
62
+ // 2. Fetch mailboxes and identity in one request
63
+ const responses = await this.jmapRequest([
64
+ [
65
+ "Mailbox/get",
66
+ {
67
+ accountId: this.session.accountId,
68
+ properties: ["id", "name", "parentId", "role"],
69
+ },
70
+ "0",
71
+ ],
72
+ [
73
+ "Identity/get",
74
+ {
75
+ accountId: this.session.accountId,
76
+ },
77
+ "1",
78
+ ],
79
+ ]);
80
+ // Process mailboxes
81
+ const mailboxResponse = this.findResponse(responses, "Mailbox/get");
82
+ const mailboxes = mailboxResponse.list;
83
+ const mailboxesById = new Map();
84
+ for (const mb of mailboxes) {
85
+ mailboxesById.set(mb.id, mb);
86
+ }
87
+ this.mailboxCache.clear();
88
+ this.mailboxNameToId.clear();
89
+ for (const mb of mailboxes) {
90
+ const path = this.buildMailboxPath(mb, mailboxesById);
91
+ this.mailboxCache.set(mb.id, path);
92
+ this.mailboxNameToId.set(path, mb.id);
93
+ }
94
+ // Process identity
95
+ const identityResponse = this.findResponse(responses, "Identity/get");
96
+ const identities = identityResponse.list;
97
+ if (identities.length > 0) {
98
+ this.identity = {
99
+ id: identities[0].id,
100
+ email: identities[0].email,
101
+ name: identities[0].name ?? "",
102
+ };
103
+ }
104
+ }
105
+ async disconnect() {
106
+ this.session = null;
107
+ this.identity = null;
108
+ this.mailboxCache.clear();
109
+ this.mailboxNameToId.clear();
110
+ }
111
+ async listFolders() {
112
+ return Array.from(this.mailboxNameToId.keys()).sort();
113
+ }
114
+ async listMessages(options) {
115
+ this.ensureConnected();
116
+ const filter = {};
117
+ if (options?.folder) {
118
+ const mailboxId = this.mailboxNameToId.get(options.folder);
119
+ if (!mailboxId) {
120
+ throw new Error(`Unknown folder: ${options.folder}`);
121
+ }
122
+ filter.inMailbox = mailboxId;
123
+ }
124
+ const responses = await this.jmapRequest([
125
+ [
126
+ "Email/query",
127
+ {
128
+ accountId: this.session.accountId,
129
+ filter,
130
+ sort: [{ property: "receivedAt", isAscending: false }],
131
+ position: options?.offset ?? 0,
132
+ limit: options?.limit ?? 25,
133
+ collapseThreads: true,
134
+ },
135
+ "0",
136
+ ],
137
+ [
138
+ "Email/get",
139
+ {
140
+ accountId: this.session.accountId,
141
+ "#ids": {
142
+ name: "Email/query",
143
+ path: "/ids",
144
+ resultOf: "0",
145
+ },
146
+ properties: LIST_PROPERTIES,
147
+ },
148
+ "1",
149
+ ],
150
+ ]);
151
+ const emailResponse = this.findResponse(responses, "Email/get");
152
+ return emailResponse.list.map((raw) => this.mapJmapEmail(raw));
153
+ }
154
+ async getMessage(id) {
155
+ this.ensureConnected();
156
+ const responses = await this.jmapRequest([
157
+ [
158
+ "Email/get",
159
+ {
160
+ accountId: this.session.accountId,
161
+ ids: [id],
162
+ properties: FULL_PROPERTIES,
163
+ fetchAllBodyValues: true,
164
+ },
165
+ "0",
166
+ ],
167
+ ]);
168
+ const emailResponse = this.findResponse(responses, "Email/get");
169
+ if (emailResponse.notFound?.includes(id)) {
170
+ return null;
171
+ }
172
+ if (emailResponse.list.length === 0) {
173
+ return null;
174
+ }
175
+ const raw = emailResponse.list[0];
176
+ const message = this.mapJmapEmail(raw);
177
+ // Assemble body from textBody parts
178
+ const textParts = raw.textBody ?? [];
179
+ const bodyText = textParts
180
+ .map((part) => raw.bodyValues?.[part.partId]?.value ?? "")
181
+ .join("\n");
182
+ if (bodyText) {
183
+ message.body = bodyText;
184
+ }
185
+ return message;
186
+ }
187
+ async searchMessages(options) {
188
+ this.ensureConnected();
189
+ const filter = { text: options.query };
190
+ if (options.folder) {
191
+ const mailboxId = this.mailboxNameToId.get(options.folder);
192
+ if (!mailboxId) {
193
+ throw new Error(`Unknown folder: ${options.folder}`);
194
+ }
195
+ filter.inMailbox = mailboxId;
196
+ }
197
+ const responses = await this.jmapRequest([
198
+ [
199
+ "Email/query",
200
+ {
201
+ accountId: this.session.accountId,
202
+ filter,
203
+ sort: [{ property: "receivedAt", isAscending: false }],
204
+ limit: options.limit ?? 25,
205
+ },
206
+ "0",
207
+ ],
208
+ [
209
+ "Email/get",
210
+ {
211
+ accountId: this.session.accountId,
212
+ "#ids": {
213
+ name: "Email/query",
214
+ path: "/ids",
215
+ resultOf: "0",
216
+ },
217
+ properties: LIST_PROPERTIES,
218
+ },
219
+ "1",
220
+ ],
221
+ ]);
222
+ const emailResponse = this.findResponse(responses, "Email/get");
223
+ return emailResponse.list.map((raw) => this.mapJmapEmail(raw));
224
+ }
225
+ async sendMessage(options) {
226
+ this.ensureConnected();
227
+ if (!this.identity) {
228
+ throw new Error("No identity available for sending");
229
+ }
230
+ // Find drafts mailbox
231
+ let draftsId;
232
+ for (const [id, path] of this.mailboxCache) {
233
+ if (path.toLowerCase() === "drafts") {
234
+ draftsId = id;
235
+ break;
236
+ }
237
+ }
238
+ if (!draftsId) {
239
+ throw new Error("Drafts mailbox not found");
240
+ }
241
+ const emailCreate = {
242
+ mailboxIds: { [draftsId]: true },
243
+ from: [{ name: this.identity.name, email: this.identity.email }],
244
+ to: options.to.map((email) => ({ email })),
245
+ ...(options.cc?.length
246
+ ? { cc: options.cc.map((email) => ({ email })) }
247
+ : {}),
248
+ ...(options.bcc?.length
249
+ ? { bcc: options.bcc.map((email) => ({ email })) }
250
+ : {}),
251
+ subject: options.subject,
252
+ textBody: [{ partId: "textBody", type: "text/plain" }],
253
+ bodyValues: {
254
+ textBody: { value: options.textBody },
255
+ ...(options.htmlBody
256
+ ? { htmlBody: { value: options.htmlBody } }
257
+ : {}),
258
+ },
259
+ ...(options.htmlBody
260
+ ? { htmlBody: [{ partId: "htmlBody", type: "text/html" }] }
261
+ : {}),
262
+ keywords: { $draft: true },
263
+ };
264
+ if (options.inReplyTo) {
265
+ emailCreate.inReplyTo = [options.inReplyTo];
266
+ }
267
+ const responses = await this.jmapRequest([
268
+ [
269
+ "Email/set",
270
+ {
271
+ accountId: this.session.accountId,
272
+ create: { draft: emailCreate },
273
+ },
274
+ "0",
275
+ ],
276
+ [
277
+ "EmailSubmission/set",
278
+ {
279
+ accountId: this.session.accountId,
280
+ create: {
281
+ submission: {
282
+ emailId: "#draft",
283
+ identityId: this.identity.id,
284
+ },
285
+ },
286
+ },
287
+ "1",
288
+ ],
289
+ ]);
290
+ const emailSetResponse = this.findResponse(responses, "Email/set");
291
+ const createdId = emailSetResponse.created?.draft?.id;
292
+ if (!createdId) {
293
+ const err = emailSetResponse.notCreated?.draft;
294
+ throw new JmapError(err?.type ?? "unknown", err?.description ?? "Failed to create email");
295
+ }
296
+ return { id: createdId };
297
+ }
298
+ // --- Private helpers ---
299
+ ensureConnected() {
300
+ if (!this.session) {
301
+ throw new Error("Not connected. Call connect() first.");
302
+ }
303
+ return this.session;
304
+ }
305
+ async jmapRequest(methodCalls) {
306
+ const session = this.ensureConnected();
307
+ const res = await fetch(session.apiUrl, {
308
+ method: "POST",
309
+ headers: {
310
+ "Content-Type": "application/json",
311
+ Authorization: `Bearer ${this.config.token}`,
312
+ },
313
+ body: JSON.stringify({
314
+ using: USING,
315
+ methodCalls,
316
+ }),
317
+ });
318
+ if (!res.ok) {
319
+ throw new Error(`JMAP request failed: ${res.status} ${res.statusText}`);
320
+ }
321
+ const data = await res.json();
322
+ const methodResponses = data.methodResponses;
323
+ // Check for method-level errors
324
+ for (const response of methodResponses) {
325
+ if (response[0] === "error") {
326
+ throw new JmapError(response[1].type ?? "unknown", response[1].description ?? "Unknown JMAP error");
327
+ }
328
+ }
329
+ return methodResponses;
330
+ }
331
+ findResponse(responses, methodName) {
332
+ for (const response of responses) {
333
+ if (response[0] === methodName) {
334
+ return response[1];
335
+ }
336
+ }
337
+ throw new Error(`Expected ${methodName} response not found`);
338
+ }
339
+ buildMailboxPath(mailbox, mailboxesById) {
340
+ const parts = [mailbox.name];
341
+ let current = mailbox;
342
+ while (current.parentId) {
343
+ const parent = mailboxesById.get(current.parentId);
344
+ if (!parent)
345
+ break;
346
+ parts.unshift(parent.name);
347
+ current = parent;
348
+ }
349
+ return parts.join("/");
350
+ }
351
+ mapJmapEmail(raw) {
352
+ const mailboxId = Object.keys(raw.mailboxIds ?? {})[0];
353
+ const folder = mailboxId
354
+ ? this.mailboxCache.get(mailboxId) ?? mailboxId
355
+ : "";
356
+ const message = {
357
+ id: raw.id,
358
+ subject: raw.subject ?? "",
359
+ from: raw.from?.[0]?.email ?? raw.from?.[0]?.name ?? "",
360
+ to: (raw.to ?? []).map((a) => a.email),
361
+ date: raw.receivedAt ?? "",
362
+ snippet: raw.preview ?? "",
363
+ isRead: raw.keywords?.$seen === true,
364
+ folder,
365
+ };
366
+ const cc = (raw.cc ?? []).map((a) => a.email);
367
+ if (cc.length > 0) {
368
+ message.cc = cc;
369
+ }
370
+ return message;
371
+ }
372
+ }
373
+ exports.JmapBackend = JmapBackend;
374
+ //# sourceMappingURL=jmap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jmap.js","sourceRoot":"","sources":["../../src/backends/jmap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Minimal IMAP client using Node's built-in net/tls modules.
3
+ * Supports only the commands needed by the IMAP backend:
4
+ * LOGIN, LIST, SELECT, UID SEARCH, UID FETCH, LOGOUT.
5
+ */
6
+ import { ImapResponse } from "./parser.js";
7
+ export interface ImapClientConfig {
8
+ host: string;
9
+ port: number;
10
+ tls: boolean;
11
+ }
12
+ export declare class ImapError extends Error {
13
+ readonly code: string;
14
+ constructor(code: string, message: string);
15
+ }
16
+ export declare class ImapClient {
17
+ private socket;
18
+ private tagCounter;
19
+ private buffer;
20
+ private literalRemaining;
21
+ private literalBuffer;
22
+ private currentLines;
23
+ private pending;
24
+ private greetingResolve;
25
+ connect(config: ImapClientConfig): Promise<void>;
26
+ /**
27
+ * Send an IMAP command and collect all responses until the tagged completion.
28
+ * Returns array of untagged responses. Throws on NO/BAD.
29
+ */
30
+ command(cmd: string): Promise<ImapResponse[]>;
31
+ disconnect(): Promise<void>;
32
+ private onData;
33
+ private processBuffer;
34
+ private handleLine;
35
+ }
36
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/imap/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAqB,YAAY,EAAE,MAAM,aAAa,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;CACd;AAED,qBAAa,SAAU,SAAQ,KAAK;aAEhB,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;CAKlB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAA2C;IACzD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,YAAY,CAAgB;IAGpC,OAAO,CAAC,OAAO,CAKC;IAGhB,OAAO,CAAC,eAAe,CAA+C;IAEhE,OAAO,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA8CtD;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAa7C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBjC,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,aAAa;IAsDrB,OAAO,CAAC,UAAU;CA+BnB"}
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+ /**
3
+ * Minimal IMAP client using Node's built-in net/tls modules.
4
+ * Supports only the commands needed by the IMAP backend:
5
+ * LOGIN, LIST, SELECT, UID SEARCH, UID FETCH, LOGOUT.
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.ImapClient = exports.ImapError = void 0;
42
+ const net = __importStar(require("net"));
43
+ const tls = __importStar(require("tls"));
44
+ const parser_js_1 = require("./parser.js");
45
+ class ImapError extends Error {
46
+ code;
47
+ constructor(code, message) {
48
+ super(`IMAP error [${code}]: ${message}`);
49
+ this.code = code;
50
+ this.name = "ImapError";
51
+ }
52
+ }
53
+ exports.ImapError = ImapError;
54
+ class ImapClient {
55
+ socket = null;
56
+ tagCounter = 0;
57
+ buffer = "";
58
+ literalRemaining = 0;
59
+ literalBuffer = "";
60
+ currentLines = [];
61
+ // Pending command awaiting tagged response
62
+ pending = null;
63
+ // Queue for incoming lines when no command is pending
64
+ greetingResolve = null;
65
+ async connect(config) {
66
+ return new Promise((resolve, reject) => {
67
+ const onGreeting = (resp) => {
68
+ if (resp.type === "OK" || resp.type === "PREAUTH") {
69
+ resolve();
70
+ }
71
+ else {
72
+ reject(new ImapError("greeting", `Server rejected connection: ${resp.text}`));
73
+ }
74
+ };
75
+ this.greetingResolve = onGreeting;
76
+ const onConnect = () => {
77
+ // Socket connected, waiting for greeting
78
+ };
79
+ const onError = (err) => {
80
+ this.greetingResolve = null;
81
+ reject(new ImapError("connect", err.message));
82
+ };
83
+ if (config.tls) {
84
+ this.socket = tls.connect({ host: config.host, port: config.port }, onConnect);
85
+ }
86
+ else {
87
+ this.socket = net.connect({ host: config.host, port: config.port }, onConnect);
88
+ }
89
+ this.socket.setEncoding("utf-8");
90
+ this.socket.on("data", (data) => this.onData(data));
91
+ this.socket.on("error", onError);
92
+ this.socket.on("close", () => {
93
+ if (this.pending) {
94
+ this.pending.reject(new ImapError("closed", "Connection closed unexpectedly"));
95
+ this.pending = null;
96
+ }
97
+ this.socket = null;
98
+ });
99
+ });
100
+ }
101
+ /**
102
+ * Send an IMAP command and collect all responses until the tagged completion.
103
+ * Returns array of untagged responses. Throws on NO/BAD.
104
+ */
105
+ async command(cmd) {
106
+ if (!this.socket) {
107
+ throw new ImapError("disconnected", "Not connected");
108
+ }
109
+ const tag = `A${++this.tagCounter}`;
110
+ return new Promise((resolve, reject) => {
111
+ this.pending = { tag, responses: [], resolve, reject };
112
+ this.socket.write(`${tag} ${cmd}\r\n`);
113
+ });
114
+ }
115
+ async disconnect() {
116
+ if (!this.socket)
117
+ return;
118
+ try {
119
+ await this.command("LOGOUT");
120
+ }
121
+ catch {
122
+ // Ignore errors during logout
123
+ }
124
+ if (this.socket) {
125
+ this.socket.destroy();
126
+ this.socket = null;
127
+ }
128
+ }
129
+ // --- Private ---
130
+ onData(data) {
131
+ this.buffer += data;
132
+ this.processBuffer();
133
+ }
134
+ processBuffer() {
135
+ while (this.buffer.length > 0) {
136
+ // If we're reading a literal, consume bytes
137
+ if (this.literalRemaining > 0) {
138
+ if (this.buffer.length < this.literalRemaining) {
139
+ // Not enough data yet
140
+ this.literalBuffer += this.buffer;
141
+ this.literalRemaining -= this.buffer.length;
142
+ this.buffer = "";
143
+ return;
144
+ }
145
+ this.literalBuffer += this.buffer.substring(0, this.literalRemaining);
146
+ this.buffer = this.buffer.substring(this.literalRemaining);
147
+ this.literalRemaining = 0;
148
+ // Append literal content to the current line being built
149
+ this.currentLines[this.currentLines.length - 1] += this.literalBuffer;
150
+ this.literalBuffer = "";
151
+ // Continue processing — the line continues after the literal
152
+ continue;
153
+ }
154
+ // Look for end of line
155
+ const crlfIdx = this.buffer.indexOf("\r\n");
156
+ if (crlfIdx === -1)
157
+ return; // Need more data
158
+ const line = this.buffer.substring(0, crlfIdx);
159
+ this.buffer = this.buffer.substring(crlfIdx + 2);
160
+ // Check if line ends with a literal marker {N}
161
+ const literalMatch = line.match(/\{(\d+)\}$/);
162
+ if (literalMatch) {
163
+ this.literalRemaining = parseInt(literalMatch[1], 10);
164
+ this.literalBuffer = "";
165
+ // Store partial line (without the {N}) for continuation
166
+ this.currentLines.push(line.substring(0, line.length - literalMatch[0].length));
167
+ continue;
168
+ }
169
+ // Complete line — join with any previous literal parts
170
+ let fullLine;
171
+ if (this.currentLines.length > 0) {
172
+ this.currentLines.push(line);
173
+ fullLine = this.currentLines.join("");
174
+ this.currentLines = [];
175
+ }
176
+ else {
177
+ fullLine = line;
178
+ }
179
+ this.handleLine(fullLine);
180
+ }
181
+ }
182
+ handleLine(line) {
183
+ const resp = (0, parser_js_1.parseResponseLine)(line);
184
+ // Server greeting (before any command)
185
+ if (this.greetingResolve && resp.tag === "*") {
186
+ const resolve = this.greetingResolve;
187
+ this.greetingResolve = null;
188
+ resolve(resp);
189
+ return;
190
+ }
191
+ if (!this.pending)
192
+ return;
193
+ // Untagged response — collect it
194
+ if (resp.tag === "*" || resp.tag === "+") {
195
+ this.pending.responses.push(resp);
196
+ return;
197
+ }
198
+ // Tagged response — check if it matches our pending command
199
+ if (resp.tag === this.pending.tag) {
200
+ const { responses, resolve, reject } = this.pending;
201
+ this.pending = null;
202
+ if (resp.type === "OK") {
203
+ resolve(responses);
204
+ }
205
+ else {
206
+ reject(new ImapError(resp.type ?? "unknown", resp.text || "Command failed"));
207
+ }
208
+ }
209
+ }
210
+ }
211
+ exports.ImapClient = ImapClient;
212
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/imap/client.ts"],"names":[],"mappings":"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"}