@diskd-ai/email-client-mcp 0.1.39 → 0.1.41

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.
Files changed (40) hide show
  1. package/dist/config/schema.d.ts +22 -32
  2. package/dist/config/schema.js +0 -1
  3. package/dist/config/schema.js.map +1 -1
  4. package/dist/delivery/infrastructure/deliveryProcessor.d.ts +6 -0
  5. package/dist/delivery/infrastructure/deliveryProcessor.js +95 -15
  6. package/dist/delivery/infrastructure/deliveryProcessor.js.map +1 -1
  7. package/dist/delivery/infrastructure/deliveryProtocol.d.ts +50 -0
  8. package/dist/delivery/infrastructure/deliveryProtocol.js +28 -0
  9. package/dist/delivery/infrastructure/deliveryProtocol.js.map +1 -0
  10. package/dist/delivery/infrastructure/deliveryRuntime.d.ts +0 -4
  11. package/dist/delivery/infrastructure/deliveryRuntime.js +4 -110
  12. package/dist/delivery/infrastructure/deliveryRuntime.js.map +1 -1
  13. package/dist/delivery/infrastructure/driveAttachmentLoader.d.ts +36 -0
  14. package/dist/delivery/infrastructure/driveAttachmentLoader.js +76 -0
  15. package/dist/delivery/infrastructure/driveAttachmentLoader.js.map +1 -0
  16. package/dist/delivery/infrastructure/emailOutboxPayload.js +35 -5
  17. package/dist/delivery/infrastructure/emailOutboxPayload.js.map +1 -1
  18. package/dist/delivery/infrastructure/sentFolderAppender.d.ts +48 -0
  19. package/dist/delivery/infrastructure/sentFolderAppender.js +47 -0
  20. package/dist/delivery/infrastructure/sentFolderAppender.js.map +1 -0
  21. package/dist/delivery/infrastructure/smtpTransport.d.ts +21 -2
  22. package/dist/delivery/infrastructure/smtpTransport.js +48 -11
  23. package/dist/delivery/infrastructure/smtpTransport.js.map +1 -1
  24. package/dist/entrypointMode.d.ts +9 -0
  25. package/dist/entrypointMode.js +16 -0
  26. package/dist/entrypointMode.js.map +1 -0
  27. package/dist/events/platformEventNotifier.d.ts +22 -0
  28. package/dist/events/platformEventNotifier.js +29 -0
  29. package/dist/events/platformEventNotifier.js.map +1 -0
  30. package/dist/sdk/diskdClient.d.ts +1 -0
  31. package/dist/sdk/diskdClient.js +2 -1
  32. package/dist/sdk/diskdClient.js.map +1 -1
  33. package/dist/server.js +43 -60
  34. package/dist/server.js.map +1 -1
  35. package/dist/sync/sync.js +2 -2
  36. package/dist/sync/sync.js.map +1 -1
  37. package/package.json +2 -3
  38. package/dist/delivery/infrastructure/outboxEvent.d.ts +0 -30
  39. package/dist/delivery/infrastructure/outboxEvent.js +0 -72
  40. package/dist/delivery/infrastructure/outboxEvent.js.map +0 -1
@@ -1,75 +1,6 @@
1
- import { createHash } from "node:crypto";
2
- import { connect, consumerOpts, } from "nats";
3
1
  import { None, Some } from "../../domain/result.js";
4
- import { outboxCreatedSubject, parseOutboxCreatedEvent } from "./outboxEvent.js";
5
- const ACK_WAIT_MS = 300_000;
6
- const ACK_CONFIRM_TIMEOUT_MS = 5_000;
7
2
  const RECONCILIATION_INTERVAL_MS = 60_000;
8
3
  const RECONCILIATION_PAGE_SIZE = 100;
