@cogitator-ai/channels 0.16.0 → 0.17.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 (69) hide show
  1. package/README.md +53 -12
  2. package/dist/assistant-config.d.ts +40 -0
  3. package/dist/assistant-config.d.ts.map +1 -1
  4. package/dist/assistant-config.js +66 -0
  5. package/dist/assistant-config.js.map +1 -1
  6. package/dist/channels/email/address.d.ts +44 -0
  7. package/dist/channels/email/address.d.ts.map +1 -0
  8. package/dist/channels/email/address.js +211 -0
  9. package/dist/channels/email/address.js.map +1 -0
  10. package/dist/channels/email/auth.d.ts +59 -0
  11. package/dist/channels/email/auth.d.ts.map +1 -0
  12. package/dist/channels/email/auth.js +212 -0
  13. package/dist/channels/email/auth.js.map +1 -0
  14. package/dist/channels/email/channel.d.ts +256 -0
  15. package/dist/channels/email/channel.d.ts.map +1 -0
  16. package/dist/channels/email/channel.js +701 -0
  17. package/dist/channels/email/channel.js.map +1 -0
  18. package/dist/channels/email/errors.d.ts +11 -0
  19. package/dist/channels/email/errors.d.ts.map +1 -0
  20. package/dist/channels/email/errors.js +13 -0
  21. package/dist/channels/email/errors.js.map +1 -0
  22. package/dist/channels/email/imap.d.ts +125 -0
  23. package/dist/channels/email/imap.d.ts.map +1 -0
  24. package/dist/channels/email/imap.js +309 -0
  25. package/dist/channels/email/imap.js.map +1 -0
  26. package/dist/channels/email/index.d.ts +7 -0
  27. package/dist/channels/email/index.d.ts.map +1 -0
  28. package/dist/channels/email/index.js +3 -0
  29. package/dist/channels/email/index.js.map +1 -0
  30. package/dist/channels/email/mime.d.ts +71 -0
  31. package/dist/channels/email/mime.d.ts.map +1 -0
  32. package/dist/channels/email/mime.js +83 -0
  33. package/dist/channels/email/mime.js.map +1 -0
  34. package/dist/channels/email/multipart.d.ts +28 -0
  35. package/dist/channels/email/multipart.d.ts.map +1 -0
  36. package/dist/channels/email/multipart.js +102 -0
  37. package/dist/channels/email/multipart.js.map +1 -0
  38. package/dist/channels/email/providers.d.ts +49 -0
  39. package/dist/channels/email/providers.d.ts.map +1 -0
  40. package/dist/channels/email/providers.js +292 -0
  41. package/dist/channels/email/providers.js.map +1 -0
  42. package/dist/channels/email/reply.d.ts +9 -0
  43. package/dist/channels/email/reply.d.ts.map +1 -0
  44. package/dist/channels/email/reply.js +122 -0
  45. package/dist/channels/email/reply.js.map +1 -0
  46. package/dist/formatters/html.d.ts +16 -0
  47. package/dist/formatters/html.d.ts.map +1 -0
  48. package/dist/formatters/html.js +535 -0
  49. package/dist/formatters/html.js.map +1 -0
  50. package/dist/formatters/markdown.d.ts.map +1 -1
  51. package/dist/formatters/markdown.js +1 -0
  52. package/dist/formatters/markdown.js.map +1 -1
  53. package/dist/gateway.d.ts +23 -1
  54. package/dist/gateway.d.ts.map +1 -1
  55. package/dist/gateway.js +104 -14
  56. package/dist/gateway.js.map +1 -1
  57. package/dist/inbound-debounce.d.ts +4 -1
  58. package/dist/inbound-debounce.d.ts.map +1 -1
  59. package/dist/inbound-debounce.js +4 -2
  60. package/dist/inbound-debounce.js.map +1 -1
  61. package/dist/index.d.ts +3 -1
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +3 -1
  64. package/dist/index.js.map +1 -1
  65. package/dist/runtime-builder.d.ts +9 -0
  66. package/dist/runtime-builder.d.ts.map +1 -1
  67. package/dist/runtime-builder.js +110 -0
  68. package/dist/runtime-builder.js.map +1 -1
  69. package/package.json +25 -8
