@cogitator-ai/channels 0.16.0 → 0.18.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.
Files changed (112) hide show
  1. package/README.md +78 -14
  2. package/dist/approvals.d.ts +3 -0
  3. package/dist/approvals.d.ts.map +1 -1
  4. package/dist/approvals.js +1 -0
  5. package/dist/approvals.js.map +1 -1
  6. package/dist/assistant-config.d.ts +60 -0
  7. package/dist/assistant-config.d.ts.map +1 -1
  8. package/dist/assistant-config.js +102 -0
  9. package/dist/assistant-config.js.map +1 -1
  10. package/dist/channels/email/address.d.ts +44 -0
  11. package/dist/channels/email/address.d.ts.map +1 -0
  12. package/dist/channels/email/address.js +211 -0
  13. package/dist/channels/email/address.js.map +1 -0
  14. package/dist/channels/email/auth.d.ts +59 -0
  15. package/dist/channels/email/auth.d.ts.map +1 -0
  16. package/dist/channels/email/auth.js +212 -0
  17. package/dist/channels/email/auth.js.map +1 -0
  18. package/dist/channels/email/channel.d.ts +256 -0
  19. package/dist/channels/email/channel.d.ts.map +1 -0
  20. package/dist/channels/email/channel.js +701 -0
  21. package/dist/channels/email/channel.js.map +1 -0
  22. package/dist/channels/email/errors.d.ts +11 -0
  23. package/dist/channels/email/errors.d.ts.map +1 -0
  24. package/dist/channels/email/errors.js +13 -0
  25. package/dist/channels/email/errors.js.map +1 -0
  26. package/dist/channels/email/imap.d.ts +125 -0
  27. package/dist/channels/email/imap.d.ts.map +1 -0
  28. package/dist/channels/email/imap.js +309 -0
  29. package/dist/channels/email/imap.js.map +1 -0
  30. package/dist/channels/email/index.d.ts +7 -0
  31. package/dist/channels/email/index.d.ts.map +1 -0
  32. package/dist/channels/email/index.js +3 -0
  33. package/dist/channels/email/index.js.map +1 -0
  34. package/dist/channels/email/mime.d.ts +71 -0
  35. package/dist/channels/email/mime.d.ts.map +1 -0
  36. package/dist/channels/email/mime.js +83 -0
  37. package/dist/channels/email/mime.js.map +1 -0
  38. package/dist/channels/email/multipart.d.ts +28 -0
  39. package/dist/channels/email/multipart.d.ts.map +1 -0
  40. package/dist/channels/email/multipart.js +102 -0
  41. package/dist/channels/email/multipart.js.map +1 -0
  42. package/dist/channels/email/providers.d.ts +49 -0
  43. package/dist/channels/email/providers.d.ts.map +1 -0
  44. package/dist/channels/email/providers.js +292 -0
  45. package/dist/channels/email/providers.js.map +1 -0
  46. package/dist/channels/email/reply.d.ts +9 -0
  47. package/dist/channels/email/reply.d.ts.map +1 -0
  48. package/dist/channels/email/reply.js +122 -0
  49. package/dist/channels/email/reply.js.map +1 -0
  50. package/dist/channels/teams/activity.d.ts +108 -0
  51. package/dist/channels/teams/activity.d.ts.map +1 -0
  52. package/dist/channels/teams/activity.js +206 -0
  53. package/dist/channels/teams/activity.js.map +1 -0
  54. package/dist/channels/teams/auth.d.ts +65 -0
  55. package/dist/channels/teams/auth.d.ts.map +1 -0
  56. package/dist/channels/teams/auth.js +213 -0
  57. package/dist/channels/teams/auth.js.map +1 -0
  58. package/dist/channels/teams/cards.d.ts +23 -0
  59. package/dist/channels/teams/cards.d.ts.map +1 -0
  60. package/dist/channels/teams/cards.js +97 -0
  61. package/dist/channels/teams/cards.js.map +1 -0
  62. package/dist/channels/teams/channel.d.ts +303 -0
  63. package/dist/channels/teams/channel.d.ts.map +1 -0
  64. package/dist/channels/teams/channel.js +1071 -0
  65. package/dist/channels/teams/channel.js.map +1 -0
  66. package/dist/channels/teams/client.d.ts +72 -0
  67. package/dist/channels/teams/client.d.ts.map +1 -0
  68. package/dist/channels/teams/client.js +161 -0
  69. package/dist/channels/teams/client.js.map +1 -0
  70. package/dist/channels/teams/index.d.ts +7 -0
  71. package/dist/channels/teams/index.d.ts.map +1 -0
  72. package/dist/channels/teams/index.js +6 -0
  73. package/dist/channels/teams/index.js.map +1 -0
  74. package/dist/channels/teams/pacer.d.ts +47 -0
  75. package/dist/channels/teams/pacer.d.ts.map +1 -0
  76. package/dist/channels/teams/pacer.js +174 -0
  77. package/dist/channels/teams/pacer.js.map +1 -0
  78. package/dist/channels/teams/token.d.ts +47 -0
  79. package/dist/channels/teams/token.d.ts.map +1 -0
  80. package/dist/channels/teams/token.js +107 -0
  81. package/dist/channels/teams/token.js.map +1 -0
  82. package/dist/channels/telegram.d.ts.map +1 -1
  83. package/dist/channels/telegram.js +3 -0
  84. package/dist/channels/telegram.js.map +1 -1
  85. package/dist/formatters/html.d.ts +16 -0
  86. package/dist/formatters/html.d.ts.map +1 -0
  87. package/dist/formatters/html.js +535 -0
  88. package/dist/formatters/html.js.map +1 -0
  89. package/dist/formatters/markdown-images.d.ts +8 -0
  90. package/dist/formatters/markdown-images.d.ts.map +1 -0
  91. package/dist/formatters/markdown-images.js +181 -0
  92. package/dist/formatters/markdown-images.js.map +1 -0
  93. package/dist/formatters/markdown.d.ts.map +1 -1
  94. package/dist/formatters/markdown.js +22 -3
  95. package/dist/formatters/markdown.js.map +1 -1
  96. package/dist/gateway.d.ts +23 -1
  97. package/dist/gateway.d.ts.map +1 -1
  98. package/dist/gateway.js +113 -16
  99. package/dist/gateway.js.map +1 -1
  100. package/dist/inbound-debounce.d.ts +4 -1
  101. package/dist/inbound-debounce.d.ts.map +1 -1
  102. package/dist/inbound-debounce.js +4 -2
  103. package/dist/inbound-debounce.js.map +1 -1
  104. package/dist/index.d.ts +5 -2
  105. package/dist/index.d.ts.map +1 -1
  106. package/dist/index.js +5 -2
  107. package/dist/index.js.map +1 -1
  108. package/dist/runtime-builder.d.ts +9 -0
  109. package/dist/runtime-builder.d.ts.map +1 -1
  110. package/dist/runtime-builder.js +145 -1
  111. package/dist/runtime-builder.js.map +1 -1
  112. package/package.json +25 -8
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime.d.ts","sourceRoot":"","sources":["../../../src/channels/email/mime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAQL,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAwB,KAAK,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAGzE,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,wEAAwE;IACxE,cAAc,EAAE,oBAAoB,CAAC;IACrC,uDAAuD;IACvD,GAAG,EAAE,OAAO,CAAC;CACd;AAED,+EAA+E;AAC/E,UAAU,gBAAgB;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;CAC5C;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC3D;AAED,UAAU,gBAAgB;IACxB,OAAO,EAAE,UAAU,gBAAgB,CAAC;CACrC;AAID,iFAAiF;AACjF,wBAAgB,cAAc,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAY1D;AAED,0CAA0C;AAC1C,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAKjE;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAC1B,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,QAAQ,EAAE,MAAM,GACf,UAAU,GAAG,SAAS,CAcxB;AAOD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAYA;AAED,MAAM,WAAW,eAAe;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,yDAAyD;AACzD,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,GAAG,UAAU,EACxB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,YAAY,CAAC,CA6BvB"}
@@ -0,0 +1,83 @@
1
+ import { decodeMimeWords, domainOf, headerOf, headersOf, messageIdOf, messageIdsOf, parseMailbox, } from './address.js';
2
+ import { headerAuthentication } from './auth.js';
3
+ import { EmailDependencyError } from './errors.js';
4
+ let postalMime;
5
+ /** Loads `postal-mime` once, failing with an install hint when it is missing. */
6
+ export function loadPostalMime() {
7
+ postalMime ??= import('postal-mime').catch((error) => {
8
+ postalMime = undefined;
9
+ throw new EmailDependencyError('postal-mime', 'to read raw email (IMAP, Mailgun MIME mode, SendGrid raw mode)', { cause: error });
10
+ });
11
+ return postalMime;
12
+ }
13
+ /** The attachment type of a MIME type. */
14
+ export function attachmentTypeOf(mimeType) {
15
+ if (mimeType.startsWith('image/'))
16
+ return 'image';
17
+ if (mimeType.startsWith('audio/'))
18
+ return 'audio';
19
+ if (mimeType.startsWith('video/'))
20
+ return 'video';
21
+ return 'file';
22
+ }
23
+ /** An attachment of an email, or nothing when it is larger than `maxBytes`. */
24
+ export function attachmentOf(content, mimeType, filename, maxBytes) {
25
+ if (content.byteLength > maxBytes) {
26
+ console.warn(`[email] Skipped the attachment ${filename ?? mimeType} of ${content.byteLength} bytes, over the limit of ${maxBytes}`);
27
+ return undefined;
28
+ }
29
+ const type = mimeType.toLowerCase().split(';')[0].trim() || 'application/octet-stream';
30
+ return {
31
+ type: attachmentTypeOf(type),
32
+ buffer: content,
33
+ mimeType: type,
34
+ ...(filename && { filename }),
35
+ };
36
+ }
37
+ function bytesOf(content) {
38
+ if (typeof content === 'string')
39
+ return Buffer.from(content, 'base64');
40
+ return content instanceof Uint8Array ? content : new Uint8Array(content);
41
+ }
42
+ /**
43
+ * The thread fields, sender and subject every inbound email reads from its headers. A mail with
44
+ * more than one `From` has no sender, since mail clients may show another one than is checked.
45
+ */
46
+ export function envelopeOf(headers) {
47
+ const messageId = messageIdOf(headerOf(headers, 'message-id'));
48
+ const inReplyTo = messageIdOf(headerOf(headers, 'in-reply-to'));
49
+ const fromHeaders = headersOf(headers, 'from');
50
+ const from = fromHeaders.length === 1 ? parseMailbox(fromHeaders[0]) : undefined;
51
+ return {
52
+ ...(messageId && { messageId }),
53
+ ...(inReplyTo && { inReplyTo }),
54
+ references: messageIdsOf(headerOf(headers, 'references')),
55
+ ...(from && { from }),
56
+ subject: decodeMimeWords(headerOf(headers, 'subject') ?? '').trim(),
57
+ };
58
+ }
59
+ /** A raw RFC 5322 message, parsed with `postal-mime`. */
60
+ export async function parseRawEmail(raw, options) {
61
+ const { default: PostalMime } = await loadPostalMime();
62
+ const parsed = await new PostalMime().parse(raw);
63
+ const headers = parsed.headers.map(({ key, value }) => [key.toLowerCase(), value]);
64
+ const envelope = envelopeOf(headers);
65
+ const attachments = parsed.attachments
66
+ .filter((attachment) => !attachment.related)
67
+ .map((attachment) => attachmentOf(bytesOf(attachment.content), attachment.mimeType, attachment.filename ?? undefined, options.maxAttachmentBytes))
68
+ .filter((attachment) => attachment !== undefined);
69
+ return {
70
+ ...envelope,
71
+ subject: parsed.subject?.trim() ?? envelope.subject,
72
+ ...(parsed.text !== undefined && { text: parsed.text }),
73
+ ...(parsed.html !== undefined && { html: parsed.html }),
74
+ headers,
75
+ attachments,
76
+ authentication: headerAuthentication(headers, domainOf(envelope.from?.address ?? ''), {
77
+ source: 'imap',
78
+ ...(options.trustedAuthservIds && { trustedAuthservIds: options.trustedAuthservIds }),
79
+ }),
80
+ raw: parsed,
81
+ };
82
+ }
83
+ //# sourceMappingURL=mime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime.js","sourceRoot":"","sources":["../../../src/channels/email/mime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /** One part of a `multipart/form-data` body, its content as received. */
2
+ export interface FormPart {
3
+ name: string;
4
+ filename?: string;
5
+ contentType?: string;
6
+ data: Buffer;
7
+ }
8
+ /** The fields of a webhook form, by name: text decoded on demand, files as bytes. */
9
+ export interface FormFields {
10
+ /** The field decoded as text, in `charset` (UTF-8 by default) */
11
+ text(name: string, charset?: string): string | undefined;
12
+ /** A field with its bytes, for files */
13
+ part(name: string): FormPart | undefined;
14
+ /** Every text field, decoded as UTF-8, for `ChannelMessage.raw` */
15
+ entries(): Record<string, string>;
16
+ }
17
+ /**
18
+ * A `multipart/form-data` body split into its parts, keeping each part's bytes, so a field sent
19
+ * in another character set than UTF-8 (as SendGrid's Inbound Parse does) can be decoded in its
20
+ * own. Linear in the size of the body.
21
+ */
22
+ export declare function parseMultipart(body: Buffer, boundary: string): FormPart[];
23
+ /**
24
+ * The fields of a form body: `multipart/form-data` split by its boundary, or
25
+ * `application/x-www-form-urlencoded`. Throws when the content type is neither.
26
+ */
27
+ export declare function readFormFields(raw: string | Uint8Array, contentType: string): FormFields;
28
+ //# sourceMappingURL=multipart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../../../src/channels/email/multipart.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qFAAqF;AACrF,MAAM,WAAW,UAAU;IACzB,iEAAiE;IACjE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACzD,wCAAwC;IACxC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzC,mEAAmE;IACnE,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AA6BD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE,CA8BzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CAkCxF"}
@@ -0,0 +1,102 @@
1
+ function decode(data, charset) {
2
+ try {
3
+ return new TextDecoder((charset ?? 'utf-8').trim().toLowerCase()).decode(data);
4
+ }
5
+ catch {
6
+ return new TextDecoder('utf-8').decode(data);
7
+ }
8
+ }
9
+ function headerParameter(header, name) {
10
+ const match = new RegExp(`;\\s*${name}\\*?=(?:"((?:[^"\\\\]|\\\\.)*)"|([^;\\s]+))`, 'i').exec(header);
11
+ const value = match?.[1] ?? match?.[2];
12
+ return value?.replace(/\\(.)/g, '$1');
13
+ }
14
+ /** The trimmed value of the part header `name` (lower case), scanned line by line */
15
+ function partHeader(headers, name) {
16
+ for (const line of headers.split('\r\n')) {
17
+ const colon = line.indexOf(':');
18
+ if (colon !== -1 && line.slice(0, colon).trim().toLowerCase() === name) {
19
+ return line.slice(colon + 1).trim();
20
+ }
21
+ }
22
+ return undefined;
23
+ }
24
+ /**
25
+ * A `multipart/form-data` body split into its parts, keeping each part's bytes, so a field sent
26
+ * in another character set than UTF-8 (as SendGrid's Inbound Parse does) can be decoded in its
27
+ * own. Linear in the size of the body.
28
+ */
29
+ export function parseMultipart(body, boundary) {
30
+ const delimiter = Buffer.from(`--${boundary}`);
31
+ const parts = [];
32
+ let start = body.indexOf(delimiter);
33
+ while (start !== -1) {
34
+ const afterDelimiter = start + delimiter.length;
35
+ if (body.subarray(afterDelimiter, afterDelimiter + 2).toString() === '--')
36
+ break;
37
+ const headersStart = body.indexOf('\r\n', afterDelimiter);
38
+ if (headersStart === -1)
39
+ break;
40
+ const headersEnd = body.indexOf('\r\n\r\n', headersStart);
41
+ if (headersEnd === -1)
42
+ break;
43
+ const next = body.indexOf(delimiter, headersEnd + 4);
44
+ if (next === -1)
45
+ break;
46
+ const contentEnd = body[next - 2] === 0x0d && body[next - 1] === 0x0a ? next - 2 : next;
47
+ const headers = body.subarray(headersStart + 2, headersEnd).toString('utf-8');
48
+ const disposition = partHeader(headers, 'content-disposition') ?? '';
49
+ const name = headerParameter(disposition, 'name');
50
+ if (name !== undefined) {
51
+ const filename = headerParameter(disposition, 'filename');
52
+ const contentType = partHeader(headers, 'content-type');
53
+ parts.push({
54
+ name,
55
+ ...(filename !== undefined && { filename }),
56
+ ...(contentType && { contentType }),
57
+ data: body.subarray(headersEnd + 4, contentEnd),
58
+ });
59
+ }
60
+ start = next;
61
+ }
62
+ return parts;
63
+ }
64
+ /**
65
+ * The fields of a form body: `multipart/form-data` split by its boundary, or
66
+ * `application/x-www-form-urlencoded`. Throws when the content type is neither.
67
+ */
68
+ export function readFormFields(raw, contentType) {
69
+ const body = typeof raw === 'string' ? Buffer.from(raw, 'utf-8') : Buffer.from(raw);
70
+ if (/^application\/x-www-form-urlencoded/i.test(contentType)) {
71
+ const params = new URLSearchParams(body.toString('utf-8'));
72
+ return {
73
+ text: (name) => params.get(name) ?? undefined,
74
+ part: (name) => {
75
+ const value = params.get(name);
76
+ return value === null ? undefined : { name, data: Buffer.from(value, 'utf-8') };
77
+ },
78
+ entries: () => Object.fromEntries(params),
79
+ };
80
+ }
81
+ const boundary = /^multipart\/form-data/i.test(contentType)
82
+ ? headerParameter(contentType, 'boundary')
83
+ : undefined;
84
+ if (!boundary)
85
+ throw new Error('Expected a form body');
86
+ const byName = new Map();
87
+ for (const part of parseMultipart(body, boundary)) {
88
+ if (!byName.has(part.name))
89
+ byName.set(part.name, part);
90
+ }
91
+ return {
92
+ text: (name, charset) => {
93
+ const part = byName.get(name);
94
+ return part && part.filename === undefined ? decode(part.data, charset) : undefined;
95
+ },
96
+ part: (name) => byName.get(name),
97
+ entries: () => Object.fromEntries([...byName.values()]
98
+ .filter((part) => part.filename === undefined)
99
+ .map((part) => [part.name, decode(part.data, undefined)])),
100
+ };
101
+ }
102
+ //# sourceMappingURL=multipart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipart.js","sourceRoot":"","sources":["../../../src/channels/email/multipart.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { type EmailHeaders } from './address.js';
2
+ import { type SenderAuthentication } from './auth.js';
3
+ import type { FormFields } from './multipart.js';
4
+ import { type InboundEmail, type RawEmailOptions } from './mime.js';
5
+ /** The email providers whose inbound webhooks the channel reads. */
6
+ export type EmailProvider = 'mailgun' | 'postmark' | 'sendgrid';
7
+ /** A webhook request, as any HTTP server hands it over. */
8
+ export interface EmailWebhookRequest {
9
+ method: string;
10
+ /** The query string parameters, where a secret token may be */
11
+ query?: Record<string, string | undefined>;
12
+ headers: Record<string, string | string[] | undefined>;
13
+ /** The body exactly as received, which Mailgun's signature covers in JSON mode */
14
+ rawBody?: string | Uint8Array;
15
+ }
16
+ export interface EmailWebhookResponse {
17
+ status: number;
18
+ body: string;
19
+ }
20
+ /** A header by its name in any letter case, as HTTP header names are. */
21
+ export declare function requestHeader(headers: EmailWebhookRequest['headers'], name: string): string | undefined;
22
+ export declare function bodyText(raw: string | Uint8Array): string;
23
+ export declare function isForm(contentType: string | undefined): boolean;
24
+ /**
25
+ * Mailgun's verdict, from the headers Mailgun adds to a received message: `X-Mailgun-Spf` for the
26
+ * envelope sender and `X-Mailgun-Dkim-Check-Result`. A message with more than one copy of either
27
+ * fails, since the sender may have added one. Mailgun does not say which signature its DKIM
28
+ * result is for, so a DKIM pass counts only when the message carries exactly one signature and
29
+ * it is for the author's domain.
30
+ */
31
+ export declare function mailgunAuthentication(headers: EmailHeaders, fromDomain: string, envelopeSender: string | undefined): SenderAuthentication;
32
+ /** A Mailgun route's form post (`forward()` to a URL), as an inbound email. */
33
+ export declare function mailgunFormEmail(fields: FormFields, options: RawEmailOptions): Promise<InboundEmail>;
34
+ /** A Mailgun route's JSON post (a `forward()` URL ending in `json`), as an inbound email. */
35
+ export declare function mailgunJsonEmail(payload: unknown, options: RawEmailOptions): Promise<InboundEmail>;
36
+ /** Postmark's inbound webhook JSON, as an inbound email. */
37
+ export declare function postmarkEmail(payload: unknown, options: RawEmailOptions): InboundEmail;
38
+ /**
39
+ * SendGrid's verdict: the `dkim` field (`{@example.com : pass}`, one entry per signature) and
40
+ * the `SPF` field for the envelope sender.
41
+ */
42
+ export declare function sendgridAuthentication(dkim: string | undefined, spf: string | undefined, envelopeFrom: string | undefined, fromDomain: string): SenderAuthentication;
43
+ /**
44
+ * A SendGrid Inbound Parse post (parsed, or raw with the whole message in `email`). SendGrid
45
+ * posts each parsed field in the character set it was written in and names them in `charsets`,
46
+ * so the fields are decoded by it.
47
+ */
48
+ export declare function sendgridEmail(fields: FormFields, options: RawEmailOptions): Promise<InboundEmail>;
49
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../../src/channels/email/providers.ts"],"names":[],"mappings":"AAEA,OAAO,EAUL,KAAK,YAAY,EAElB,MAAM,WAAW,CAAC;AACnB,OAAO,EAA+C,KAAK,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAChG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,QAAQ,CAAC;AAEhB,oEAAoE;AACpE,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEhE,2DAA2D;AAC3D,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAC3B,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC,EACvC,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAKpB;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAEzD;AAED,wBAAgB,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE/D;AAyDD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,oBAAoB,CAiBtB;AAkDD,+EAA+E;AAC/E,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,YAAY,CAAC,CAgBvB;AAiBD,6FAA6F;AAC7F,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,YAAY,CAAC,CAwBvB;AAsBD,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,GAAG,YAAY,CAwCtF;AAOD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,UAAU,EAAE,MAAM,GACjB,oBAAoB,CAwBtB;AAID;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,YAAY,CAAC,CA6CvB"}
@@ -0,0 +1,292 @@
1
+ import { z } from 'zod';
2
+ import { alignedDomains, domainOf, headersOf, messageIdOf, messageIdsOf, isAddress, normalizeAddress, parseHeaderBlock, parseMailbox, } from './address.js';
3
+ import { combineAuthentication, headerAuthentication } from './auth.js';
4
+ import { attachmentOf, envelopeOf, parseRawEmail, } from './mime.js';
5
+ /** A header by its name in any letter case, as HTTP header names are. */
6
+ export function requestHeader(headers, name) {
7
+ const wanted = name.toLowerCase();
8
+ const key = Object.keys(headers).find((candidate) => candidate.toLowerCase() === wanted);
9
+ const value = key === undefined ? undefined : headers[key];
10
+ return Array.isArray(value) ? value[0] : value;
11
+ }
12
+ export function bodyText(raw) {
13
+ return typeof raw === 'string' ? raw : Buffer.from(raw).toString('utf-8');
14
+ }
15
+ export function isForm(contentType) {
16
+ return /^(multipart\/form-data|application\/x-www-form-urlencoded)/i.test(contentType ?? '');
17
+ }
18
+ /** The attachment a form part holds, typed by `info` where the provider lists it. */
19
+ function formAttachment(fields, name, maxBytes, info) {
20
+ const part = fields.part(name);
21
+ if (!part)
22
+ return undefined;
23
+ return attachmentOf(new Uint8Array(part.data), info?.type ?? part.contentType ?? 'application/octet-stream', info?.filename ?? part.filename, maxBytes);
24
+ }
25
+ /** A stand-in `Message-ID` for a message that has none, stable for the same message. */
26
+ function fallbackMessageId(provider, id) {
27
+ return `<${id.replace(/[<>\s]/g, '')}@${provider}.invalid>`;
28
+ }
29
+ const HeaderPairsSchema = z.array(z.tuple([z.string(), z.unknown()]).rest(z.unknown()));
30
+ function headerPairs(value) {
31
+ const parsed = HeaderPairsSchema.safeParse(typeof value === 'string' ? safeJson(value) : value);
32
+ if (!parsed.success)
33
+ return [];
34
+ return parsed.data.map(([name, headerValue]) => [name.toLowerCase(), String(headerValue)]);
35
+ }
36
+ function safeJson(text) {
37
+ try {
38
+ return JSON.parse(text);
39
+ }
40
+ catch {
41
+ return undefined;
42
+ }
43
+ }
44
+ /** The domain of each `DKIM-Signature` header, by its `d=` tag. */
45
+ function signingDomains(headers) {
46
+ return headersOf(headers, 'dkim-signature')
47
+ .map((value) => /(?:^|;)\s*d\s*=\s*([^;\s]+)/i.exec(value)?.[1]?.toLowerCase())
48
+ .filter((domain) => !!domain);
49
+ }
50
+ /**
51
+ * The value of a header the provider adds, or `fail` when the message carries more than one copy:
52
+ * the sender may have added one, and which is the provider's own cannot be told.
53
+ */
54
+ function providerHeader(headers, name) {
55
+ const values = headersOf(headers, name);
56
+ if (values.length > 1)
57
+ return 'duplicate';
58
+ return values[0]?.trim().toLowerCase();
59
+ }
60
+ /**
61
+ * Mailgun's verdict, from the headers Mailgun adds to a received message: `X-Mailgun-Spf` for the
62
+ * envelope sender and `X-Mailgun-Dkim-Check-Result`. A message with more than one copy of either
63
+ * fails, since the sender may have added one. Mailgun does not say which signature its DKIM
64
+ * result is for, so a DKIM pass counts only when the message carries exactly one signature and
65
+ * it is for the author's domain.
66
+ */
67
+ export function mailgunAuthentication(headers, fromDomain, envelopeSender) {
68
+ const spf = providerHeader(headers, 'x-mailgun-spf');
69
+ const dkim = providerHeader(headers, 'x-mailgun-dkim-check-result');
70
+ if (spf === 'duplicate' || dkim === 'duplicate')
71
+ return 'fail';
72
+ const verdicts = [];
73
+ if (spf) {
74
+ const senderDomain = envelopeSender ? domainOf(envelopeSender) : '';
75
+ if (spf === 'pass' && alignedDomains(senderDomain, fromDomain))
76
+ verdicts.push('pass');
77
+ else if (spf !== 'neutral' && spf !== 'none')
78
+ verdicts.push('fail');
79
+ }
80
+ if (dkim) {
81
+ const domains = signingDomains(headers);
82
+ if (dkim === 'pass' && domains.length === 1 && alignedDomains(domains[0], fromDomain)) {
83
+ verdicts.push('pass');
84
+ }
85
+ else
86
+ verdicts.push('fail');
87
+ }
88
+ return combineAuthentication(...verdicts);
89
+ }
90
+ async function mailgunEmailOf(fields, raw, options) {
91
+ const mime = fields.get('body-mime');
92
+ const sender = fields.get('sender');
93
+ if (mime) {
94
+ const parsed = await parseRawEmail(mime, options);
95
+ const headers = fields.headers.length ? fields.headers : parsed.headers;
96
+ return {
97
+ ...parsed,
98
+ authentication: mailgunAuthentication(headers, domainOf(parsed.from?.address ?? ''), sender),
99
+ raw,
100
+ };
101
+ }
102
+ const headers = fields.headers;
103
+ const envelope = envelopeOf(headers);
104
+ const from = envelope.from ?? parseMailbox(fields.get('from') ?? fields.get('From'));
105
+ const messageId = envelope.messageId ?? messageIdOf(fields.get('Message-Id') ?? fields.get('message-id'));
106
+ const inReplyTo = envelope.inReplyTo ?? messageIdOf(fields.get('In-Reply-To'));
107
+ const references = envelope.references.length
108
+ ? envelope.references
109
+ : messageIdsOf(fields.get('References'));
110
+ const text = fields.get('body-plain');
111
+ const html = fields.get('body-html');
112
+ return {
113
+ ...(messageId && { messageId }),
114
+ ...(inReplyTo && { inReplyTo }),
115
+ references,
116
+ ...(from && { from }),
117
+ subject: envelope.subject || (fields.get('subject') ?? '').trim(),
118
+ ...(text !== undefined && { text }),
119
+ ...(html !== undefined && { html }),
120
+ headers,
121
+ attachments: fields.attachments,
122
+ authentication: mailgunAuthentication(headers, domainOf(from?.address ?? ''), sender),
123
+ raw,
124
+ };
125
+ }
126
+ /** A Mailgun route's form post (`forward()` to a URL), as an inbound email. */
127
+ export async function mailgunFormEmail(fields, options) {
128
+ const count = Number(fields.text('attachment-count') ?? 0);
129
+ const attachments = [];
130
+ for (let i = 1; i <= Math.min(count, 100); i++) {
131
+ const attachment = formAttachment(fields, `attachment-${i}`, options.maxAttachmentBytes);
132
+ if (attachment)
133
+ attachments.push(attachment);
134
+ }
135
+ return mailgunEmailOf({
136
+ get: (name) => fields.text(name),
137
+ headers: headerPairs(fields.text('message-headers')),
138
+ attachments,
139
+ }, fields.entries(), options);
140
+ }
141
+ const MailgunJsonSchema = z
142
+ .object({
143
+ 'message-headers': z.unknown().optional(),
144
+ attachments: z
145
+ .array(z.object({
146
+ filename: z.string().optional(),
147
+ 'content-type': z.string().optional(),
148
+ content: z.string(),
149
+ }))
150
+ .optional(),
151
+ })
152
+ .catchall(z.unknown());
153
+ /** A Mailgun route's JSON post (a `forward()` URL ending in `json`), as an inbound email. */
154
+ export async function mailgunJsonEmail(payload, options) {
155
+ const body = MailgunJsonSchema.parse(payload);
156
+ const attachments = (body.attachments ?? [])
157
+ .map((attachment) => attachmentOf(Buffer.from(attachment.content, 'base64'), attachment['content-type'] ?? 'application/octet-stream', attachment.filename, options.maxAttachmentBytes))
158
+ .filter((attachment) => attachment !== undefined);
159
+ return mailgunEmailOf({
160
+ get: (name) => {
161
+ const value = body[name];
162
+ return typeof value === 'string' ? value : undefined;
163
+ },
164
+ headers: headerPairs(body['message-headers']),
165
+ attachments,
166
+ }, payload, options);
167
+ }
168
+ const PostmarkSchema = z.object({
169
+ MessageID: z.string().optional(),
170
+ From: z.string().optional(),
171
+ FromName: z.string().optional(),
172
+ FromFull: z.object({ Email: z.string(), Name: z.string().optional() }).optional(),
173
+ Subject: z.string().optional(),
174
+ TextBody: z.string().optional(),
175
+ HtmlBody: z.string().optional(),
176
+ Headers: z.array(z.object({ Name: z.string(), Value: z.string() })).optional(),
177
+ Attachments: z
178
+ .array(z.object({
179
+ Name: z.string().optional(),
180
+ Content: z.string(),
181
+ ContentType: z.string().optional(),
182
+ }))
183
+ .optional(),
184
+ });
185
+ /** Postmark's inbound webhook JSON, as an inbound email. */
186
+ export function postmarkEmail(payload, options) {
187
+ const body = PostmarkSchema.parse(payload);
188
+ const headers = (body.Headers ?? []).map(({ Name, Value }) => [
189
+ Name.toLowerCase(),
190
+ Value,
191
+ ]);
192
+ const envelope = envelopeOf(headers);
193
+ const fromAddress = normalizeAddress(body.FromFull?.Email ?? body.From ?? '');
194
+ const fromName = (body.FromFull?.Name || body.FromName || '').trim();
195
+ const from = isAddress(fromAddress)
196
+ ? { address: fromAddress, ...(fromName && { name: fromName }) }
197
+ : envelope.from;
198
+ const messageId = envelope.messageId ??
199
+ (body.MessageID ? fallbackMessageId('postmark', body.MessageID) : undefined);
200
+ const attachments = (body.Attachments ?? [])
201
+ .map((attachment) => attachmentOf(Buffer.from(attachment.Content, 'base64'), attachment.ContentType ?? 'application/octet-stream', attachment.Name, options.maxAttachmentBytes))
202
+ .filter((attachment) => attachment !== undefined);
203
+ return {
204
+ ...envelope,
205
+ ...(messageId && { messageId }),
206
+ ...(from && { from }),
207
+ subject: (body.Subject ?? envelope.subject).trim(),
208
+ ...(body.TextBody !== undefined && { text: body.TextBody }),
209
+ ...(body.HtmlBody !== undefined && { html: body.HtmlBody }),
210
+ headers,
211
+ attachments,
212
+ authentication: headerAuthentication(headers, domainOf(from?.address ?? ''), {
213
+ source: 'postmark',
214
+ ...(options.trustedAuthservIds && { trustedAuthservIds: options.trustedAuthservIds }),
215
+ }),
216
+ raw: payload,
217
+ };
218
+ }
219
+ const AttachmentInfoSchema = z.record(z.string(), z.object({ filename: z.string().optional(), type: z.string().optional() }));
220
+ /**
221
+ * SendGrid's verdict: the `dkim` field (`{@example.com : pass}`, one entry per signature) and
222
+ * the `SPF` field for the envelope sender.
223
+ */
224
+ export function sendgridAuthentication(dkim, spf, envelopeFrom, fromDomain) {
225
+ const verdicts = [];
226
+ if (dkim) {
227
+ const entries = [...dkim.matchAll(/@?((?:[a-z0-9-]+\.)+[a-z]{2,})\s*:\s*([a-z]+)/gi)];
228
+ if (entries.some(([, domain, result]) => result.toLowerCase() === 'pass' && alignedDomains(domain, fromDomain))) {
229
+ verdicts.push('pass');
230
+ }
231
+ else if (entries.length > 0)
232
+ verdicts.push('fail');
233
+ }
234
+ const spfResult = spf?.trim().toLowerCase();
235
+ if (spfResult) {
236
+ if (spfResult === 'pass' &&
237
+ envelopeFrom &&
238
+ alignedDomains(domainOf(envelopeFrom), fromDomain)) {
239
+ verdicts.push('pass');
240
+ }
241
+ else if (spfResult !== 'neutral' && spfResult !== 'none')
242
+ verdicts.push('fail');
243
+ }
244
+ return combineAuthentication(...verdicts);
245
+ }
246
+ const CharsetsSchema = z.record(z.string(), z.string());
247
+ /**
248
+ * A SendGrid Inbound Parse post (parsed, or raw with the whole message in `email`). SendGrid
249
+ * posts each parsed field in the character set it was written in and names them in `charsets`,
250
+ * so the fields are decoded by it.
251
+ */
252
+ export async function sendgridEmail(fields, options) {
253
+ const charsets = CharsetsSchema.safeParse(safeJson(fields.text('charsets') ?? ''));
254
+ const text = (name) => fields.text(name, charsets.success ? charsets.data[name] : undefined);
255
+ const envelopeFrom = z
256
+ .object({ from: z.string().optional() })
257
+ .safeParse(safeJson(text('envelope') ?? ''));
258
+ const sender = envelopeFrom.success ? envelopeFrom.data.from : undefined;
259
+ const raw = fields.entries();
260
+ const authenticate = (fromAddress) => sendgridAuthentication(text('dkim'), text('SPF'), sender, domainOf(fromAddress ?? ''));
261
+ const mime = fields.part('email');
262
+ if (mime && mime.data.length > 0) {
263
+ const parsed = await parseRawEmail(new Uint8Array(mime.data), options);
264
+ return { ...parsed, authentication: authenticate(parsed.from?.address), raw };
265
+ }
266
+ const headers = parseHeaderBlock(text('headers') ?? '');
267
+ const envelope = envelopeOf(headers);
268
+ const from = envelope.from ?? parseMailbox(text('from'));
269
+ const info = AttachmentInfoSchema.safeParse(safeJson(text('attachment-info') ?? ''));
270
+ const count = Number(text('attachments') ?? 0);
271
+ const attachments = [];
272
+ for (let i = 1; i <= Math.min(count, 100); i++) {
273
+ const name = `attachment${i}`;
274
+ const attachment = formAttachment(fields, name, options.maxAttachmentBytes, info.success ? info.data[name] : undefined);
275
+ if (attachment)
276
+ attachments.push(attachment);
277
+ }
278
+ const body = text('text');
279
+ const html = text('html');
280
+ return {
281
+ ...envelope,
282
+ ...(from && { from }),
283
+ subject: envelope.subject || (text('subject') ?? '').trim(),
284
+ ...(body !== undefined && { text: body }),
285
+ ...(html !== undefined && { html }),
286
+ headers,
287
+ attachments,
288
+ authentication: authenticate(from?.address),
289
+ raw,
290
+ };
291
+ }
292
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../../src/channels/email/providers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The new text of a reply, without what it quotes: the history after an attribution line
3
+ * (`On ... wrote:` and its translations, `-----Original Message-----`, an Outlook `From:` and
4
+ * `Sent:` block), a trailing block of `>` quotes, the signature after a `-- ` line and a
5
+ * `Sent from my ...` line. Quotes the writer answers between are kept, as they say what each
6
+ * answer is about. Returns the text unchanged when stripping would leave nothing.
7
+ */
8
+ export declare function stripQuotedReply(text: string): string;
9
+ //# sourceMappingURL=reply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reply.d.ts","sourceRoot":"","sources":["../../../src/channels/email/reply.ts"],"names":[],"mappings":"AAsGA;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsBrD"}