9
- export const deliveryConsumerName = (workspaceId) => `email-client-mcp-${createHash("sha256").update(workspaceId, "utf8").digest("hex").slice(0, 24)}`;
10
- const acknowledge = async (message, log) => {
11
- const confirmed = await message.ackAck({ timeout: ACK_CONFIRM_TIMEOUT_MS });
12
- if (!confirmed) {
13
- log("delivery.ack-not-confirmed", { sequence: message.seq });
14
- }
15
- };
16
- const applyDisposition = async (message, disposition, log) => {
17
- if (disposition.kind === "Ack") {
18
- await acknowledge(message, log);
19
- return;
20
- }
21
- if (disposition.kind === "Reject") {
22
- log("delivery.event-rejected", { sequence: message.seq, reason: disposition.reason });
23
- message.term();
24
- return;
25
- }
26
- log("delivery.retry-scheduled", {
27
- sequence: message.seq,
28
- reason: disposition.reason,
29
- delayMs: disposition.delayMs,
30
- });
31
- message.nak(disposition.delayMs);
32
- };
33
- const decodeEvent = (message) => {
34
- const text = new TextDecoder().decode(message.data);
35
- const decoded = JSON.parse(text);
36
- return decoded;
37
- };
38
- const handleMessage = async (message, dependencies) => {
39
- let decoded;
40
- try {
41
- decoded = decodeEvent(message);
42
- }
43
- catch (cause) {
44
- dependencies.log("delivery.invalid-json-event", {
45
- sequence: message.seq,
46
- error: cause instanceof Error ? cause.message : String(cause),
47
- });
48
- message.term();
49
- return;
50
- }
51
- const event = parseOutboxCreatedEvent(decoded, dependencies.workspaceId);
52
- if (event.tag === "Err") {
53
- dependencies.log("delivery.invalid-outbox-event", {
54
- sequence: message.seq,
55
- error: event.error.kind,
56
- });
57
- message.term();
58
- return;
59
- }
60
- const disposition = await dependencies.processor.process({
61
- kind: "EventLocator",
62
- externalId: event.value.externalId,
63
- account: event.value.account,
64
- mailboxId: event.value.mailboxId,
65
- });
66
- dependencies.log("delivery.event-processed", {
67
- eventId: event.value.eventId,
68
- externalId: event.value.externalId,
69
- disposition: disposition.kind,
70
- });
71
- await applyDisposition(message, disposition, dependencies.log);
72
- };
73
4
  const reconcilePending = async (dependencies) => {
74
5
  let cursor = None;
75
6
  const seenCursors = new Set();
@@ -108,13 +39,12 @@ const reconcilePending = async (dependencies) => {
108
39
  }
109
40
  };