@@ -0,0 +1,59 @@
1
+ import { type EmailHeaders } from './address.js';
2
+ /**
3
+ * What the receiving side found about the sender: `pass` when DKIM, SPF or DMARC passed for a
4
+ * domain aligned with the `From` address, `fail` when results were reported and none of them
5
+ * did, `none` when nothing was reported.
6
+ */
7
+ export type SenderAuthentication = 'pass' | 'fail' | 'none';
8
+ /**
9
+ * Combines the results of one source, such as the methods of one `Authentication-Results`:
10
+ * any pass passes (mail forwarded on breaks SPF but keeps DKIM), else any fail fails.
11
+ */
12
+ export declare function combineAuthentication(...verdicts: readonly SenderAuthentication[]): SenderAuthentication;
13
+ /**
14
+ * The verdict of one `Authentication-Results` header (RFC 8601) for the author domain
15
+ * `fromDomain`, and its authserv-id. A DMARC result for the `From` domain decides when there is
16
+ * one: DMARC already weighs DKIM and SPF alignment. Otherwise a DKIM or SPF pass for an aligned
17
+ * domain passes, and any definite result (a fail, or a pass for another domain, as a spoofer
18
+ * signing with a domain of its own gets) fails, while `none` or `neutral` say nothing. Parts
19
+ * are split outside quoted strings, so an address like `"a;dkim=pass"@evil.example` stays one
20
+ * value.
21
+ */
22
+ export declare function parseAuthenticationResults(value: string, fromDomain: string): {
23
+ authservId: string;
24
+ verdict: SenderAuthentication;
25
+ };
26
+ /** Where the sender authentication of a message's headers comes from, and whom to trust. */
27
+ export interface HeaderAuthenticationOptions {
28
+ /**
29
+ * `imap`: the `Authentication-Results` of `trustedAuthservIds`. `postmark`: the SpamAssassin
30
+ * `X-Spam-Tests` Postmark adds, whose earlier copies SpamAssassin removes, and the
31
+ * `Authentication-Results` of `trustedAuthservIds`.
32
+ */
33
+ source: 'imap' | 'postmark';
34
+ /** The authserv-ids (the receiving servers) whose `Authentication-Results` count */
35
+ trustedAuthservIds?: readonly string[];
36
+ }
37
+ /**
38
+ * Combines the verdicts of independent sources: a fail of any of them fails, since one source
39
+ * passing does not undo what another found, then any pass passes.
40
+ */
41
+ export declare function combineSources(...verdicts: readonly SenderAuthentication[]): SenderAuthentication;
42
+ /**
43
+ * The sender verdict a message's headers carry, for the author domain `fromDomain`. A sender can
44
+ * add any header, so only those the receiving side wrote count: the topmost
45
+ * `Authentication-Results` of one of `trustedAuthservIds` (without them none is trusted), and
46
+ * Postmark's `X-Spam-Tests`. A fail of either source fails.
47
+ */
48
+ export declare function headerAuthentication(headers: EmailHeaders, fromDomain: string, options: HeaderAuthenticationOptions): SenderAuthentication;
49
+ /**
50
+ * Compares two secrets in constant time for their contents: unequal lengths still run one full
51
+ * comparison (of the expected secret with itself), so only the length of the secret can show.
52
+ */
53
+ export declare function secretsEqual(given: string, expected: string): boolean;
54
+ /**
55
+ * Whether `signature` is the hex HMAC SHA-256 of `timestamp` and `token` with Mailgun's webhook
56
+ * signing key, as Mailgun signs the requests of its routes (in JSON mode `token` is the body).
57
+ */
58
+ export declare function verifyMailgunSignature(timestamp: string, token: string | Uint8Array, signature: string | undefined, signingKey: string): boolean;
59
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/channels/email/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5D;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,QAAQ,EAAE,SAAS,oBAAoB,EAAE,GAC3C,oBAAoB,CAItB;AAyFD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,CAqBvD;AAED,4FAA4F;AAC5F,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC;IAC5B,oFAAoF;IACpF,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,QAAQ,EAAE,SAAS,oBAAoB,EAAE,GAAG,oBAAoB,CAIjG;AAgBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,2BAA2B,GACnC,oBAAoB,CAatB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKrE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,UAAU,EAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,EAAE,MAAM,GACjB,OAAO,CAOT"}
@@ -0,0 +1,212 @@
1
+ import { createHmac, timingSafeEqual } from 'node:crypto';
2
+ import { alignedDomains, headersOf } from './address.js';
3
+ /**
4
+ * Combines the results of one source, such as the methods of one `Authentication-Results`:
5
+ * any pass passes (mail forwarded on breaks SPF but keeps DKIM), else any fail fails.
6
+ */
7
+ export function combineAuthentication(...verdicts) {
8
+ if (verdicts.includes('pass'))
9
+ return 'pass';
10
+ if (verdicts.includes('fail'))
11
+ return 'fail';
12
+ return 'none';
13
+ }
14
+ /** Results that say something about the sender, unlike `none`, `neutral` or `temperror`. */
15
+ const DEFINITE = new Set(['pass', 'fail', 'softfail', 'permerror', 'hardfail']);
16
+ /**
17
+ * The text of a header without its comments, in one pass that knows quoted strings and `\`
18
+ * escapes: a `(` inside quotes is text, and an escaped quote does not end them.
19
+ */
20
+ function withoutComments(text) {
21
+ let out = '';
22
+ let depth = 0;
23
+ let quoted = false;
24
+ for (let i = 0; i < text.length; i++) {
25
+ const char = text[i];
26
+ if (char === '\\' && i + 1 < text.length) {
27
+ if (depth === 0)
28
+ out += char + text[i + 1];
29
+ i++;
30
+ continue;
31
+ }
32
+ if (depth === 0 && char === '"')
33
+ quoted = !quoted;
34
+ if (!quoted && char === '(')
35
+ depth++;
36
+ else if (!quoted && char === ')' && depth > 0)
37
+ depth--;
38
+ else if (depth === 0)
39
+ out += char;
40
+ }
41
+ return out;
42
+ }
43
+ /** `text` split at `separator` and at whitespace too when `alsoSpace`, never inside quotes. */
44
+ function splitOutsideQuotes(text, separator, alsoSpace = false) {
45
+ const parts = [];
46
+ let current = '';
47
+ let quoted = false;
48
+ for (let i = 0; i < text.length; i++) {
49
+ const char = text[i];
50
+ if (char === '\\' && i + 1 < text.length) {
51
+ current += char + text[++i];
52
+ continue;
53
+ }
54
+ if (char === '"')
55
+ quoted = !quoted;
56
+ if (!quoted && (char === separator || (alsoSpace && /\s/.test(char)))) {
57
+ if (current)
58
+ parts.push(current);
59
+ current = '';
60
+ }
61
+ else
62
+ current += char;
63
+ }
64
+ if (current)
65
+ parts.push(current);
66
+ return parts;
67
+ }
68
+ /** The results of a header, its `;`-separated parts read outside quoted strings. */
69
+ function authResultsOf(value) {
70
+ const [id = '', ...segments] = splitOutsideQuotes(withoutComments(value), ';');
71
+ const results = [];
72
+ for (const segment of segments) {
73
+ const [first = '', ...rest] = splitOutsideQuotes(segment.trim(), ' ', true);
74
+ const method = /^(dkim|spf|dmarc)=([a-z]+)$/i.exec(first);
75
+ if (!method)
76
+ continue;
77
+ const properties = new Map();
78
+ for (const token of rest) {
79
+ const equals = token.indexOf('=');
80
+ if (equals <= 0)
81
+ continue;
82
+ const name = token.slice(0, equals).toLowerCase();
83
+ if (!properties.has(name))
84
+ properties.set(name, token.slice(equals + 1));
85
+ }
86
+ results.push({ method: method[1].toLowerCase(), result: method[2].toLowerCase(), properties });
87
+ }
88
+ return { authservId: id.trim().split(/\s+/)[0]?.toLowerCase() ?? '', results };
89
+ }
90
+ /** The domain a property names: of an address (after its last `@`) or the value itself. */
91
+ function propertyDomain(result, ...names) {
92
+ for (const name of names) {
93
+ const value = result.properties.get(name);
94
+ if (!value)
95
+ continue;
96
+ const bare = value.replace(/^"|"$/g, '');
97
+ const at = bare.lastIndexOf('@');
98
+ const domain = (at === -1 ? bare : bare.slice(at + 1)).replace(/^"|"$/g, '').toLowerCase();
99
+ if (domain && !/[\s";]/.test(domain))
100
+ return domain;
101
+ }
102
+ return undefined;
103
+ }
104
+ /**
105
+ * The verdict of one `Authentication-Results` header (RFC 8601) for the author domain
106
+ * `fromDomain`, and its authserv-id. A DMARC result for the `From` domain decides when there is
107
+ * one: DMARC already weighs DKIM and SPF alignment. Otherwise a DKIM or SPF pass for an aligned
108
+ * domain passes, and any definite result (a fail, or a pass for another domain, as a spoofer
109
+ * signing with a domain of its own gets) fails, while `none` or `neutral` say nothing. Parts
110
+ * are split outside quoted strings, so an address like `"a;dkim=pass"@evil.example` stays one
111
+ * value.
112
+ */
113
+ export function parseAuthenticationResults(value, fromDomain) {
114
+ const { authservId, results } = authResultsOf(value);
115
+ const dmarc = results.find((result) => {
116
+ if (result.method !== 'dmarc')
117
+ return false;
118
+ const from = propertyDomain(result, 'header.from');
119
+ return !from || alignedDomains(from, fromDomain);
120
+ });
121
+ if (dmarc?.result === 'pass')
122
+ return { authservId, verdict: 'pass' };
123
+ if (dmarc && DEFINITE.has(dmarc.result))
124
+ return { authservId, verdict: 'fail' };
125
+ let reported = false;
126
+ for (const result of results) {
127
+ if (result.method === 'dmarc')
128
+ continue;
129
+ if (DEFINITE.has(result.result))
130
+ reported = true;
131
+ if (result.result !== 'pass')
132
+ continue;
133
+ const domain = result.method === 'dkim'
134
+ ? propertyDomain(result, 'header.d', 'header.i')
135
+ : propertyDomain(result, 'smtp.mailfrom', 'smtp.helo');
136
+ if (domain && alignedDomains(domain, fromDomain))
137
+ return { authservId, verdict: 'pass' };
138
+ }
139
+ return { authservId, verdict: reported ? 'fail' : 'none' };
140
+ }
141
+ /**
142
+ * Combines the verdicts of independent sources: a fail of any of them fails, since one source
143
+ * passing does not undo what another found, then any pass passes.
144
+ */
145
+ export function combineSources(...verdicts) {
146
+ if (verdicts.includes('fail'))
147
+ return 'fail';
148
+ if (verdicts.includes('pass'))
149
+ return 'pass';
150
+ return 'none';
151
+ }
152
+ /**
153
+ * The verdict of Postmark's SpamAssassin tests: `DKIM_VALID_AU` is a valid signature of the
154
+ * author's domain, an SPF fail or an invalid signature fails. More than one `X-Spam-Tests`
155
+ * header fails, since one of them came from the sender.
156
+ */
157
+ function spamTestsAuthentication(headers) {
158
+ const tests = headersOf(headers, 'x-spam-tests');
159
+ if (tests.length > 1)
160
+ return 'fail';
161
+ if (tests.length === 0)
162
+ return 'none';
163
+ if (/\bDKIM_VALID_AU\b/.test(tests[0]))
164
+ return 'pass';
165
+ if (/\b(SPF_FAIL|SPF_SOFTFAIL|DKIM_INVALID)\b/.test(tests[0]))
166
+ return 'fail';
167
+ return 'none';
168
+ }
169
+ /**
170
+ * The sender verdict a message's headers carry, for the author domain `fromDomain`. A sender can
171
+ * add any header, so only those the receiving side wrote count: the topmost
172
+ * `Authentication-Results` of one of `trustedAuthservIds` (without them none is trusted), and
173
+ * Postmark's `X-Spam-Tests`. A fail of either source fails.
174
+ */
175
+ export function headerAuthentication(headers, fromDomain, options) {
176
+ const verdicts = [];
177
+ const trusted = options.trustedAuthservIds?.map((id) => id.toLowerCase()) ?? [];
178
+ if (trusted.length > 0) {
179
+ for (const value of headersOf(headers, 'authentication-results')) {
180
+ const parsed = parseAuthenticationResults(value, fromDomain);
181
+ if (!trusted.includes(parsed.authservId))
182
+ continue;
183
+ verdicts.push(parsed.verdict);
184
+ break;
185
+ }
186
+ }
187
+ if (options.source === 'postmark')
188
+ verdicts.push(spamTestsAuthentication(headers));
189
+ return combineSources(...verdicts);
190
+ }
191
+ /**
192
+ * Compares two secrets in constant time for their contents: unequal lengths still run one full
193
+ * comparison (of the expected secret with itself), so only the length of the secret can show.
194
+ */
195
+ export function secretsEqual(given, expected) {
196
+ const givenBytes = Buffer.from(given);
197
+ const expectedBytes = Buffer.from(expected);
198
+ const sameLength = givenBytes.length === expectedBytes.length;
199
+ return timingSafeEqual(sameLength ? givenBytes : expectedBytes, expectedBytes) && sameLength;
200
+ }
201
+ /**
202
+ * Whether `signature` is the hex HMAC SHA-256 of `timestamp` and `token` with Mailgun's webhook
203
+ * signing key, as Mailgun signs the requests of its routes (in JSON mode `token` is the body).
204
+ */
205
+ export function verifyMailgunSignature(timestamp, token, signature, signingKey) {
206
+ if (!signature || !/^[0-9a-f]+$/i.test(signature))
207
+ return false;
208
+ const expected = Buffer.from(createHmac('sha256', signingKey).update(timestamp).update(token).digest('hex'));
209
+ const given = Buffer.from(signature.toLowerCase());
210
+ return given.length === expected.length && timingSafeEqual(given, expected);
211
+ }
212
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/channels/email/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,256 @@
1
+ import { type RequestListener } from 'node:http';
2
+ import type { Attachment, Channel, ChannelMessage, SendOptions } from '@cogitator-ai/types';
3
+ import { type EmailImapConfig } from './imap.js';
4
+ import { type InboundEmail } from './mime.js';
5
+ import { type EmailWebhookRequest, type EmailWebhookResponse } from './providers.js';
6
+ /** The header the channel puts on every mail it sends, and skips mail that carries it. */
7
+ export declare const EMAIL_LOOP_HEADER = "X-Cogitator";
8
+ /** The largest webhook body the channel's own server takes by default, in bytes. */
9
+ export declare const EMAIL_DEFAULT_MAX_BODY: number;
10
+ /** The largest attachment handed to the agent by default, in bytes. */
11
+ export declare const EMAIL_DEFAULT_MAX_ATTACHMENT: number;
12
+ /** How old a Mailgun signature may be by default, in seconds. */
13
+ export declare const MAILGUN_DEFAULT_MAX_AGE = 300;
14
+ /** Credentials for HTTP basic authentication of a webhook. */
15
+ export interface EmailBasicAuth {
16
+ username: string;
17
+ password: string;
18
+ }
19
+ /** Mailgun signs each request of a route with the webhook signing key. */
20
+ export interface MailgunWebhookConfig {
21
+ provider: 'mailgun';
22
+ /** The HTTP webhook signing key of the Mailgun account (Settings, Webhooks) */
23
+ signingKey: string;
24
+ /** How old a signature may be, in seconds (default 300). Older requests are refused as replays */
25
+ maxAge?: number;
26
+ }
27
+ /**
28
+ * Postmark and SendGrid do not sign inbound mail, so the webhook URL carries a secret: basic
29
+ * authentication (`https://user:password@host/path`) or a `token` query parameter (also taken
30
+ * from an `X-Webhook-Token` header). At least one is required.
31
+ */
32
+ export interface SecretWebhookConfig {
33
+ provider: 'postmark' | 'sendgrid';
34
+ basicAuth?: EmailBasicAuth;
35
+ token?: string;
36
+ }
37
+ export type EmailWebhookConfig = (MailgunWebhookConfig | SecretWebhookConfig) & {
38
+ /**
39
+ * Run an HTTP server of the channel's own on this port. Without it, mount `handleWebhook` or
40
+ * `webhookListener()` in a server of yours.
41
+ */
42
+ port?: number;
43
+ /** The path of the channel's own server (default `/email/webhook`) */
44
+ path?: string;
45
+ host?: string;
46
+ /** The largest body taken, in bytes (default 10 MB), larger ones get `413` */
47
+ maxBody?: number;
48
+ };
49
+ /** A mail as the channel hands it to the transport, in the shape nodemailer takes. */
50
+ export interface OutgoingEmail {
51
+ from: string | {
52
+ name: string;
53
+ address: string;
54
+ };
55
+ to: string;
56
+ subject: string;
57
+ text: string;
58
+ html?: string;
59
+ messageId: string;
60
+ inReplyTo?: string;
61
+ references?: string[];
62
+ headers: Record<string, string>;
63
+ attachments?: {
64
+ filename?: string;
65
+ content?: Buffer;
66
+ href?: string;
67
+ contentType?: string;
68
+ }[];
69
+ }
70
+ /** Anything that sends mail: a nodemailer transporter (SMTP, SES, ...) or one of your own. */
71
+ export interface EmailTransport {
72
+ sendMail(mail: OutgoingEmail): Promise<unknown>;
73
+ close?(): void;
74
+ }
75
+ /** An SMTP server the channel sends through with nodemailer. */
76
+ export interface EmailSmtpServer {
77
+ host: string;
78
+ /** Default 587, or 465 when `secure` */
79
+ port?: number;
80
+ /** TLS from the start, as on port 465 (default: true on port 465). Otherwise STARTTLS */
81
+ secure?: boolean;
82
+ auth?: {
83
+ user: string;
84
+ pass: string;
85
+ };
86
+ /** Further nodemailer SMTP options */
87
+ options?: Record<string, unknown>;
88
+ }
89
+ export type EmailSmtpConfig = EmailSmtpServer | {
90
+ transport: EmailTransport;
91
+ };
92
+ /**
93
+ * How mail is checked against the sender authentication results the receiving side reports
94
+ * (DKIM, SPF, DMARC): `when-reported` (default) drops mail whose results fail for the `From`
95
+ * domain and takes mail without results, `required` also drops mail without results, `off`
96
+ * does not look.
97
+ */
98
+ export type EmailSenderAuthPolicy = 'required' | 'when-reported' | 'off';
99
+ export interface EmailChannelConfig {
100
+ /** The bot's address: mail is sent from it, and mail from it is never answered */
101
+ address: string;
102
+ /** The display name of the mail it sends */
103
+ name?: string;
104
+ /** Other addresses of the bot, also never answered */
105
+ aliases?: string[];
106
+ /** How mail is sent */
107
+ smtp: EmailSmtpConfig;
108
+ /** Read mail from a mailbox over IMAP */
109
+ imap?: EmailImapConfig;
110
+ /** Take mail from a provider's inbound webhook: Mailgun, Postmark or SendGrid */
111
+ webhook?: EmailWebhookConfig;
112
+ /**
113
+ * Who the bot answers: addresses (`ann@example.com`), domains (`example.com`), subdomain
114
+ * wildcards (`*.example.com`) or `*` for everyone. Default: nobody, which `start()` warns
115
+ * about, since anyone can send mail and the `From` address can be forged.
116
+ */
117
+ allowFrom?: string[];
118
+ /**
119
+ * Addresses the gateway gives owner rights, also answered whatever `allowFrom` says. A `From`
120
+ * can be forged, so their mail reaches the agent only when the sender authentication passes
121
+ * for their domain, unless `senderAuth` is `off`.
122
+ */
123
+ owners?: string[];
124
+ /** See {@link EmailSenderAuthPolicy}. Default `when-reported` */
125
+ senderAuth?: EmailSenderAuthPolicy;
126
+ /**
127
+ * The authserv-ids (the first word of `Authentication-Results`, such as `mx.google.com`) of
128
+ * the servers that receive the mail, whose results count over IMAP and Postmark. A sender can
129
+ * add any header, so without them IMAP mail has no sender authentication at all.
130
+ */
131
+ trustedAuthservIds?: string[];
132
+ /** Start the text of a conversation's first mail with its subject (default true) */
133
+ includeSubject?: boolean;
134
+ /** The subject of mail that starts a conversation, such as a reminder (default `Message from <name>`) */
135
+ subject?: string;
136
+ /** The largest attachment handed to the agent, in bytes (default 10 MB), larger ones are skipped */
137
+ maxAttachmentBytes?: number;
138
+ }
139
+ /** `subject` as a reply's subject: with one `Re: `, whatever prefix it had. */
140
+ export declare function replySubject(subject: string): string;
141
+ /** Whether the mail is an automatic one: an auto-reply, a bounce, a list or bulk mailing. */
142
+ export declare function isAutomatedEmail(email: InboundEmail): boolean;
143
+ /**
144
+ * An email channel: an agent answers mail, in the thread of each mail. Mail comes from a mailbox
145
+ * over IMAP (`imapflow` and `postal-mime`), or from the inbound webhook of Mailgun, Postmark or
146
+ * SendGrid, and answers go out over SMTP (`nodemailer`) or any transport given, with
147
+ * `In-Reply-To` and `References` set, so mail clients keep them in the thread.
148
+ *
149
+ * A sender is a conversation partner: `channelId` and `userId` are the sender's address in lower
150
+ * case, and `topicId` is the thread's first `Message-ID`, so each email thread is a conversation
151
+ * of its own. Answers are Markdown, sent as HTML with a plain text alternative, and cannot be
152
+ * edited. Mail from the bot itself, mail that carries the `X-Cogitator` header the channel puts
153
+ * on what it sends, auto-replies, bounces and bulk mail are never answered.
154
+ */
155
+ export declare class EmailChannel implements Channel {
156
+ readonly type = "email";
157
+ readonly editable = false;
158
+ readonly nativeMarkdown = true;
159
+ readonly maxMessageChars: number;
160
+ private readonly config;
161
+ private readonly address;
162
+ private readonly ownAddresses;
163
+ private readonly owners;
164
+ private handler;
165
+ /** Mail handed to the gateway whose handler has not resolved yet, by `Message-ID` */
166
+ private readonly inFlight;
167
+ /** Mail of `inFlight` the gateway handed back while it was being taken */
168
+ private readonly refused;
169
+ private readonly handled;
170
+ /** Mailgun signatures seen, with their timestamps, against replays */
171
+ private readonly signatures;
172
+ /** The IMAP UID of each mail taken from the mailbox, by `Message-ID`, to mark it unread again */
173
+ private readonly uids;
174
+ private readonly threads;
175
+ /** The latest mail of each thread, by `address|root` */
176
+ private readonly latest;
177
+ private transport?;
178
+ private inbox?;
179
+ private server?;
180
+ private running;
181
+ private stopped;
182
+ constructor(config: EmailChannelConfig);
183
+ onMessage(handler: (msg: ChannelMessage) => Promise<void>): void;
184
+ start(): Promise<void>;
185
+ stop(): Promise<void>;
186
+ /** Looks for unread mail over IMAP now, besides IDLE and the poll timer. */
187
+ poll(): Promise<void>;
188
+ /**
189
+ * Takes back a mail the gateway does not answer because it stops. One it refuses while it is
190
+ * being handed over stays unread in the mailbox, and its webhook request is answered `503`, so
191
+ * the provider sends it again. One it dropped after taking it is marked unread again, so the
192
+ * next start reads it once more, or, when a webhook brought it, only logged.
193
+ */
194
+ redeliver(msg: ChannelMessage): Promise<void>;
195
+ /**
196
+ * Answers a provider's inbound webhook request: checks its signature or secret, reads the
197
+ * mail, answers at once and hands the mail to the agent after. Mount it in any HTTP server
198
+ * with the raw body unparsed. It works before `start()` too and answers `503` once stopped.
199
+ */
200
+ handleWebhook(request: EmailWebhookRequest): Promise<EmailWebhookResponse>;
201
+ /**
202
+ * A Node request listener that answers webhook requests on any path it is mounted at. Bodies
203
+ * over `webhook.maxBody` (10 MB by default) are refused with `413`.
204
+ */
205
+ webhookListener(): RequestListener;
206
+ /**
207
+ * Sends `text` to the address `channelId`. With a `replyTo` of a mail the channel saw, or the
208
+ * `topicId` of a thread, it answers in that thread (`Re:` subject, `In-Reply-To`,
209
+ * `References`), and otherwise it starts a new one. Resolves with the new mail's `Message-ID`.
210
+ */
211
+ sendText(channelId: string, text: string, options?: SendOptions): Promise<string>;
212
+ editText(): Promise<void>;
213
+ /**
214
+ * Sends a file as an attachment, its caption as the text, in the thread as `sendText` does.
215
+ * A file needs a `buffer` or an `http(s)` url, which nodemailer downloads.
216
+ */
217
+ sendFile(channelId: string, file: Attachment, options?: SendOptions): Promise<string>;
218
+ sendTyping(): Promise<void>;
219
+ private parseOptions;
220
+ private authorized;
221
+ /**
222
+ * Checks a Mailgun request's signature, age and token, and reads its mail. The signature is
223
+ * checked before the mail is read: a form is only split into its fields first, where the
224
+ * signature is.
225
+ */
226
+ private mailgunEmail;
227
+ /**
228
+ * Remembers a signature for as long as its timestamp is within the replay window: older ones
229
+ * are refused as stale anyway. Past `MAX_SIGNATURES` the oldest are forgotten.
230
+ */
231
+ private rememberSignature;
232
+ /** Whether the mail may reach the agent: by its sender, its kind and its authentication. */
233
+ private admits;
234
+ /**
235
+ * The text the agent reads: the new text of the mail, starting with the subject on a thread's
236
+ * first mail. A command (`/status`) stays first, so the gateway still sees it, and a mail
237
+ * with only a command as its subject is that command.
238
+ */
239
+ private textOf;
240
+ /**
241
+ * Hands an inbound mail to the agent when it is one to answer. Resolves `refused` when the
242
+ * gateway did not take it, so it may come again.
243
+ */
244
+ private accept;
245
+ private fallbackId;
246
+ private remember;
247
+ /** The thread a mail to `to` goes in: the mail it answers, or the latest of its topic. */
248
+ private threadOf;
249
+ private bodies;
250
+ private send;
251
+ private transportOf;
252
+ private listen;
253
+ }
254
+ /** An email channel that answers mail in its thread. */
255
+ export declare function emailChannel(config: EmailChannelConfig): EmailChannel;
256
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/channels/email/channel.ts"],"names":[],"mappings":"AACA,OAAO,EAAsC,KAAK,eAAe,EAAe,MAAM,WAAW,CAAC;AAClG,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAM5F,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAiC,KAAK,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE1E,OAAO,EAQL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAC;AAGrB,0FAA0F;AAC1F,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,oFAAoF;AACpF,eAAO,MAAM,sBAAsB,QAAmB,CAAC;AACvD,uEAAuE;AACvE,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAC7D,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAc3C,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC;IACpB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;IACnB,kGAAkG;IAClG,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,UAAU,GAAG,UAAU,CAAC;IAClC,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,oBAAoB,GAAG,mBAAmB,CAAC,GAAG;IAC9E;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9F;AAED,8FAA8F;AAC9F,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,IAAI,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAAE,SAAS,EAAE,cAAc,CAAA;CAAE,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,eAAe,GAAG,KAAK,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,uBAAuB;IACvB,IAAI,EAAE,eAAe,CAAC;IACtB,yCAAyC;IACzC,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,iFAAiF;IACjF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iEAAiE;IACjE,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,oFAAoF;IACpF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yGAAyG;IACzG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oGAAoG;IACpG,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AA2CD,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGpD;AASD,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAW7D;AAsBD;;;;;;;;;;;GAWG;AACH,qBAAa,YAAa,YAAW,OAAO;IAC1C,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,QAAQ,SAAS;IAC1B,QAAQ,CAAC,cAAc,QAAQ;IAC/B,QAAQ,CAAC,eAAe,SAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,OAAO,CAAyD;IACxE,qFAAqF;IACrF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,iGAAiG;IACjG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,wDAAwD;IACxD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,SAAS,CAAC,CAA0B;IAC5C,OAAO,CAAC,KAAK,CAAC,CAAkD;IAChE,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,kBAAkB;IA+BtC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,4EAA4E;IACtE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B;;;;;OAKG;IACG,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAenD;;;;OAIG;IACG,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAwDhF;;;OAGG;IACH,eAAe,IAAI,eAAe;IA8BlC;;;;OAIG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAKvF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB;;;OAGG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAcrF,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAEjC,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,UAAU;IAelB;;;;OAIG;YACW,YAAY;IAgD1B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAQzB,4FAA4F;IAC5F,OAAO,CAAC,MAAM;IAad;;;;OAIG;IACH,OAAO,CAAC,MAAM;IAad;;;OAGG;YACW,MAAM;IAuDpB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,QAAQ;IAUhB,0FAA0F;IAC1F,OAAO,CAAC,QAAQ;IAiBhB,OAAO,CAAC,MAAM;YAMA,IAAI;IA4ClB,OAAO,CAAC,WAAW;IAqBnB,OAAO,CAAC,MAAM;CA6Bf;AAED,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAErE"}