@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,211 @@
1
+ const ADDRESS = /^[^\s@<>()",;:]+@[^\s@<>()",;:.]+(?:\.[^\s@<>()",;:.]+)+$/;
2
+ /** An address in the form the channel keys senders by: trimmed and in lower case. */
3
+ export function normalizeAddress(address) {
4
+ return address.trim().replace(/^<|>$/g, '').toLowerCase();
5
+ }
6
+ /** Whether `text` is a plain address, `local@domain.tld`. */
7
+ export function isAddress(text) {
8
+ return ADDRESS.test(text);
9
+ }
10
+ /** The domain of an address, in lower case. */
11
+ export function domainOf(address) {
12
+ const at = address.lastIndexOf('@');
13
+ return at === -1 ? '' : address.slice(at + 1).toLowerCase();
14
+ }
15
+ function decodeBytes(bytes, charset) {
16
+ try {
17
+ return new TextDecoder(charset.toLowerCase()).decode(bytes);
18
+ }
19
+ catch {
20
+ return new TextDecoder('utf-8').decode(bytes);
21
+ }
22
+ }
23
+ /** Header text with its RFC 2047 encoded words (`=?utf-8?B?...?=`, `=?utf-8?Q?...?=`) decoded. */
24
+ export function decodeMimeWords(text) {
25
+ return text
26
+ .replace(/(=\?[^?\s]+\?[bq]\?[^?\s]*\?=)\s+(?==\?[^?\s]+\?[bq]\?)/gi, '$1')
27
+ .replace(/=\?([^?\s*]+)(?:\*[^?\s]*)?\?([bq])\?([^?\s]*)\?=/gi, (word, charset, encoding, data) => {
28
+ if (encoding.toLowerCase() === 'b') {
29
+ return decodeBytes(Buffer.from(data, 'base64'), charset);
30
+ }
31
+ const bytes = [];
32
+ const text = data.replace(/_/g, ' ');
33
+ for (let i = 0; i < text.length; i++) {
34
+ if (text[i] === '=' && /^[0-9a-f]{2}$/i.test(text.slice(i + 1, i + 3))) {
35
+ bytes.push(parseInt(text.slice(i + 1, i + 3), 16));
36
+ i += 2;
37
+ }
38
+ else
39
+ bytes.push(text.charCodeAt(i) & 0xff);
40
+ }
41
+ return bytes.length ? decodeBytes(Uint8Array.from(bytes), charset) : word;
42
+ });
43
+ }
44
+ /**
45
+ * Splits the first mailbox of an address header (RFC 5322) in one pass: quoted strings and
46
+ * comments are taken as text, so an address written inside them (`"x <ceo@victim.com>"`) is
47
+ * part of the name and never the address. The mailbox ends at the first comma outside them.
48
+ */
49
+ function mailboxParts(text) {
50
+ let phrase = '';
51
+ let bare = '';
52
+ let comment;
53
+ let angle;
54
+ let quoted = false;
55
+ let depth = 0;
56
+ let currentComment = '';
57
+ let inAngle = false;
58
+ let angleText = '';
59
+ for (let i = 0; i < text.length; i++) {
60
+ const char = text[i];
61
+ if (quoted) {
62
+ if (char === '\\' && i + 1 < text.length)
63
+ phrase += text[++i];
64
+ else if (char === '"')
65
+ quoted = false;
66
+ else
67
+ phrase += char;
68
+ continue;
69
+ }
70
+ if (depth > 0) {
71
+ if (char === '\\' && i + 1 < text.length)
72
+ currentComment += text[++i];
73
+ else if (char === '(') {
74
+ depth++;
75
+ currentComment += char;
76
+ }
77
+ else if (char === ')') {
78
+ depth--;
79
+ if (depth === 0)
80
+ comment ??= currentComment.trim();
81
+ else
82
+ currentComment += char;
83
+ }
84
+ else
85
+ currentComment += char;
86
+ continue;
87
+ }
88
+ if (inAngle) {
89
+ if (char === '>') {
90
+ inAngle = false;
91
+ angle = angleText.trim();
92
+ }
93
+ else
94
+ angleText += char;
95
+ continue;
96
+ }
97
+ if (char === '"')
98
+ quoted = true;
99
+ else if (char === '(') {
100
+ depth = 1;
101
+ currentComment = '';
102
+ }
103
+ else if (char === '<') {
104
+ inAngle = true;
105
+ angleText = '';
106
+ }
107
+ else if (char === ',')
108
+ break;
109
+ else {
110
+ if (angle === undefined)
111
+ phrase += char;
112
+ bare += char;
113
+ }
114
+ }
115
+ return { ...(angle !== undefined && { angle }), phrase, bare, ...(comment && { comment }) };
116
+ }
117
+ /**
118
+ * The first mailbox of an address header such as `From`: `"Ann Lee" <ann@example.com>`,
119
+ * `Ann <ann@example.com>` or `ann@example.com (Ann)`, with encoded words in the name decoded.
120
+ * The address is the angle address outside quoted strings and comments, so a display name that
121
+ * holds another address cannot pass for it.
122
+ */
123
+ export function parseMailbox(value) {
124
+ if (!value)
125
+ return undefined;
126
+ const parts = mailboxParts(value.replace(/\r?\n[ \t]+/g, ' ').trim());
127
+ if (parts.angle !== undefined) {
128
+ const address = normalizeAddress(parts.angle);
129
+ if (!isAddress(address))
130
+ return undefined;
131
+ const name = decodeMimeWords(parts.phrase.replace(/\s+/g, ' ').trim()).trim();
132
+ return name ? { address, name } : { address };
133
+ }
134
+ const address = normalizeAddress(parts.bare.trim());
135
+ if (!isAddress(address))
136
+ return undefined;
137
+ return parts.comment ? { address, name: decodeMimeWords(parts.comment) } : { address };
138
+ }
139
+ /** The message ids (`<id@host>`) of a `Message-ID`, `In-Reply-To` or `References` header. */
140
+ export function messageIdsOf(value) {
141
+ if (!value)
142
+ return [];
143
+ const ids = value.match(/<[^<>\s]+>/g);
144
+ if (ids)
145
+ return ids;
146
+ const bare = value.trim();
147
+ return bare && !/\s/.test(bare) ? [`<${bare.replace(/^<|>$/g, '')}>`] : [];
148
+ }
149
+ /** The first message id of a header, if it has one. */
150
+ export function messageIdOf(value) {
151
+ return messageIdsOf(value)[0];
152
+ }
153
+ /** A header block (`Name: value` lines, folded lines continuing with whitespace) as headers. */
154
+ export function parseHeaderBlock(block) {
155
+ const headers = [];
156
+ for (const line of block.replace(/\r\n?/g, '\n').split('\n')) {
157
+ if (!line)
158
+ break;
159
+ if (/^[ \t]/.test(line) && headers.length > 0) {
160
+ const last = headers[headers.length - 1];
161
+ last[1] = `${last[1]} ${line.trim()}`;
162
+ continue;
163
+ }
164
+ const colon = line.indexOf(':');
165
+ if (colon <= 0)
166
+ continue;
167
+ headers.push([line.slice(0, colon).trim().toLowerCase(), line.slice(colon + 1).trim()]);
168
+ }
169
+ return headers;
170
+ }
171
+ /** The first value of a header, by its name in any letter case. */
172
+ export function headerOf(headers, name) {
173
+ const wanted = name.toLowerCase();
174
+ return headers.find(([key]) => key === wanted)?.[1];
175
+ }
176
+ /** Every value of a header, top to bottom, by its name in any letter case. */
177
+ export function headersOf(headers, name) {
178
+ const wanted = name.toLowerCase();
179
+ return headers.filter(([key]) => key === wanted).map(([, value]) => value);
180
+ }
181
+ /**
182
+ * Whether `domain` is aligned with the author's domain `fromDomain` in the relaxed DMARC sense:
183
+ * the same domain, or one a subdomain of the other.
184
+ */
185
+ export function alignedDomains(domain, fromDomain) {
186
+ const a = domain.toLowerCase().replace(/\.$/, '');
187
+ const b = fromDomain.toLowerCase().replace(/\.$/, '');
188
+ if (!a || !b)
189
+ return false;
190
+ return a === b || a.endsWith(`.${b}`) || b.endsWith(`.${a}`);
191
+ }
192
+ /**
193
+ * Whether an allow list lets `address` in. Entries are addresses (`ann@example.com`), domains
194
+ * (`example.com` or `@example.com`, without subdomains), subdomain wildcards (`*.example.com`)
195
+ * or `*` for everyone, in any letter case.
196
+ */
197
+ export function allowsSender(list, address) {
198
+ const sender = normalizeAddress(address);
199
+ const domain = domainOf(sender);
200
+ return list.some((raw) => {
201
+ const entry = raw.trim().toLowerCase();
202
+ if (entry === '*')
203
+ return true;
204
+ if (entry.startsWith('*.'))
205
+ return domain.endsWith(entry.slice(1));
206
+ if (entry.includes('@') && !entry.startsWith('@'))
207
+ return entry === sender;
208
+ return entry.replace(/^@/, '') === domain;
209
+ });
210
+ }
211
+ //# sourceMappingURL=address.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.js","sourceRoot":"","sources":["../../../src/channels/email/address.ts"],"names":[],"mappings":"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"}
@@ -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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"}