dkimkit 0.0.0-stage → 0.6.1

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 (128) hide show
  1. package/README.md +153 -2
  2. package/dist/src/cli.d.ts +2 -0
  3. package/dist/src/cli.js +398 -0
  4. package/dist/src/cli.js.map +1 -0
  5. package/dist/src/dns-host.d.ts +10 -0
  6. package/dist/src/dns-host.js +31 -0
  7. package/dist/src/dns-host.js.map +1 -0
  8. package/dist/src/errors.d.ts +17 -0
  9. package/dist/src/errors.js +51 -0
  10. package/dist/src/errors.js.map +1 -0
  11. package/dist/src/hosted/api.d.ts +95 -0
  12. package/dist/src/hosted/api.js +781 -0
  13. package/dist/src/hosted/api.js.map +1 -0
  14. package/dist/src/hosted/auth.d.ts +70 -0
  15. package/dist/src/hosted/auth.js +121 -0
  16. package/dist/src/hosted/auth.js.map +1 -0
  17. package/dist/src/hosted/billing-dodo.d.ts +58 -0
  18. package/dist/src/hosted/billing-dodo.js +139 -0
  19. package/dist/src/hosted/billing-dodo.js.map +1 -0
  20. package/dist/src/hosted/billing-stripe.d.ts +82 -0
  21. package/dist/src/hosted/billing-stripe.js +205 -0
  22. package/dist/src/hosted/billing-stripe.js.map +1 -0
  23. package/dist/src/hosted/billing.d.ts +114 -0
  24. package/dist/src/hosted/billing.js +173 -0
  25. package/dist/src/hosted/billing.js.map +1 -0
  26. package/dist/src/hosted/cli.d.ts +2 -0
  27. package/dist/src/hosted/cli.js +305 -0
  28. package/dist/src/hosted/cli.js.map +1 -0
  29. package/dist/src/hosted/crypto.d.ts +22 -0
  30. package/dist/src/hosted/crypto.js +55 -0
  31. package/dist/src/hosted/crypto.js.map +1 -0
  32. package/dist/src/hosted/index.d.ts +7 -0
  33. package/dist/src/hosted/index.js +11 -0
  34. package/dist/src/hosted/index.js.map +1 -0
  35. package/dist/src/hosted/markdown.d.ts +16 -0
  36. package/dist/src/hosted/markdown.js +168 -0
  37. package/dist/src/hosted/markdown.js.map +1 -0
  38. package/dist/src/hosted/net.d.ts +9 -0
  39. package/dist/src/hosted/net.js +60 -0
  40. package/dist/src/hosted/net.js.map +1 -0
  41. package/dist/src/hosted/postgres-store.d.ts +62 -0
  42. package/dist/src/hosted/postgres-store.js +387 -0
  43. package/dist/src/hosted/postgres-store.js.map +1 -0
  44. package/dist/src/hosted/serialize.d.ts +144 -0
  45. package/dist/src/hosted/serialize.js +126 -0
  46. package/dist/src/hosted/serialize.js.map +1 -0
  47. package/dist/src/hosted/service.d.ts +166 -0
  48. package/dist/src/hosted/service.js +582 -0
  49. package/dist/src/hosted/service.js.map +1 -0
  50. package/dist/src/hosted/site.d.ts +54 -0
  51. package/dist/src/hosted/site.js +472 -0
  52. package/dist/src/hosted/site.js.map +1 -0
  53. package/dist/src/hosted/sqlite-store.d.ts +45 -0
  54. package/dist/src/hosted/sqlite-store.js +351 -0
  55. package/dist/src/hosted/sqlite-store.js.map +1 -0
  56. package/dist/src/hosted/store.d.ts +257 -0
  57. package/dist/src/hosted/store.js +181 -0
  58. package/dist/src/hosted/store.js.map +1 -0
  59. package/dist/src/hosted/widget.d.ts +46 -0
  60. package/dist/src/hosted/widget.js +130 -0
  61. package/dist/src/hosted/widget.js.map +1 -0
  62. package/dist/src/hosted/worker.d.ts +45 -0
  63. package/dist/src/hosted/worker.js +142 -0
  64. package/dist/src/hosted/worker.js.map +1 -0
  65. package/dist/src/http.d.ts +14 -0
  66. package/dist/src/http.js +54 -0
  67. package/dist/src/http.js.map +1 -0
  68. package/dist/src/index.d.ts +19 -0
  69. package/dist/src/index.js +19 -0
  70. package/dist/src/index.js.map +1 -0
  71. package/dist/src/orchestrator.d.ts +70 -0
  72. package/dist/src/orchestrator.js +69 -0
  73. package/dist/src/orchestrator.js.map +1 -0
  74. package/dist/src/propagation.d.ts +30 -0
  75. package/dist/src/propagation.js +76 -0
  76. package/dist/src/propagation.js.map +1 -0
  77. package/dist/src/providers/dns/aws.d.ts +28 -0
  78. package/dist/src/providers/dns/aws.js +103 -0
  79. package/dist/src/providers/dns/aws.js.map +1 -0
  80. package/dist/src/providers/dns/cloudflare.d.ts +26 -0
  81. package/dist/src/providers/dns/cloudflare.js +97 -0
  82. package/dist/src/providers/dns/cloudflare.js.map +1 -0
  83. package/dist/src/providers/dns/manual.d.ts +12 -0
  84. package/dist/src/providers/dns/manual.js +18 -0
  85. package/dist/src/providers/dns/manual.js.map +1 -0
  86. package/dist/src/providers/dns/route53.d.ts +34 -0
  87. package/dist/src/providers/dns/route53.js +176 -0
  88. package/dist/src/providers/dns/route53.js.map +1 -0
  89. package/dist/src/providers/email/factory.d.ts +29 -0
  90. package/dist/src/providers/email/factory.js +67 -0
  91. package/dist/src/providers/email/factory.js.map +1 -0
  92. package/dist/src/providers/email/mailgun.d.ts +36 -0
  93. package/dist/src/providers/email/mailgun.js +141 -0
  94. package/dist/src/providers/email/mailgun.js.map +1 -0
  95. package/dist/src/providers/email/postmark.d.ts +37 -0
  96. package/dist/src/providers/email/postmark.js +121 -0
  97. package/dist/src/providers/email/postmark.js.map +1 -0
  98. package/dist/src/providers/email/sendgrid.d.ts +31 -0
  99. package/dist/src/providers/email/sendgrid.js +109 -0
  100. package/dist/src/providers/email/sendgrid.js.map +1 -0
  101. package/dist/src/providers/email/ses.d.ts +39 -0
  102. package/dist/src/providers/email/ses.js +123 -0
  103. package/dist/src/providers/email/ses.js.map +1 -0
  104. package/dist/src/providers/factory.d.ts +14 -0
  105. package/dist/src/providers/factory.js +32 -0
  106. package/dist/src/providers/factory.js.map +1 -0
  107. package/dist/src/records.d.ts +35 -0
  108. package/dist/src/records.js +109 -0
  109. package/dist/src/records.js.map +1 -0
  110. package/dist/src/server.d.ts +67 -0
  111. package/dist/src/server.js +301 -0
  112. package/dist/src/server.js.map +1 -0
  113. package/dist/src/types.d.ts +75 -0
  114. package/dist/src/types.js +2 -0
  115. package/dist/src/types.js.map +1 -0
  116. package/dist/src/xml.d.ts +6 -0
  117. package/dist/src/xml.js +23 -0
  118. package/dist/src/xml.js.map +1 -0
  119. package/docs/billing.md +43 -0
  120. package/docs/getting-started.md +57 -0
  121. package/docs/hosted-api.md +192 -0
  122. package/docs/self-hosting.md +148 -0
  123. package/docs/widget.md +121 -0
  124. package/package.json +63 -4
  125. package/web/dashboard.html +390 -0
  126. package/web/index.html +697 -0
  127. package/web/widget-frame.html +480 -0
  128. package/web/widget.js +91 -0