110
41
  export const buildDeliveryRuntime = (dependencies) => {
111
- let connection;
112
- let subscription;
113
- let consumeLoop;
114
42
  let reconciliation;
115
43
  let reconciliationTimer;
116
44
  let stopping = false;
117
45
  const beginReconciliation = () => {
46
+ if (stopping)
47
+ return;
118
48
  if (reconciliation !== undefined) {
119
49
  dependencies.log("delivery.reconciliation-skipped", { reason: "previous sweep is active" });
120
50
  return;
@@ -131,41 +61,11 @@ export const buildDeliveryRuntime = (dependencies) => {
131
61
  };
132
62
  return {
133
63
  start: async () => {
134
- connection = await connect({
135
- servers: dependencies.natsUrl,
136
- name: deliveryConsumerName(dependencies.workspaceId),
137
- maxReconnectAttempts: -1,
138
- });
139
- const options = consumerOpts();
140
- options
141
- .durable(deliveryConsumerName(dependencies.workspaceId))
142
- .deliverAll()
143
- .ackExplicit()
144
- .manualAck()
145
- .ackWait(ACK_WAIT_MS)
146
- .maxAckPending(1);
147
- const subject = outboxCreatedSubject(dependencies.workspaceId);
148
- subscription = await connection.jetstream().pullSubscribe(subject, options);
149
- const activeSubscription = subscription;
150
- activeSubscription.pull({ batch: 1 });
151
- consumeLoop = (async () => {
152
- for await (const message of activeSubscription) {
153
- await handleMessage(message, dependencies);
154
- if (!stopping)
155
- activeSubscription.pull({ batch: 1 });
156
- }
157
- if (!stopping)
158
- throw new Error("JetStream delivery subscription ended unexpectedly");
159
- })();
160
- consumeLoop.catch((cause) => {
161
- if (!stopping)
162
- dependencies.onFatal(cause);
163
- });
164
64
  await reconcilePending(dependencies);
165
65
  reconciliationTimer = setInterval(beginReconciliation, RECONCILIATION_INTERVAL_MS);
166
66
  dependencies.log("delivery.ready", {
167
- subject,
168
- consumer: deliveryConsumerName(dependencies.workspaceId),
67
+ source: "drive-outbox-reconciliation",
68
+ intervalMs: RECONCILIATION_INTERVAL_MS,
169
69
  });
170
70
  },
171
71
  stop: async () => {
@@ -174,12 +74,6 @@ export const buildDeliveryRuntime = (dependencies) => {
174
74
  clearInterval(reconciliationTimer);
175
75
  if (reconciliation !== undefined)
176
76
  await reconciliation;
177
- if (subscription !== undefined)
178
- await subscription.drain();
179
- if (connection !== undefined)
180
- await connection.drain();
181
- if (consumeLoop !== undefined)
182
- await consumeLoop;
183
77
  },
184
78
  };
185
79
  };
@@ -1 +1 @@
1
- {"version":3,"file":"deliveryRuntime.js","sourceRoot":"","sources":["../../../src/delivery/infrastructure/deliveryRuntime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deliveryRuntime.js","sourceRoot":"","sources":["../../../src/delivery/infrastructure/deliveryRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAe,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAIjE,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAC1C,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAarC,MAAM,gBAAgB,GAAG,KAAK,EAAE,YAAyC,EAAiB,EAAE;IAC1F,IAAI,MAAM,GAAmB,IAAI,CAAC;IAClC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC;YACrD,KAAK,EAAE,wBAAwB;YAC/B,MAAM;SACP,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;YACvB,YAAY,CAAC,GAAG,CAAC,qCAAqC,EAAE;gBACtD,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;gBACtB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS;aAChC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACpC,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC;gBACvD,IAAI,EAAE,gBAAgB;gBACtB,UAAU,EAAE,IAAI,CAAC,UAAU;aAC5B,CAAC,CAAC;YACH,YAAY,CAAC,GAAG,CAAC,8BAA8B,EAAE;gBAC/C,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,WAAW,EAAE,WAAW,CAAC,IAAI;aAC9B,CAAC,CAAC;QACL,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,KAAK,MAAM;YAAE,OAAO;QACjD,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,YAAY,CAAC,GAAG,CAAC,sCAAsC,EAAE;gBACvD,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK;aACpC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,YAAyC,EACxB,EAAE;IACnB,IAAI,cAAyC,CAAC;IAC9C,IAAI,mBAA+C,CAAC;IACpD,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,mBAAmB,GAAG,GAAS,EAAE;QACrC,IAAI,QAAQ;YAAE,OAAO;QACrB,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;YACjC,YAAY,CAAC,GAAG,CAAC,iCAAiC,EAAE,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC,CAAC;YAC5F,OAAO;QACT,CAAC;QACD,cAAc,GAAG,gBAAgB,CAAC,YAAY,CAAC;aAC5C,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,YAAY,CAAC,GAAG,CAAC,gCAAgC,EAAE;gBACjD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;QACL,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,cAAc,GAAG,SAAS,CAAC;QAC7B,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,gBAAgB,CAAC,YAAY,CAAC,CAAC;YACrC,mBAAmB,GAAG,WAAW,CAAC,mBAAmB,EAAE,0BAA0B,CAAC,CAAC;YACnF,YAAY,CAAC,GAAG,CAAC,gBAAgB,EAAE;gBACjC,MAAM,EAAE,6BAA6B;gBACrC,UAAU,EAAE,0BAA0B;aACvC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,mBAAmB,KAAK,SAAS;gBAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;YAC1E,IAAI,cAAc,KAAK,SAAS;gBAAE,MAAM,cAAc,CAAC;QACzD,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { EmailOutboxAttachment } from "@diskd-ai/sdk";
2
+ import { type Result } from "../../domain/result.js";
3
+ type DriveDownloadResult = {
4
+ readonly stream: ReadableStream<Uint8Array>;
5
+ readonly size: number;
6
+ readonly mimeType: string | null;
7
+ };
8
+ type DriveDownloadPort = {
9
+ readonly download: {
10
+ readonly file: (input: {
11
+ readonly path: string;
12
+ }) => Promise<DriveDownloadResult>;
13
+ };
14
+ };
15
+ export type LoadedEmailAttachment = {
16
+ readonly filename: string;
17
+ readonly contentType: string;
18
+ readonly content: Buffer;
19
+ };
20
+ export type DriveAttachmentLoadError = {
21
+ readonly kind: "AttachmentSizeExceeded";
22
+ readonly path: string;
23
+ readonly maxTotalBytes: number;
24
+ } | {
25
+ readonly kind: "AttachmentDownloadFailed";
26
+ readonly path: string;
27
+ readonly message: string;
28
+ };
29
+ export type DriveAttachmentLoader = {
30
+ readonly load: (attachments: readonly EmailOutboxAttachment[]) => Promise<Result<DriveAttachmentLoadError, readonly LoadedEmailAttachment[]>>;
31
+ };
32
+ type DriveAttachmentLoaderOptions = {
33
+ readonly maxTotalBytes?: number;
34
+ };
35
+ export declare const buildDriveAttachmentLoader: (drive: DriveDownloadPort, options?: DriveAttachmentLoaderOptions) => DriveAttachmentLoader;
36
+ export {};
@@ -0,0 +1,76 @@
1
+ import { Err, Ok } from "../../domain/result.js";
2
+ const DEFAULT_MAX_TOTAL_BYTES = 25 * 1024 * 1024;
3
+ const causeMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
4
+ const readBounded = async (attachment, download, bytesAlreadyLoaded, maxTotalBytes) => {
5
+ if (download.size > maxTotalBytes - bytesAlreadyLoaded) {
6
+ return Err({
7
+ kind: "AttachmentSizeExceeded",
8
+ path: attachment.path,
9
+ maxTotalBytes,
10
+ });
11
+ }
12
+ const reader = download.stream.getReader();
13
+ const chunks = [];
14
+ let attachmentBytes = 0;
15
+ try {
16
+ for (;;) {
17
+ const chunk = await reader.read();
18
+ if (chunk.done)
19
+ break;
20
+ attachmentBytes += chunk.value.byteLength;
21
+ if (bytesAlreadyLoaded + attachmentBytes > maxTotalBytes) {
22
+ await reader.cancel("attachment size limit exceeded");
23
+ return Err({
24
+ kind: "AttachmentSizeExceeded",
25
+ path: attachment.path,
26
+ maxTotalBytes,
27
+ });
28
+ }
29
+ chunks.push(chunk.value);
30
+ }
31
+ return Ok(Buffer.concat(chunks.map((chunk) => Buffer.from(chunk))));
32
+ }
33
+ catch (cause) {
34
+ return Err({
35
+ kind: "AttachmentDownloadFailed",
36
+ path: attachment.path,
37
+ message: causeMessage(cause),
38
+ });
39
+ }
40
+ finally {
41
+ reader.releaseLock();
42
+ }
43
+ };
44
+ export const buildDriveAttachmentLoader = (drive, options = {}) => {
45
+ const maxTotalBytes = options.maxTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES;
46
+ return {
47
+ load: async (attachments) => {
48
+ const loaded = [];
49
+ let bytesLoaded = 0;
50
+ for (const attachment of attachments) {
51
+ let download;
52
+ try {
53
+ download = await drive.download.file({ path: attachment.path });
54
+ }
55
+ catch (cause) {
56
+ return Err({
57
+ kind: "AttachmentDownloadFailed",
58
+ path: attachment.path,
59
+ message: causeMessage(cause),
60
+ });
61
+ }
62
+ const content = await readBounded(attachment, download, bytesLoaded, maxTotalBytes);
63
+ if (content.tag === "Err")
64
+ return content;
65
+ bytesLoaded += content.value.byteLength;
66
+ loaded.push({
67
+ filename: attachment.filename,
68
+ contentType: attachment.contentType,
69
+ content: content.value,
70
+ });
71
+ }
72
+ return Ok(loaded);
73
+ },
74
+ };
75
+ };
76
+ //# sourceMappingURL=driveAttachmentLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driveAttachmentLoader.js","sourceRoot":"","sources":["../../../src/delivery/infrastructure/driveAttachmentLoader.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,14 @@ const recipientContactSchema = z.object({
8
8
  name: z.string(),
9
9
  address: z.string().email(),
10
10
  });
11
- const emailOutboxPayloadSchema = z.object({
11
+ const emailOutboxAttachmentSchema = z
12
+ .object({
13
+ path: z.string().min(1),
14
+ filename: z.string().min(1),
15
+ contentType: z.string().min(1),
16
+ })
17
+ .strict();
18
+ const emailOutboxPayloadFields = {
12
19
  messageId: z.string().min(1),
13
20
  account: z.string().min(1),
14
21
  threadId: z.string().min(1).nullable(),
@@ -20,9 +27,19 @@ const emailOutboxPayloadSchema = z.object({
20
27
  subject: z.string(),
21
28
  bodyText: z.string(),
22
29
  bodyHtml: z.string(),
23
- hasAttachments: z.literal(false),
24
- attachments: z.tuple([]),
25
- });
30
+ };
31
+ const emailOutboxPayloadSchema = z.discriminatedUnion("hasAttachments", [
32
+ z.object({
33
+ ...emailOutboxPayloadFields,
34
+ hasAttachments: z.literal(false),
35
+ attachments: z.tuple([]),
36
+ }),
37
+ z.object({
38
+ ...emailOutboxPayloadFields,
39
+ hasAttachments: z.literal(true),
40
+ attachments: z.array(emailOutboxAttachmentSchema).min(1),
41
+ }),
42
+ ]);
26
43
  export const parseEmailOutboxPayload = (rawPayload, expectedAccount) => {
27
44
  const parsed = emailOutboxPayloadSchema.safeParse(rawPayload);
28
45
  if (!parsed.success) {
@@ -37,6 +54,19 @@ export const parseEmailOutboxPayload = (rawPayload, expectedAccount) => {
37
54
  issues: ["account: payload account does not match the stored Outbox account"],
38
55
  });
39
56
  }
40
- return Ok(parsed.data);
57
+ if (!parsed.data.hasAttachments)
58
+ return Ok(parsed.data);
59
+ const [firstAttachment, ...remainingAttachments] = parsed.data.attachments;
60
+ if (firstAttachment === undefined) {
61
+ return Err({
62
+ kind: "InvalidEmailOutboxPayload",
63
+ issues: ["attachments: at least one Drive attachment reference is required"],
64
+ });
65
+ }
66
+ const value = {
67
+ ...parsed.data,
68
+ attachments: [firstAttachment, ...remainingAttachments],
69
+ };
70
+ return Ok(value);
41
71
  };
42
72
  //# sourceMappingURL=emailOutboxPayload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"emailOutboxPayload.js","sourceRoot":"","sources":["../../../src/delivery/infrastructure/emailOutboxPayload.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,wBAAwB,CAAC;AAE9D,MAAM,mBAAmB,GAAkC,CAAC,CAAC,MAAM,CAAC;IAClE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3B,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAkC,CAAC,CAAC,MAAM,CAAC;IACrE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;CAC5B,CAAC,CAAC;AAEH,MAAM,wBAAwB,GAAkC,CAAC,CAAC,MAAM,CAAC;IACvE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACtC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvC,IAAI,EAAE,mBAAmB;IACzB,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC;IACnC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC;IACpC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IAChC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;CACzB,CAAC,CAAC;AAOH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,UAAmB,EACnB,eAAuB,EAC8B,EAAE;IACvD,MAAM,MAAM,GAAG,wBAAwB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,GAAG,CAAC;YACT,IAAI,EAAE,2BAA2B;YACjC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;SACxF,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,eAAe,EAAE,CAAC;QAC5C,OAAO,GAAG,CAAC;YACT,IAAI,EAAE,2BAA2B;YACjC,MAAM,EAAE,CAAC,mEAAmE,CAAC;SAC9E,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC,CAAC"}
1
+ {"version":3,"file":"emailOutboxPayload.js","sourceRoot":"","sources":["../../../src/delivery/infrastructure/emailOutboxPayload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { type Result } from "../../domain/result.js";
2
+ type SentFolder = {
3
+ readonly path: string;
4
+ readonly specialUse?: string;
5
+ };
6
+ type AppendReceipt = {
7
+ readonly destination: string;
8
+ readonly uidValidity?: bigint;
9
+ readonly uid?: number;
10
+ };
11
+ type SentFolderClient = {
12
+ readonly list: () => Promise<readonly SentFolder[]>;
13
+ readonly append: (path: string, rawMessage: Buffer, flags: string[], internalDate: Date) => Promise<AppendReceipt | false>;
14
+ };
15
+ type SentFolderPool = {
16
+ readonly forAccount: (accountId: string) => Promise<Result<{
17
+ readonly message?: string;
18
+ }, SentFolderClient>>;
19
+ };
20
+ export type SentFolderAppendReceipt = {
21
+ readonly folder: string;
22
+ readonly uidValidity: string;
23
+ readonly uid: string;
24
+ };
25
+ export type SentFolderAppendError = {
26
+ readonly kind: "SentAccountUnavailable";
27
+ readonly accountId: string;
28
+ readonly message: string;
29
+ } | {
30
+ readonly kind: "SentFolderListFailed";
31
+ readonly accountId: string;
32
+ readonly message: string;
33
+ } | {
34
+ readonly kind: "SentFolderMissing";
35
+ readonly accountId: string;
36
+ } | {
37
+ readonly kind: "SentAppendFailed";
38
+ readonly accountId: string;
39
+ readonly message: string;
40
+ } | {
41
+ readonly kind: "SentAppendReceiptMissing";
42
+ readonly accountId: string;
43
+ };
44
+ export type SentFolderAppender = {
45
+ readonly append: (accountId: string, rawMessage: Buffer, internalDate: Date) => Promise<Result<SentFolderAppendError, SentFolderAppendReceipt>>;
46
+ };
47
+ export declare const buildSentFolderAppender: (pool: SentFolderPool) => SentFolderAppender;
48
+ export {};
@@ -0,0 +1,47 @@
1
+ import { Err, Ok } from "../../domain/result.js";
2
+ const causeMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
3
+ export const buildSentFolderAppender = (pool) => ({
4
+ append: async (accountId, rawMessage, internalDate) => {
5
+ const connected = await pool.forAccount(accountId);
6
+ if (connected.tag === "Err") {
7
+ return Err({
8
+ kind: "SentAccountUnavailable",
9
+ accountId,
10
+ message: connected.error.message ?? "IMAP account unavailable",
11
+ });
12
+ }
13
+ let folders;
14
+ try {
15
+ folders = await connected.value.list();
16
+ }
17
+ catch (cause) {
18
+ return Err({
19
+ kind: "SentFolderListFailed",
20
+ accountId,
21
+ message: causeMessage(cause),
22
+ });
23
+ }
24
+ const sentFolder = folders.find((folder) => folder.specialUse === "\\Sent");
25
+ if (sentFolder === undefined)
26
+ return Err({ kind: "SentFolderMissing", accountId });
27
+ try {
28
+ const appended = await connected.value.append(sentFolder.path, rawMessage, ["\\Seen"], internalDate);
29
+ if (appended === false || appended.uidValidity === undefined || appended.uid === undefined) {
30
+ return Err({ kind: "SentAppendReceiptMissing", accountId });
31
+ }
32
+ return Ok({
33
+ folder: appended.destination,
34
+ uidValidity: appended.uidValidity.toString(),
35
+ uid: appended.uid.toString(),
36
+ });
37
+ }
38
+ catch (cause) {
39
+ return Err({
40
+ kind: "SentAppendFailed",
41
+ accountId,
42
+ message: causeMessage(cause),
43
+ });
44
+ }
45
+ },
46
+ });
47
+ //# sourceMappingURL=sentFolderAppender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentFolderAppender.js","sourceRoot":"","sources":["../../../src/delivery/infrastructure/sentFolderAppender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,wBAAwB,CAAC;AAsD9D,MAAM,YAAY,GAAG,CAAC,KAAc,EAAU,EAAE,CAC9C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAEzD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,IAAoB,EAAsB,EAAE,CAAC,CAAC;IACpF,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE;QACpD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,SAAS,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;YAC5B,OAAO,GAAG,CAAC;gBACT,IAAI,EAAE,wBAAwB;gBAC9B,SAAS;gBACT,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,OAAO,IAAI,0BAA0B;aAC/D,CAAC,CAAC;QACL,CAAC;QAED,IAAI,OAA8B,CAAC;QACnC,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,GAAG,CAAC;gBACT,IAAI,EAAE,sBAAsB;gBAC5B,SAAS;gBACT,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC;aAC7B,CAAC,CAAC;QACL,CAAC;QACD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC;QAC5E,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,SAAS,EAAE,CAAC,CAAC;QAEnF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,MAAM,CAC3C,UAAU,CAAC,IAAI,EACf,UAAU,EACV,CAAC,QAAQ,CAAC,EACV,YAAY,CACb,CAAC;YACF,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,CAAC,WAAW,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;gBAC3F,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,0BAA0B,EAAE,SAAS,EAAE,CAAC,CAAC;YAC9D,CAAC;YACD,OAAO,EAAE,CAAC;gBACR,MAAM,EAAE,QAAQ,CAAC,WAAW;gBAC5B,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE;gBAC5C,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE;aAC7B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,GAAG,CAAC;gBACT,IAAI,EAAE,kBAAkB;gBACxB,SAAS;gBACT,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC;aAC7B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import type { EmailOutboxPayload } from "@diskd-ai/sdk";
2
2
  import { type Account, type SmtpSettings } from "../../config/schema.js";
3
3
  import type { TransportOutcome } from "../domain/transportOutcome.js";
4
+ import type { LoadedEmailAttachment } from "./driveAttachmentLoader.js";
4
5
  type PasswordSmtpAuth = {
5
6
  readonly type: "login";
6
7
  readonly user: string;
@@ -28,16 +29,34 @@ export type SmtpConnectionOptions = {
28
29
  };
29
30
  export type SmtpMessage = {
30
31
  readonly payload: EmailOutboxPayload;
32
+ readonly attachments: readonly LoadedEmailAttachment[];
31
33
  readonly fromAddress: string;
32
34
  readonly fromName: string;
33
35
  };
36
+ export type SmtpSendResult = {
37
+ readonly kind: "Accepted";
38
+ readonly receipt: {
39
+ readonly messageId: string;
40
+ readonly accepted: readonly string[];
41
+ readonly rejected: readonly string[];
42
+ readonly response: string;
43
+ };
44
+ readonly rawMessage: Buffer;
45
+ } | Exclude<TransportOutcome, {
46
+ readonly kind: "Accepted";
47
+ }>;
48
+ type SmtpFailureOutcome = Exclude<TransportOutcome, {
49
+ readonly kind: "Accepted";
50
+ }>;
34
51
  export type SmtpSender = {
35
- readonly send: (message: SmtpMessage) => Promise<TransportOutcome>;
52
+ readonly send: (message: SmtpMessage) => Promise<SmtpSendResult>;
36
53
  readonly close: () => void;
37
54
  };
38
55
  /** Classify only failures proven to occur before SMTP acceptance as retryable. */
39
- export declare const classifySmtpFailure: (cause: unknown) => TransportOutcome;
56
+ export declare const classifySmtpFailure: (cause: unknown) => SmtpFailureOutcome;
40
57
  export declare const buildSmtpConnectionOptions: (account: Account, smtp: SmtpSettings) => SmtpConnectionOptions;
41
58
  export declare const toSmtpMessageId: (messageId: string) => string;
59
+ /** Compose once so SMTP submission and the IMAP Sent copy share byte-identical RFC822 content. */
60
+ export declare const composeRawMessage: (message: SmtpMessage) => Promise<Buffer>;
42
61
  export declare const buildSmtpSender: (account: Account) => SmtpSender;
43
62
  export {};
@@ -1,5 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import * as nodemailer from "nodemailer";
3
+ import MailComposer from "nodemailer/lib/mail-composer/index.js";
3
4
  import { z } from "zod";
4
5
  import { isOAuthAccount } from "../../config/schema.js";
5
6
  const CONNECTION_TIMEOUT_MS = 30_000;
@@ -101,6 +102,32 @@ const normalizeSmtpAddresses = (values) => values.flatMap((value) => {
101
102
  const address = readSmtpAddress(value);
102
103
  return address === undefined ? [] : [address];
103
104
  });
105
+ const recipientAddresses = (payload) => [
106
+ ...payload.to.map((contact) => contact.address),
107
+ ...payload.cc.map((contact) => contact.address),
108
+ ...payload.bcc.map((contact) => contact.address),
109
+ ];
110
+ /** Compose once so SMTP submission and the IMAP Sent copy share byte-identical RFC822 content. */
111
+ export const composeRawMessage = async (message) => new MailComposer({
112
+ messageId: toSmtpMessageId(message.payload.messageId),
113
+ from: { name: message.fromName, address: message.fromAddress },
114
+ to: [...message.payload.to],
115
+ cc: [...message.payload.cc],
116
+ bcc: [...message.payload.bcc],
117
+ subject: message.payload.subject,
118
+ text: message.payload.bodyText,
119
+ html: message.payload.bodyHtml || undefined,
120
+ inReplyTo: message.payload.inReplyTo ?? undefined,
121
+ attachments: message.attachments.map((attachment) => ({
122
+ filename: attachment.filename,
123
+ contentType: attachment.contentType,
124
+ content: attachment.content,
125
+ })),
126
+ disableFileAccess: true,
127
+ disableUrlAccess: true,
128
+ })
129
+ .compile()
130
+ .build();
104
131
  export const buildSmtpSender = (account) => {
105
132
  if (account.smtp === undefined) {
106
133
  throw new Error(`SMTP settings missing for account: ${account.name}`);
@@ -108,22 +135,32 @@ export const buildSmtpSender = (account) => {
108
135
  const transport = nodemailer.createTransport(buildSmtpConnectionOptions(account, account.smtp));
109
136
  return {
110
137
  send: async (message) => {
138
+ let rawMessage;
139
+ try {
140
+ rawMessage = await composeRawMessage(message);
141
+ }
142
+ catch (cause) {
143
+ return {
144
+ kind: "RejectedBeforeAcceptance",
145
+ rejection: {
146
+ kind: "Permanent",
147
+ failure: {
148
+ reason: `Message composition failed: ${cause instanceof Error ? cause.message : String(cause)}`,
149
+ },
150
+ },
151
+ };
152
+ }
111
153
  try {
112
154
  const info = await transport.sendMail({
113
- messageId: toSmtpMessageId(message.payload.messageId),
114
- from: { name: message.fromName, address: message.fromAddress },
115
- to: [...message.payload.to],
116
- cc: [...message.payload.cc],
117
- bcc: [...message.payload.bcc],
118
- subject: message.payload.subject,
119
- text: message.payload.bodyText,
120
- html: message.payload.bodyHtml || undefined,
121
- inReplyTo: message.payload.inReplyTo ?? undefined,
122
- disableFileAccess: true,
123
- disableUrlAccess: true,
155
+ raw: rawMessage,
156
+ envelope: {
157
+ from: message.fromAddress,
158
+ to: [...recipientAddresses(message.payload)],
159
+ },
124
160
  });
125
161
  return {
126
162
  kind: "Accepted",
163
+ rawMessage,
127
164
  receipt: {
128
165
  messageId: info.messageId,
129
166
  accepted: normalizeSmtpAddresses(info.accepted),
@@ -1 +1 @@
1
- {"version":3,"file":"smtpTransport.js","sourceRoot":"","sources":["../../../src/delivery/infrastructure/smtpTransport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"smtpTransport.js","sourceRoot":"","sources":["../../../src/delivery/infrastructure/smtpTransport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type ServerMode = "stdio" | "deliver" | "unknown";
2
+ export type ServerModeRegistrations = {
3
+ readonly registerDelivery: () => void;
4
+ readonly registerTools: () => void;
5
+ };
6
+ /** Parse the executable subcommand without reading process-global state. */
7
+ export declare const parseSubcommand: (argv: readonly string[]) => ServerMode;
8
+ /** Register only the protocol surfaces owned by the selected entrypoint. */
9
+ export declare const configureServerMode: (mode: Exclude<ServerMode, "unknown">, registrations: ServerModeRegistrations) => void;