@@ -0,0 +1,34 @@
1
+ import { type FetchLike } from '../../http.js';
2
+ import type { DnsProvider, DnsRecord, PlannedChange } from '../../types.js';
3
+ import { type AwsCredentials } from './aws.js';
4
+ export interface Route53Options {
5
+ /** Static credentials, or a loader called once on first use (e.g. `() => loadAwsCredentials()`). */
6
+ credentials: AwsCredentials | (() => Promise<AwsCredentials>);
7
+ /** Use this hosted zone instead of looking one up by name. */
8
+ hostedZoneId?: string;
9
+ baseUrl?: string;
10
+ fetch?: FetchLike;
11
+ }
12
+ /**
13
+ * Route53 stores one record set per (name, type) holding every value, so
14
+ * writes rebuild the whole set (keeping values we didn't create) and UPSERT it.
15
+ */
16
+ export declare class Route53Dns implements DnsProvider {
17
+ private readonly opts;
18
+ readonly name = "route53";
19
+ private readonly baseUrl;
20
+ private readonly fetchImpl;
21
+ private credentials?;
22
+ private readonly zoneIds;
23
+ private readonly knownZones;
24
+ constructor(opts: Route53Options);
25
+ plan(records: DnsRecord[], opts?: {
26
+ overwrite?: boolean;
27
+ }): Promise<PlannedChange[]>;
28
+ apply(changes: PlannedChange[]): Promise<void>;
29
+ /** Finds the public hosted zone holding `name` by trying it and each parent domain. */
30
+ zoneFor(name: string): Promise<string>;
31
+ private lookupZone;
32
+ private listSets;
33
+ private call;
34
+ }
@@ -0,0 +1,176 @@
1
+ import { ConfigError, DnsConflictError } from '../../errors.js';
2
+ import { requestText } from '../../http.js';
3
+ import { decideChange, normalizeName } from '../../records.js';
4
+ import { decodeXml, encodeXml, xmlTags, xmlText } from '../../xml.js';
5
+ import { signRequest } from './aws.js';
6
+ const API_VERSION = '2013-04-01';
7
+ const DEFAULT_TTL = 300;
8
+ /**
9
+ * Route53 stores one record set per (name, type) holding every value, so
10
+ * writes rebuild the whole set (keeping values we didn't create) and UPSERT it.
11
+ */
12
+ export class Route53Dns {
13
+ opts;
14
+ name = 'route53';
15
+ baseUrl;
16
+ fetchImpl;
17
+ credentials;
18
+ zoneIds = new Map();
19
+ knownZones = new Map();
20
+ constructor(opts) {
21
+ this.opts = opts;
22
+ this.baseUrl = opts.baseUrl ?? 'https://route53.amazonaws.com';
23
+ this.fetchImpl = opts.fetch ?? fetch;
24
+ }
25
+ async plan(records, opts = {}) {
26
+ const changes = [];
27
+ for (const record of records) {
28
+ const zoneId = await this.zoneFor(record.name);
29
+ const existing = (await this.listSets(zoneId, record.name)).flatMap(toExisting);
30
+ changes.push(decideChange(record, existing, opts.overwrite, records));
31
+ }
32
+ return changes;
33
+ }
34
+ async apply(changes) {
35
+ const conflicts = changes.filter((c) => c.action === 'conflict');
36
+ if (conflicts.length > 0)
37
+ throw new DnsConflictError(conflicts);
38
+ // zone → (name|type → changes)
39
+ const byZone = new Map();
40
+ for (const change of changes) {
41
+ if (change.action === 'noop')
42
+ continue;
43
+ const zoneId = await this.zoneFor(change.record.name);
44
+ const sets = byZone.get(zoneId) ?? new Map();
45
+ byZone.set(zoneId, sets);
46
+ const key = `${change.record.name}|${change.record.type}`;
47
+ sets.set(key, [...(sets.get(key) ?? []), change]);
48
+ }
49
+ for (const [zoneId, sets] of byZone) {
50
+ const upserts = [];
51
+ for (const group of sets.values()) {
52
+ const { name, type } = group[0].record;
53
+ // Re-read so values added since planning aren't dropped.
54
+ const current = (await this.listSets(zoneId, name)).find((s) => s.type === type);
55
+ let values = type === 'CNAME' ? [] : [...(current?.values ?? [])];
56
+ for (const change of group) {
57
+ if (change.action === 'update' && change.existingId)
58
+ values = values.filter((v) => v !== change.existingId);
59
+ values.push(formatValue(change.record));
60
+ }
61
+ upserts.push({ name, type, ttl: current?.ttl ?? DEFAULT_TTL, values: [...new Set(values)] });
62
+ }
63
+ await this.call('POST', `/hostedzone/${zoneId}/rrset`, changeBatchXml(upserts));
64
+ }
65
+ }
66
+ /** Finds the public hosted zone holding `name` by trying it and each parent domain. */
67
+ async zoneFor(name) {
68
+ if (this.opts.hostedZoneId)
69
+ return this.opts.hostedZoneId.replace(/^\/hostedzone\//, '');
70
+ const labels = normalizeName(name).split('.');
71
+ const candidates = labels.slice(0, -1).map((_, i) => labels.slice(i).join('.'));
72
+ const known = candidates.find((c) => this.knownZones.has(c));
73
+ if (known)
74
+ return this.knownZones.get(known);
75
+ for (const candidate of candidates) {
76
+ const id = await this.lookupZone(candidate);
77
+ if (id) {
78
+ this.knownZones.set(candidate, id);
79
+ return id;
80
+ }
81
+ }
82
+ throw new ConfigError(`No public Route53 hosted zone found for ${name}. Check the AWS account, or pass a hosted zone id.`);
83
+ }
84
+ lookupZone(zoneName) {
85
+ let id = this.zoneIds.get(zoneName);
86
+ if (!id) {
87
+ id = this.call('GET', `/hostedzonesbyname?dnsname=${encodeURIComponent(zoneName)}&maxitems=10`).then((xml) => {
88
+ // Results start at dnsname and continue alphabetically, so match exactly.
89
+ const zone = xmlTags(xml, 'HostedZone').find((z) => decodeName(xmlText(z, 'Name') ?? '') === zoneName && xmlText(z, 'PrivateZone') !== 'true');
90
+ return zone ? xmlText(zone, 'Id').replace(/^\/hostedzone\//, '') : null;
91
+ });
92
+ this.zoneIds.set(zoneName, id);
93
+ }
94
+ return id;
95
+ }
96
+ async listSets(zoneId, name) {
97
+ // Listing starts at `name`; all of a name's sets are adjacent.
98
+ const xml = await this.call('GET', `/hostedzone/${zoneId}/rrset?name=${encodeURIComponent(name)}&maxitems=20`);
99
+ return xmlTags(xml, 'ResourceRecordSet')
100
+ .map((s) => {
101
+ const ttl = xmlText(s, 'TTL');
102
+ const alias = xmlTags(s, 'AliasTarget')[0];
103
+ return {
104
+ name: decodeName(xmlText(s, 'Name') ?? ''),
105
+ type: xmlText(s, 'Type') ?? '',
106
+ ...(ttl ? { ttl: Number(ttl) } : {}),
107
+ values: xmlTags(s, 'Value').map((v) => decodeXml(v.trim())),
108
+ ...(alias ? { alias: normalizeName(xmlText(alias, 'DNSName') ?? '') } : {}),
109
+ };
110
+ })
111
+ .filter((s) => s.name === name);
112
+ }
113
+ async call(method, path, body) {
114
+ this.credentials ??= Promise.resolve(typeof this.opts.credentials === 'function' ? this.opts.credentials() : this.opts.credentials);
115
+ const credentials = await this.credentials;
116
+ const url = `${this.baseUrl}/${API_VERSION}${path}`;
117
+ return requestText(this.fetchImpl, 'Route53', url, () => ({
118
+ method,
119
+ body,
120
+ headers: signRequest({ method, url, body, headers: body ? { 'content-type': 'application/xml' } : {} }, credentials, 'us-east-1', 'route53'),
121
+ }), describeRoute53Error);
122
+ }
123
+ }
124
+ function toExisting(set) {
125
+ if (set.alias)
126
+ return [{ id: `alias:${set.alias}`, type: set.type, value: set.alias }];
127
+ return set.values.map((raw) => {
128
+ if (set.type === 'MX') {
129
+ const [priority, host] = raw.split(/\s+/);
130
+ return { id: raw, type: 'MX', value: host ?? '', priority: Number(priority) };
131
+ }
132
+ return { id: raw, type: set.type, value: set.type === 'TXT' ? unquoteTxt(raw) : raw };
133
+ });
134
+ }
135
+ function formatValue(record) {
136
+ switch (record.type) {
137
+ case 'MX':
138
+ return `${record.priority ?? 10} ${record.value}`;
139
+ case 'TXT': {
140
+ // Route53 wants quoted strings, each at most 255 characters.
141
+ const escaped = record.value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
142
+ return (escaped.match(/[\s\S]{1,255}/g) ?? ['']).map((chunk) => `"${chunk}"`).join(' ');
143
+ }
144
+ default:
145
+ return record.value;
146
+ }
147
+ }
148
+ function unquoteTxt(raw) {
149
+ const chunks = [...raw.matchAll(/"((?:[^"\\]|\\.)*)"/g)].map((m) => m[1].replace(/\\(.)/g, '$1'));
150
+ return chunks.length > 0 ? chunks.join('') : raw;
151
+ }
152
+ /** Route53 returns names with a trailing dot and octal escapes (e.g. \052 for *). */
153
+ function decodeName(name) {
154
+ return normalizeName(name.replace(/\\(\d{3})/g, (_, oct) => String.fromCharCode(parseInt(oct, 8))));
155
+ }
156
+ function changeBatchXml(sets) {
157
+ const changes = sets
158
+ .map((s) => `<Change><Action>UPSERT</Action><ResourceRecordSet><Name>${encodeXml(s.name)}</Name><Type>${s.type}</Type>` +
159
+ `<TTL>${s.ttl ?? DEFAULT_TTL}</TTL><ResourceRecords>` +
160
+ s.values.map((v) => `<ResourceRecord><Value>${encodeXml(v)}</Value></ResourceRecord>`).join('') +
161
+ `</ResourceRecords></ResourceRecordSet></Change>`)
162
+ .join('');
163
+ return (`<?xml version="1.0" encoding="UTF-8"?>` +
164
+ `<ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/${API_VERSION}/">` +
165
+ `<ChangeBatch><Comment>dkimkit</Comment><Changes>${changes}</Changes></ChangeBatch>` +
166
+ `</ChangeResourceRecordSetsRequest>`);
167
+ }
168
+ function describeRoute53Error(text) {
169
+ // InvalidChangeBatch nests per-change <Message>s; other errors have one.
170
+ const messages = xmlTags(text, 'Message').map((m) => decodeXml(m.trim()));
171
+ const code = xmlText(text, 'Code');
172
+ if (messages.length === 0)
173
+ return code;
174
+ return code ? `${code}: ${messages.join('; ')}` : messages.join('; ');
175
+ }
176
+ //# sourceMappingURL=route53.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route53.js","sourceRoot":"","sources":["../../../../src/providers/dns/route53.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { FetchLike } from '../../http.js';
2
+ import type { EmailProvider } from '../../types.js';
3
+ export declare const EMAIL_PROVIDERS: readonly ["sendgrid", "postmark", "mailgun", "ses"];
4
+ export type EmailProviderName = (typeof EMAIL_PROVIDERS)[number];
5
+ export declare const EMAIL_PROVIDER_LABELS: Record<EmailProviderName, string>;
6
+ /** Credentials for any supported email provider; each uses its own fields. */
7
+ export interface EmailCredentials {
8
+ /** SendGrid, Mailgun */
9
+ apiKey?: string;
10
+ /** Postmark account token */
11
+ accountToken?: string;
12
+ /** Postmark server that receives inbound mail */
13
+ inboundServerId?: string;
14
+ /** Mailgun: us | eu. SES: AWS region. */
15
+ region?: string;
16
+ /** SES */
17
+ accessKeyId?: string;
18
+ secretAccessKey?: string;
19
+ sessionToken?: string;
20
+ }
21
+ export declare function isEmailProvider(name: string): name is EmailProviderName;
22
+ /** Throws a ConfigError naming what's missing for the provider. */
23
+ export declare function assertEmailCredentials(provider: string, c: EmailCredentials): void;
24
+ /** Keeps only the fields the provider uses, so nothing extra is stored. */
25
+ export declare function pickEmailCredentials(provider: string, c: EmailCredentials): EmailCredentials;
26
+ export declare function createEmailProvider(provider: string, credentials: EmailCredentials, opts?: {
27
+ subuser?: string | null;
28
+ fetch?: FetchLike;
29
+ }): EmailProvider;
@@ -0,0 +1,67 @@
1
+ import { ConfigError } from '../../errors.js';
2
+ import { MailgunProvider } from './mailgun.js';
3
+ import { PostmarkProvider } from './postmark.js';
4
+ import { SendGridProvider } from './sendgrid.js';
5
+ import { SesProvider } from './ses.js';
6
+ export const EMAIL_PROVIDERS = ['sendgrid', 'postmark', 'mailgun', 'ses'];
7
+ export const EMAIL_PROVIDER_LABELS = {
8
+ sendgrid: 'SendGrid',
9
+ postmark: 'Postmark',
10
+ mailgun: 'Mailgun',
11
+ ses: 'Amazon SES',
12
+ };
13
+ export function isEmailProvider(name) {
14
+ return EMAIL_PROVIDERS.includes(name);
15
+ }
16
+ /** Throws a ConfigError naming what's missing for the provider. */
17
+ export function assertEmailCredentials(provider, c) {
18
+ const need = (ok, message) => {
19
+ if (!ok)
20
+ throw new ConfigError(message);
21
+ };
22
+ switch (provider) {
23
+ case 'sendgrid':
24
+ return need(c.apiKey, 'SendGrid needs an API key.');
25
+ case 'postmark':
26
+ return need(c.accountToken, 'Postmark needs an account API token.');
27
+ case 'mailgun':
28
+ need(c.apiKey, 'Mailgun needs an API key.');
29
+ return need(!c.region || c.region === 'us' || c.region === 'eu', 'Mailgun region must be us or eu.');
30
+ case 'ses':
31
+ need(c.accessKeyId && c.secretAccessKey, 'Amazon SES needs an AWS access key id and secret access key.');
32
+ return need(c.region, 'Amazon SES needs an AWS region, e.g. us-east-1.');
33
+ default:
34
+ throw new ConfigError(`Email provider must be one of: ${EMAIL_PROVIDERS.join(', ')}.`);
35
+ }
36
+ }
37
+ /** Keeps only the fields the provider uses, so nothing extra is stored. */
38
+ export function pickEmailCredentials(provider, c) {
39
+ const keys = {
40
+ sendgrid: ['apiKey'],
41
+ postmark: ['accountToken', 'inboundServerId'],
42
+ mailgun: ['apiKey', 'region'],
43
+ ses: ['accessKeyId', 'secretAccessKey', 'sessionToken', 'region'],
44
+ };
45
+ return Object.fromEntries((keys[provider] ?? []).filter((k) => c[k]).map((k) => [k, c[k]]));
46
+ }
47
+ export function createEmailProvider(provider, credentials, opts = {}) {
48
+ assertEmailCredentials(provider, credentials);
49
+ if (opts.subuser && provider !== 'sendgrid')
50
+ throw new ConfigError('Subusers only apply to SendGrid.');
51
+ const c = credentials;
52
+ switch (provider) {
53
+ case 'sendgrid':
54
+ return new SendGridProvider({ apiKey: c.apiKey, onBehalfOf: opts.subuser ?? undefined, fetch: opts.fetch });
55
+ case 'postmark':
56
+ return new PostmarkProvider({ accountToken: c.accountToken, inboundServerId: c.inboundServerId, fetch: opts.fetch });
57
+ case 'mailgun':
58
+ return new MailgunProvider({ apiKey: c.apiKey, region: c.region ?? 'us', fetch: opts.fetch });
59
+ default:
60
+ return new SesProvider({
61
+ credentials: { accessKeyId: c.accessKeyId, secretAccessKey: c.secretAccessKey, ...(c.sessionToken ? { sessionToken: c.sessionToken } : {}) },
62
+ region: c.region,
63
+ fetch: opts.fetch,
64
+ });
65
+ }
66
+ }
67
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../../src/providers/email/factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { type FetchLike } from '../../http.js';
2
+ import type { DnsRecord, DomainAuthentication, EmailProvider, InboundAction, InboundParseOptions, ValidationResult } from '../../types.js';
3
+ export interface MailgunOptions {
4
+ apiKey: string;
5
+ /** Where the Mailgun account lives. Default "us". */
6
+ region?: 'us' | 'eu';
7
+ baseUrl?: string;
8
+ fetch?: FetchLike;
9
+ }
10
+ /**
11
+ * Mailgun sending domains (usually a subdomain like mg.example.com): SPF and
12
+ * DKIM TXT records plus a tracking CNAME. Inbound mail is received on the
13
+ * Mailgun domain itself (MX to mxa/mxb.mailgun.org) and forwarded by a route.
14
+ */
15
+ export declare class MailgunProvider implements EmailProvider {
16
+ private readonly opts;
17
+ readonly name = "mailgun";
18
+ readonly label = "Mailgun";
19
+ readonly supportsInbound = true;
20
+ private readonly baseUrl;
21
+ private readonly fetchImpl;
22
+ constructor(opts: MailgunOptions);
23
+ /** Mailgun only receives for domains added to it, so inbound goes to the sending domain itself. */
24
+ defaultInboundHostname(domain: string): string;
25
+ findDomain(domain: string): Promise<DomainAuthentication | null>;
26
+ ensureDomain(domain: string): Promise<DomainAuthentication>;
27
+ getDomain(id: string): Promise<DomainAuthentication>;
28
+ deleteDomain(id: string): Promise<void>;
29
+ validateDomain(id: string): Promise<ValidationResult>;
30
+ inboundRecords(hostname: string): DnsRecord[];
31
+ ensureInboundParse(opts: InboundParseOptions): Promise<InboundAction>;
32
+ deleteInboundParse(hostname: string): Promise<void>;
33
+ private routes;
34
+ /** Mailgun takes multipart form fields; repeated keys (e.g. `action`) come from arrays. */
35
+ private request;
36
+ }
@@ -0,0 +1,141 @@
1
+ import { ConfigError, ApiError } from '../../errors.js';
2
+ import { requestText } from '../../http.js';
3
+ import { isSpf, normalizeName } from '../../records.js';
4
+ const BASE_URLS = { us: 'https://api.mailgun.net', eu: 'https://api.eu.mailgun.net' };
5
+ const RECEIVING_MX = ['mxa.mailgun.org', 'mxb.mailgun.org'];
6
+ const routeDescription = (hostname) => `dkimkit inbound ${hostname}`;
7
+ /**
8
+ * Mailgun sending domains (usually a subdomain like mg.example.com): SPF and
9
+ * DKIM TXT records plus a tracking CNAME. Inbound mail is received on the
10
+ * Mailgun domain itself (MX to mxa/mxb.mailgun.org) and forwarded by a route.
11
+ */
12
+ export class MailgunProvider {
13
+ opts;
14
+ name = 'mailgun';
15
+ label = 'Mailgun';
16
+ supportsInbound = true;
17
+ baseUrl;
18
+ fetchImpl;
19
+ constructor(opts) {
20
+ this.opts = opts;
21
+ this.baseUrl = opts.baseUrl ?? BASE_URLS[opts.region ?? 'us'];
22
+ this.fetchImpl = opts.fetch ?? fetch;
23
+ }
24
+ /** Mailgun only receives for domains added to it, so inbound goes to the sending domain itself. */
25
+ defaultInboundHostname(domain) {
26
+ return normalizeName(domain);
27
+ }
28
+ async findDomain(domain) {
29
+ try {
30
+ return toAuthentication(await this.request('GET', `/v4/domains/${encodeURIComponent(normalizeName(domain))}`), false);
31
+ }
32
+ catch (err) {
33
+ if (err instanceof ApiError && err.status === 404)
34
+ return null;
35
+ throw err;
36
+ }
37
+ }
38
+ async ensureDomain(domain) {
39
+ const existing = await this.findDomain(domain);
40
+ if (existing)
41
+ return existing;
42
+ const created = await this.request('POST', '/v4/domains', { name: normalizeName(domain), web_scheme: 'https' });
43
+ return toAuthentication(created, true);
44
+ }
45
+ async getDomain(id) {
46
+ return toAuthentication(await this.request('GET', `/v4/domains/${encodeURIComponent(id)}`), false);
47
+ }
48
+ async deleteDomain(id) {
49
+ await this.request('DELETE', `/v3/domains/${encodeURIComponent(id)}`);
50
+ }
51
+ async validateDomain(id) {
52
+ const res = await this.request('PUT', `/v4/domains/${encodeURIComponent(id)}/verify`);
53
+ const records = toAuthentication(res, false).records;
54
+ return {
55
+ valid: res.domain.state === 'active',
56
+ results: (res.sending_dns_records ?? []).map((r, i) => {
57
+ const valid = r.valid === 'valid';
58
+ return { record: records[i]?.purpose ?? r.record_type.toLowerCase(), valid, ...(valid ? {} : { reason: 'Not found in DNS yet' }) };
59
+ }),
60
+ };
61
+ }
62
+ inboundRecords(hostname) {
63
+ return RECEIVING_MX.map((value, i) => ({
64
+ type: 'MX',
65
+ name: normalizeName(hostname),
66
+ value,
67
+ priority: 10,
68
+ purpose: i === 0 ? 'inbound_mx' : 'inbound_mx_2',
69
+ }));
70
+ }
71
+ async ensureInboundParse(opts) {
72
+ const hostname = normalizeName(opts.hostname);
73
+ if (!(await this.findDomain(hostname))) {
74
+ throw new ConfigError(`Mailgun only receives mail for domains added to Mailgun. Use the sending domain (such as mg.${hostname.split('.').slice(-2).join('.')}) as the inbound hostname.`);
75
+ }
76
+ if (/["\\]/.test(opts.url))
77
+ throw new ConfigError('The inbound webhook URL cannot contain quotes or backslashes.');
78
+ const expression = `match_recipient(".*@${hostname.replace(/\./g, '\\.')}")`;
79
+ const actions = [`forward("${opts.url}")`, 'stop()'];
80
+ const route = (await this.routes()).find((r) => r.description === routeDescription(hostname));
81
+ const form = { priority: '10', description: routeDescription(hostname), expression, action: actions };
82
+ if (!route) {
83
+ await this.request('POST', '/v3/routes', form);
84
+ return 'created';
85
+ }
86
+ if (route.expression === expression && JSON.stringify(route.actions ?? []) === JSON.stringify(actions))
87
+ return 'unchanged';
88
+ await this.request('PUT', `/v3/routes/${encodeURIComponent(route.id)}`, form);
89
+ return 'updated';
90
+ }
91
+ async deleteInboundParse(hostname) {
92
+ const route = (await this.routes()).find((r) => r.description === routeDescription(normalizeName(hostname)));
93
+ if (route)
94
+ await this.request('DELETE', `/v3/routes/${encodeURIComponent(route.id)}`);
95
+ }
96
+ async routes() {
97
+ return (await this.request('GET', '/v3/routes?limit=1000')).items ?? [];
98
+ }
99
+ /** Mailgun takes multipart form fields; repeated keys (e.g. `action`) come from arrays. */
100
+ async request(method, path, form) {
101
+ const text = await requestText(this.fetchImpl, 'Mailgun', this.baseUrl + path, () => {
102
+ let body;
103
+ if (form) {
104
+ body = new FormData();
105
+ for (const [k, v] of Object.entries(form))
106
+ for (const item of [v].flat())
107
+ body.append(k, item);
108
+ }
109
+ return {
110
+ method,
111
+ headers: { Authorization: `Basic ${Buffer.from(`api:${this.opts.apiKey}`).toString('base64')}`, Accept: 'application/json' },
112
+ body,
113
+ };
114
+ }, (t) => {
115
+ try {
116
+ return JSON.parse(t).message;
117
+ }
118
+ catch {
119
+ return undefined;
120
+ }
121
+ });
122
+ return (text ? JSON.parse(text) : {});
123
+ }
124
+ }
125
+ function toAuthentication(res, created) {
126
+ const domain = normalizeName(res.domain.name);
127
+ const records = (res.sending_dns_records ?? []).flatMap((r) => {
128
+ const type = r.record_type.toUpperCase();
129
+ if (type !== 'TXT' && type !== 'CNAME')
130
+ return [];
131
+ const name = normalizeName(r.name || domain);
132
+ if (type === 'CNAME')
133
+ return [{ type, name, value: normalizeName(r.value), purpose: 'tracking' }];
134
+ if (isSpf(r.value)) {
135
+ return [{ type, name, value: r.value, purpose: 'spf', note: 'If this name already has an SPF record (v=spf1 …), add include:mailgun.org to it instead of creating a second one.' }];
136
+ }
137
+ return [{ type, name, value: r.value, purpose: name.includes('._domainkey.') ? 'dkim' : 'txt' }];
138
+ });
139
+ return { id: domain, domain, valid: res.domain.state === 'active', records, created };
140
+ }
141
+ //# sourceMappingURL=mailgun.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mailgun.js","sourceRoot":"","sources":["../../../../src/providers/email/mailgun.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { type FetchLike } from '../../http.js';
2
+ import type { DnsRecord, DomainAuthentication, EmailProvider, InboundAction, InboundParseOptions, ValidationResult } from '../../types.js';
3
+ export declare const POSTMARK_INBOUND_MX = "inbound.postmarkapp.com";
4
+ export interface PostmarkOptions {
5
+ /** Account API token (X-Postmark-Account-Token). */
6
+ accountToken: string;
7
+ /** Server whose inbound stream receives mail. Postmark allows one inbound domain per server. */
8
+ inboundServerId?: string;
9
+ baseUrl?: string;
10
+ fetch?: FetchLike;
11
+ }
12
+ /**
13
+ * Postmark sender signatures for domains: a DKIM TXT record and a custom
14
+ * Return-Path CNAME. SPF is no longer required by Postmark.
15
+ */
16
+ export declare class PostmarkProvider implements EmailProvider {
17
+ private readonly opts;
18
+ readonly name = "postmark";
19
+ readonly label = "Postmark";
20
+ readonly supportsInbound = true;
21
+ private readonly baseUrl;
22
+ private readonly fetchImpl;
23
+ constructor(opts: PostmarkOptions);
24
+ defaultInboundHostname(domain: string): string;
25
+ findDomain(domain: string): Promise<DomainAuthentication | null>;
26
+ ensureDomain(domain: string, opts?: {
27
+ subdomain?: string;
28
+ }): Promise<DomainAuthentication>;
29
+ getDomain(id: string): Promise<DomainAuthentication>;
30
+ deleteDomain(id: string): Promise<void>;
31
+ validateDomain(id: string): Promise<ValidationResult>;
32
+ inboundRecords(hostname: string): DnsRecord[];
33
+ ensureInboundParse(opts: InboundParseOptions): Promise<InboundAction>;
34
+ deleteInboundParse(hostname: string): Promise<void>;
35
+ private inboundServer;
36
+ private request;
37
+ }