groundmail 0.23.0 → 0.25.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.
package/README.md CHANGED
@@ -25,6 +25,20 @@ const email = await tx.emails.send({
25
25
  console.log(email.id, email.status)
26
26
  ```
27
27
 
28
+ ## Azure managed identity (no API key)
29
+
30
+ On Azure, authenticate with the workload's managed identity instead of a key. Pass a token provider; the client caches the token until shortly before it expires and asks for a new one after a 401:
31
+
32
+ ```ts
33
+ import { DefaultAzureCredential } from '@azure/identity'
34
+ import { Groundmail } from 'groundmail'
35
+
36
+ const credential = new DefaultAzureCredential()
37
+ const client = new Groundmail({ getToken: () => credential.getToken('api://<your-app-id>/.default') })
38
+ ```
39
+
40
+ `getToken` may return a string or `{ token, expiresOnTimestamp }`. Register the identity in the dashboard first: https://docs.groundmail.dev/authentication/azure-managed-identity
41
+
28
42
  ## Testing
29
43
 
30
44
  Use a test key (`gm_test_…`, create one with `tx.apiKeys.create({ test: true })` or in the
package/dist/authjs.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Groundmail } from './client-CTG4zTKw.js';
1
+ import { G as Groundmail } from './client-NSj8n5sB.js';
2
2
 
3
3
  /** Subset of Auth.js theme used for the default magic-link email. */
4
4
  type AuthjsTheme = {
package/dist/authjs.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_API_BASE_URL,
3
3
  Groundmail
4
- } from "./chunk-QBGTN2WD.js";
4
+ } from "./chunk-NQWM7F3N.js";
5
5
 
6
6
  // src/authjs.ts
7
7
  function escapeHtml(value) {
@@ -1,4 +1,4 @@
1
- import { S as SendEmailResult, G as Groundmail } from './client-CTG4zTKw.js';
1
+ import { S as SendEmailResult, G as Groundmail } from './client-NSj8n5sB.js';
2
2
 
3
3
  type BetterAuthEmailUser = {
4
4
  email: string;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_API_BASE_URL,
3
3
  Groundmail
4
- } from "./chunk-QBGTN2WD.js";
4
+ } from "./chunk-NQWM7F3N.js";
5
5
 
6
6
  // src/better-auth.ts
7
7
  function linkHtml(label, url) {
@@ -1334,6 +1334,37 @@ var SuppressionsResource = class {
1334
1334
  method: "DELETE"
1335
1335
  });
1336
1336
  }
1337
+ /**
1338
+ * List category opt-outs: addresses that unsubscribed from product or
1339
+ * newsletter email. Pass `tenant` for one tenant's opt-outs.
1340
+ */
1341
+ async listCategoryOptOuts(params = {}) {
1342
+ const search = new URLSearchParams({ type: "category_opt_out" });
1343
+ if (params.limit != null) search.set("limit", String(params.limit));
1344
+ if (params.cursor) search.set("cursor", params.cursor);
1345
+ if (params.email) search.set("email", params.email);
1346
+ if (params.category) search.set("category", params.category);
1347
+ if (params.tenant) search.set("tenant", params.tenant);
1348
+ if (params.includeTenants) search.set("include_tenants", "true");
1349
+ return this.client.request(`/suppressions?${search.toString()}`, { method: "GET" });
1350
+ }
1351
+ /**
1352
+ * Remove a category opt-out by opt-out id or email address, so the address
1353
+ * can receive that category again (for example after the reader re-subscribes).
1354
+ * Throws a 404 error when nothing matches.
1355
+ */
1356
+ async removeCategoryOptOut(idOrEmail, options = {}) {
1357
+ const search = new URLSearchParams({ type: "category_opt_out" });
1358
+ if (options.category) search.set("category", options.category);
1359
+ if (options.tenant) search.set("tenant", options.tenant);
1360
+ if (idOrEmail.includes("@")) {
1361
+ search.set("email", idOrEmail);
1362
+ return this.client.request(`/suppressions?${search.toString()}`, { method: "DELETE" });
1363
+ }
1364
+ return this.client.request(`/suppressions/${encodeURIComponent(idOrEmail)}?${search.toString()}`, {
1365
+ method: "DELETE"
1366
+ });
1367
+ }
1337
1368
  };
1338
1369
 
1339
1370
  // src/templates.ts
@@ -1528,12 +1559,24 @@ var WebhooksResource = class {
1528
1559
 
1529
1560
  // src/client.ts
1530
1561
  var DEFAULT_API_BASE_URL = "https://api.groundmail.dev";
1531
- var Groundmail = class {
1532
- constructor(apiKey, options = {}) {
1533
- this.apiKey = apiKey;
1534
- this.options = options;
1535
- if (!apiKey?.startsWith("gm_")) {
1536
- throw new Error("Groundmail API key must start with gm_");
1562
+ var _Groundmail = class _Groundmail {
1563
+ constructor(apiKeyOrOptions, options = {}) {
1564
+ this.cachedToken = null;
1565
+ if (apiKeyOrOptions && typeof apiKeyOrOptions === "object") {
1566
+ if (typeof apiKeyOrOptions.getToken !== "function") {
1567
+ throw new Error("Groundmail: pass an API key (gm_\u2026) or { getToken } to authenticate");
1568
+ }
1569
+ const { getToken, ...rest } = apiKeyOrOptions;
1570
+ this.apiKey = null;
1571
+ this.getToken = getToken;
1572
+ this.options = rest;
1573
+ } else {
1574
+ if (!apiKeyOrOptions?.startsWith("gm_")) {
1575
+ throw new Error("Groundmail API key must start with gm_");
1576
+ }
1577
+ this.apiKey = apiKeyOrOptions;
1578
+ this.getToken = null;
1579
+ this.options = options;
1537
1580
  }
1538
1581
  this.domains = new DomainsResource(this);
1539
1582
  this.emails = new EmailsResource(this);
@@ -1567,12 +1610,35 @@ var Groundmail = class {
1567
1610
  get fetchImpl() {
1568
1611
  return this.options.fetch || fetch;
1569
1612
  }
1613
+ async bearer(forceRefresh = false) {
1614
+ if (this.apiKey) return this.apiKey;
1615
+ if (!forceRefresh && this.cachedToken && Date.now() < this.cachedToken.refreshAt) {
1616
+ return this.cachedToken.token;
1617
+ }
1618
+ const value = await this.getToken();
1619
+ const { token, expiresAt } = normalizeAccessToken(value);
1620
+ if (!token) throw new Error("Groundmail: getToken() returned no token");
1621
+ const fallback = Date.now() + _Groundmail.TOKEN_DEFAULT_TTL_MS;
1622
+ const refreshAt = expiresAt ? expiresAt - _Groundmail.TOKEN_REFRESH_SKEW_MS : fallback;
1623
+ this.cachedToken = { token, refreshAt };
1624
+ return token;
1625
+ }
1626
+ /** Send with the current credential; with a token provider, retry once with a fresh token after a 401. */
1627
+ async authorizedFetch(url, init, extraHeaders) {
1628
+ const send = async (forceRefresh) => this.fetchImpl(url, {
1629
+ ...init,
1630
+ headers: { Authorization: `Bearer ${await this.bearer(forceRefresh)}`, ...extraHeaders, ...init.headers || {} }
1631
+ });
1632
+ const response = await send(false);
1633
+ if (response.status === 401 && this.getToken) {
1634
+ this.cachedToken = null;
1635
+ return send(true);
1636
+ }
1637
+ return response;
1638
+ }
1570
1639
  /** GET a text body (CSV downloads). Errors are JSON, like every other route. */
1571
1640
  async requestText(path) {
1572
- const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
1573
- method: "GET",
1574
- headers: { Authorization: `Bearer ${this.apiKey}` }
1575
- });
1641
+ const response = await this.authorizedFetch(`${this.baseUrl}${path}`, { method: "GET" }, {});
1576
1642
  if (!response.ok) {
1577
1643
  const body = await response.json().catch(() => ({}));
1578
1644
  throw GroundmailError.fromResponse(response.status, body);
@@ -1580,14 +1646,7 @@ var Groundmail = class {
1580
1646
  return response.text();
1581
1647
  }
1582
1648
  async request(path, init) {
1583
- const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
1584
- ...init,
1585
- headers: {
1586
- Authorization: `Bearer ${this.apiKey}`,
1587
- "Content-Type": "application/json",
1588
- ...init.headers || {}
1589
- }
1590
- });
1649
+ const response = await this.authorizedFetch(`${this.baseUrl}${path}`, init, { "Content-Type": "application/json" });
1591
1650
  const body = await response.json().catch(() => ({}));
1592
1651
  if (!response.ok) {
1593
1652
  throw GroundmailError.fromResponse(response.status, body);
@@ -1595,6 +1654,33 @@ var Groundmail = class {
1595
1654
  return body;
1596
1655
  }
1597
1656
  };
1657
+ /** Two minutes of slack so a token never expires in flight. */
1658
+ _Groundmail.TOKEN_REFRESH_SKEW_MS = 2 * 60 * 1e3;
1659
+ /** Tokens with no known expiry are reused this long at most. */
1660
+ _Groundmail.TOKEN_DEFAULT_TTL_MS = 5 * 60 * 1e3;
1661
+ var Groundmail = _Groundmail;
1662
+ function normalizeAccessToken(value) {
1663
+ if (!value) return { token: "", expiresAt: null };
1664
+ if (typeof value === "string") return { token: value, expiresAt: jwtExpiry(value) };
1665
+ const token = typeof value.token === "string" ? value.token : "";
1666
+ let expiresAt = null;
1667
+ if (typeof value.expiresOnTimestamp === "number") expiresAt = value.expiresOnTimestamp;
1668
+ else if (value.expiresOn instanceof Date) expiresAt = value.expiresOn.getTime();
1669
+ else if (typeof value.expiresOn === "number") expiresAt = value.expiresOn < 1e12 ? value.expiresOn * 1e3 : value.expiresOn;
1670
+ return { token, expiresAt: expiresAt ?? jwtExpiry(token) };
1671
+ }
1672
+ function jwtExpiry(token) {
1673
+ const part = token.split(".")[1];
1674
+ if (!part) return null;
1675
+ try {
1676
+ const base64 = part.replace(/-/g, "+").replace(/_/g, "/");
1677
+ const json = typeof atob === "function" ? atob(base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=")) : "";
1678
+ const exp = JSON.parse(json).exp;
1679
+ return typeof exp === "number" ? exp * 1e3 : null;
1680
+ } catch {
1681
+ return null;
1682
+ }
1683
+ }
1598
1684
 
1599
1685
  export {
1600
1686
  GroundmailError,
@@ -1605,5 +1691,6 @@ export {
1605
1691
  buildSignatureHeader,
1606
1692
  verifyWebhookSignature,
1607
1693
  DEFAULT_API_BASE_URL,
1608
- Groundmail
1694
+ Groundmail,
1695
+ normalizeAccessToken
1609
1696
  };
package/dist/clerk.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Groundmail, S as SendEmailResult } from './client-CTG4zTKw.js';
1
+ import { G as Groundmail, S as SendEmailResult } from './client-NSj8n5sB.js';
2
2
 
3
3
  /**
4
4
  * Subset of Clerk `email.created` webhook `data` used for delivery.
package/dist/clerk.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_API_BASE_URL,
3
3
  Groundmail
4
- } from "./chunk-QBGTN2WD.js";
4
+ } from "./chunk-NQWM7F3N.js";
5
5
 
6
6
  // src/clerk.ts
7
7
  function resolveApiKey(options) {
@@ -697,6 +697,43 @@ type CreateSuppressionParams = {
697
697
  /** Add to this tenant's own list (external id or Groundmail id) instead of the account's. */
698
698
  tenant?: string;
699
699
  };
700
+ /** A category a reader can opt out of with a one-click unsubscribe. */
701
+ type CategoryOptOutCategory = 'product' | 'newsletter';
702
+ /**
703
+ * A category opt-out: the address unsubscribed from one category (product or
704
+ * newsletter email). Sends in that category to the address are refused with a 422.
705
+ */
706
+ type CategoryOptOut = {
707
+ id: string;
708
+ type: 'category_opt_out';
709
+ email: string;
710
+ category: CategoryOptOutCategory | string;
711
+ /** The tenant's external id for a tenant's opt-out; `null` when account-wide. */
712
+ tenant: string | null;
713
+ created_at: string;
714
+ updated_at: string;
715
+ };
716
+ type ListCategoryOptOutsParams = {
717
+ limit?: number;
718
+ cursor?: string;
719
+ email?: string;
720
+ category?: CategoryOptOutCategory;
721
+ /** List this tenant's opt-outs instead of the account-wide ones. */
722
+ tenant?: string;
723
+ /** Without `tenant`: also list every tenant's opt-outs (each row carries its tenant). */
724
+ includeTenants?: boolean;
725
+ };
726
+ type ListCategoryOptOutsResult = {
727
+ data: CategoryOptOut[];
728
+ has_more: boolean;
729
+ next_cursor: string | null;
730
+ };
731
+ type RemoveCategoryOptOutOptions = {
732
+ /** Only this category; omit to remove every category for the address. */
733
+ category?: CategoryOptOutCategory;
734
+ /** Remove from this tenant's opt-outs instead of the account-wide ones. */
735
+ tenant?: string;
736
+ };
700
737
  type TemplateStatus = 'draft' | 'published';
701
738
  type TemplateFormat = 'html' | 'blocks';
702
739
  type TemplateLintWarning = {
@@ -803,10 +840,31 @@ type UpdateTemplateParams = {
803
840
  /** Move it to this folder (created when missing); `null` or `''` takes it out of any folder. */
804
841
  folder?: string | null;
805
842
  };
843
+ /**
844
+ * What a token provider may return: the token itself, or an object with the
845
+ * token and when it expires (the `AccessToken` shape `@azure/identity`'s
846
+ * `credential.getToken()` returns, so it can be passed straight through).
847
+ */
848
+ type GroundmailAccessToken = string | {
849
+ token: string;
850
+ expiresOnTimestamp?: number;
851
+ expiresOn?: Date | number;
852
+ };
853
+ /**
854
+ * Returns a Bearer token for each request, instead of a fixed API key. Use it
855
+ * for keyless auth from Azure (a managed identity's Microsoft Entra token):
856
+ * `getToken: () => credential.getToken('api://…/.default')`. The SDK caches the
857
+ * token until two minutes before it expires and asks again after a 401.
858
+ */
859
+ type GroundmailTokenProvider = () => GroundmailAccessToken | null | undefined | Promise<GroundmailAccessToken | null | undefined>;
806
860
  type GroundmailOptions = {
807
861
  baseUrl?: string;
808
862
  fetch?: typeof fetch;
809
863
  };
864
+ /** `new Groundmail({ getToken })`: authenticate with a token provider instead of an API key. */
865
+ type GroundmailTokenOptions = GroundmailOptions & {
866
+ getToken: GroundmailTokenProvider;
867
+ };
810
868
  type DomainStatus = 'pending' | 'verified' | 'failed';
811
869
  type DomainTlsMode = 'opportunistic' | 'enforced';
812
870
  type DomainDmarcAnalysis = {
@@ -1539,6 +1597,20 @@ declare class SuppressionsResource {
1539
1597
  }): Promise<{
1540
1598
  ok: boolean;
1541
1599
  }>;
1600
+ /**
1601
+ * List category opt-outs: addresses that unsubscribed from product or
1602
+ * newsletter email. Pass `tenant` for one tenant's opt-outs.
1603
+ */
1604
+ listCategoryOptOuts(params?: ListCategoryOptOutsParams): Promise<ListCategoryOptOutsResult>;
1605
+ /**
1606
+ * Remove a category opt-out by opt-out id or email address, so the address
1607
+ * can receive that category again (for example after the reader re-subscribes).
1608
+ * Throws a 404 error when nothing matches.
1609
+ */
1610
+ removeCategoryOptOut(idOrEmail: string, options?: RemoveCategoryOptOutOptions): Promise<{
1611
+ ok: boolean;
1612
+ deleted: number;
1613
+ }>;
1542
1614
  }
1543
1615
 
1544
1616
  declare class TemplatesResource {
@@ -1667,8 +1739,6 @@ declare class WebhooksResource {
1667
1739
 
1668
1740
  declare const DEFAULT_API_BASE_URL = "https://api.groundmail.dev";
1669
1741
  declare class Groundmail {
1670
- private readonly apiKey;
1671
- private readonly options;
1672
1742
  readonly domains: DomainsResource;
1673
1743
  readonly emails: EmailsResource;
1674
1744
  readonly receivedEmails: ReceivedEmailsResource;
@@ -1686,7 +1756,16 @@ declare class Groundmail {
1686
1756
  readonly migrations: MigrationsResource;
1687
1757
  /** DMARC monitoring per domain: report address, sources, pass rates and readiness. */
1688
1758
  readonly dmarc: DmarcResource;
1759
+ private readonly apiKey;
1760
+ private readonly options;
1761
+ private readonly getToken;
1762
+ private cachedToken;
1763
+ /**
1764
+ * `new Groundmail('gm_…')` with an API key, or `new Groundmail({ getToken })`
1765
+ * with a token provider (for example an Azure managed identity; no key).
1766
+ */
1689
1767
  constructor(apiKey: string, options?: GroundmailOptions);
1768
+ constructor(options: GroundmailTokenOptions);
1690
1769
  /**
1691
1770
  * Check one address with Groundmail validation before you accept it (for
1692
1771
  * example on a signup form): syntax, mail server, disposable and role
@@ -1695,9 +1774,21 @@ declare class Groundmail {
1695
1774
  validate(email: string): Promise<ValidateEmailResult>;
1696
1775
  get baseUrl(): string;
1697
1776
  get fetchImpl(): typeof fetch;
1777
+ /** Two minutes of slack so a token never expires in flight. */
1778
+ private static readonly TOKEN_REFRESH_SKEW_MS;
1779
+ /** Tokens with no known expiry are reused this long at most. */
1780
+ private static readonly TOKEN_DEFAULT_TTL_MS;
1781
+ private bearer;
1782
+ /** Send with the current credential; with a token provider, retry once with a fresh token after a 401. */
1783
+ private authorizedFetch;
1698
1784
  /** GET a text body (CSV downloads). Errors are JSON, like every other route. */
1699
1785
  requestText(path: string): Promise<string>;
1700
1786
  request<T>(path: string, init: RequestInit): Promise<T>;
1701
1787
  }
1788
+ /** A token provider's result → the token and its expiry (ms since epoch), if known. */
1789
+ declare function normalizeAccessToken(value: GroundmailAccessToken | null | undefined): {
1790
+ token: string;
1791
+ expiresAt: number | null;
1792
+ };
1702
1793
 
1703
- export { type Domain as $, type ApiErrorBody as A, type BatchSendEmailResult as B, type CategoryUnsubscribedErrorDetails as C, type DnsRecord as D, type CreateSuppressionParams as E, type CreateTemplateParams as F, Groundmail as G, type CreateTenantParams as H, type CreateWebhookParams as I, DEFAULT_API_BASE_URL as J, type DailyRampLimitErrorDetails as K, type DeleteTenantResult as L, type DeliverabilityBucket as M, type DeliverabilityDomainInsight as N, type DeliverabilityInsightsResult as O, type DeliverabilityMailServerRelay as P, type DeliverabilityWindow as Q, type DmarcDailyPoint as R, type SendEmailResult as S, type DmarcMonitoring as T, type DmarcMonitoringDisabled as U, type DmarcReadiness as V, type DmarcReadinessVerdict as W, type DmarcSource as X, type DmarcSourceStatus as Y, type DmarcStatus as Z, type DnsProviderName as _, type ApiErrorCode as a, type TemplateStatus as a$, type DomainBimiAnalysis as a0, type DomainDetailResult as a1, type DomainDmarcAnalysis as a2, type DomainDnsAnalysis as a3, type DomainStatus as a4, type DomainTlsMode as a5, type DomainTrackingDns as a6, type DomainTrackingStatus as a7, type EmailListItem as a8, type EmailWebhookEventPayload as a9, type ListTenantsResult as aA, type MailServerSigningStatus as aB, type MailStream as aC, type Migration as aD, type MigrationDnsChange as aE, type MigrationDnsPlan as aF, type MigrationDomainItem as aG, type MigrationItemStatus as aH, type MigrationProvider as aI, type MigrationResource as aJ, type MigrationSummary as aK, type MigrationTemplateItem as aL, type MigrationTotals as aM, type MigrationWebhookItem as aN, type ReceivedEmail as aO, type ReceivedEmailAttachment as aP, type ReceivedEmailAttachmentMeta as aQ, type RemoteApplyDnsCredentials as aR, type RunMigrationOptions as aS, type SendEmailParams as aT, type StreamDeliverability as aU, type SuppressedErrorDetails as aV, type Suppression as aW, type Template as aX, type TemplateFormat as aY, type TemplateLintWarning as aZ, type TemplateStarter as a_, type EmailWebhookEventType as aa, type EnableDmarcParams as ab, type EnableDmarcResult as ac, type EnrollmentSkip as ad, type EventRecord as ae, type GroundmailOptions as af, type HeldBackErrorDetails as ag, type HeldBackReason as ah, type HeldBackRecipient as ai, type ListApiKeysParams as aj, type ListApiKeysResult as ak, type ListAutomationRunsParams as al, type ListAutomationRunsResult as am, type ListAutomationsResult as an, type ListDomainsParams as ao, type ListDomainsResult as ap, type ListEmailsParams as aq, type ListEmailsResult as ar, type ListReceivedEmailsParams as as, type ListReceivedEmailsResult as at, type ListSuppressionsParams as au, type ListSuppressionsResult as av, type ListTemplatesParams as aw, type ListTemplatesResult as ax, type ListTenantDomainsResult as ay, type ListTenantsParams as az, type ApiKey as b, type TemplateVersion as b0, type Tenant as b1, type TenantPauseSource as b2, type TenantRamp as b3, type TenantStats as b4, type TenantStatsResult as b5, type TenantStatus as b6, type TenantStreamPolicy as b7, type TestEmailWebhookParams as b8, type TestEmailWebhookResult as b9, type TriggerEventParams as ba, type TriggerEventResult as bb, type TwilioIntegrationResponse as bc, type TwilioIntegrationStatus as bd, type UpdateAutomationParams as be, type UpdateDomainParams as bf, type UpdateEmailParams as bg, type UpdateTemplateParams as bh, type UpdateTenantParams as bi, type UpdateWebhookParams as bj, type ValidateEmailResult as bk, type ValidationReason as bl, type ValidationVerdict as bm, type VerifyDomainResult as bn, type WebhookEmailTag as bo, type WebhookEndpoint as bp, type WebhookEndpointWithSecret as bq, type WebhookEventType as br, mergeMigrations as bs, type ApiKeyScope as c, type ApplyDnsParams as d, type ApplyDnsRecordResult as e, type ApplyDnsResult as f, type Asset as g, type Automation as h, type AutomationResult as i, type AutomationRun as j, type AutomationRunResponse as k, type AutomationRunStatus as l, type AutomationRunStep as m, type AutomationRunStepStatus as n, type AutomationStatus as o, type AutomationStep as p, type AutomationTrigger as q, type BounceType as r, type ConnectTwilioParams as s, type ContactWebhookEventPayload as t, type CreateApiKeyParams as u, type CreateApiKeyResult as v, type CreateAutomationParams as w, type CreateDomainParams as x, type CreateDomainResult as y, type CreateMigrationParams as z };
1794
+ export { type DmarcStatus as $, type ApiErrorBody as A, type BatchSendEmailResult as B, type CategoryOptOut as C, type DnsRecord as D, type CreateDomainResult as E, type CreateMigrationParams as F, Groundmail as G, type CreateSuppressionParams as H, type CreateTemplateParams as I, type CreateTenantParams as J, type CreateWebhookParams as K, DEFAULT_API_BASE_URL as L, type DailyRampLimitErrorDetails as M, type DeleteTenantResult as N, type DeliverabilityBucket as O, type DeliverabilityDomainInsight as P, type DeliverabilityInsightsResult as Q, type DeliverabilityMailServerRelay as R, type SendEmailResult as S, type DeliverabilityWindow as T, type DmarcDailyPoint as U, type DmarcMonitoring as V, type DmarcMonitoringDisabled as W, type DmarcReadiness as X, type DmarcReadinessVerdict as Y, type DmarcSource as Z, type DmarcSourceStatus as _, type ApiErrorCode as a, type SendEmailParams as a$, type DnsProviderName as a0, type Domain as a1, type DomainBimiAnalysis as a2, type DomainDetailResult as a3, type DomainDmarcAnalysis as a4, type DomainDnsAnalysis as a5, type DomainStatus as a6, type DomainTlsMode as a7, type DomainTrackingDns as a8, type DomainTrackingStatus as a9, type ListReceivedEmailsResult as aA, type ListSuppressionsParams as aB, type ListSuppressionsResult as aC, type ListTemplatesParams as aD, type ListTemplatesResult as aE, type ListTenantDomainsResult as aF, type ListTenantsParams as aG, type ListTenantsResult as aH, type MailServerSigningStatus as aI, type MailStream as aJ, type Migration as aK, type MigrationDnsChange as aL, type MigrationDnsPlan as aM, type MigrationDomainItem as aN, type MigrationItemStatus as aO, type MigrationProvider as aP, type MigrationResource as aQ, type MigrationSummary as aR, type MigrationTemplateItem as aS, type MigrationTotals as aT, type MigrationWebhookItem as aU, type ReceivedEmail as aV, type ReceivedEmailAttachment as aW, type ReceivedEmailAttachmentMeta as aX, type RemoteApplyDnsCredentials as aY, type RemoveCategoryOptOutOptions as aZ, type RunMigrationOptions as a_, type EmailListItem as aa, type EmailWebhookEventPayload as ab, type EmailWebhookEventType as ac, type EnableDmarcParams as ad, type EnableDmarcResult as ae, type EnrollmentSkip as af, type EventRecord as ag, type GroundmailAccessToken as ah, type GroundmailOptions as ai, type GroundmailTokenOptions as aj, type GroundmailTokenProvider as ak, type HeldBackErrorDetails as al, type HeldBackReason as am, type HeldBackRecipient as an, type ListApiKeysParams as ao, type ListApiKeysResult as ap, type ListAutomationRunsParams as aq, type ListAutomationRunsResult as ar, type ListAutomationsResult as as, type ListCategoryOptOutsParams as at, type ListCategoryOptOutsResult as au, type ListDomainsParams as av, type ListDomainsResult as aw, type ListEmailsParams as ax, type ListEmailsResult as ay, type ListReceivedEmailsParams as az, type ApiKey as b, type StreamDeliverability as b0, type SuppressedErrorDetails as b1, type Suppression as b2, type Template as b3, type TemplateFormat as b4, type TemplateLintWarning as b5, type TemplateStarter as b6, type TemplateStatus as b7, type TemplateVersion as b8, type Tenant as b9, mergeMigrations as bA, normalizeAccessToken as bB, type TenantPauseSource as ba, type TenantRamp as bb, type TenantStats as bc, type TenantStatsResult as bd, type TenantStatus as be, type TenantStreamPolicy as bf, type TestEmailWebhookParams as bg, type TestEmailWebhookResult as bh, type TriggerEventParams as bi, type TriggerEventResult as bj, type TwilioIntegrationResponse as bk, type TwilioIntegrationStatus as bl, type UpdateAutomationParams as bm, type UpdateDomainParams as bn, type UpdateEmailParams as bo, type UpdateTemplateParams as bp, type UpdateTenantParams as bq, type UpdateWebhookParams as br, type ValidateEmailResult as bs, type ValidationReason as bt, type ValidationVerdict as bu, type VerifyDomainResult as bv, type WebhookEmailTag as bw, type WebhookEndpoint as bx, type WebhookEndpointWithSecret as by, type WebhookEventType as bz, type ApiKeyScope as c, type ApplyDnsParams as d, type ApplyDnsRecordResult as e, type ApplyDnsResult as f, type Asset as g, type Automation as h, type AutomationResult as i, type AutomationRun as j, type AutomationRunResponse as k, type AutomationRunStatus as l, type AutomationRunStep as m, type AutomationRunStepStatus as n, type AutomationStatus as o, type AutomationStep as p, type AutomationTrigger as q, type BounceType as r, type CategoryOptOutCategory as s, type CategoryUnsubscribedErrorDetails as t, type ConnectTwilioParams as u, type ContactWebhookEventPayload as v, type CreateApiKeyParams as w, type CreateApiKeyResult as x, type CreateAutomationParams as y, type CreateDomainParams as z };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as ApiErrorBody, D as DnsRecord } from './client-CTG4zTKw.js';
2
- export { a as ApiErrorCode, b as ApiKey, c as ApiKeyScope, d as ApplyDnsParams, e as ApplyDnsRecordResult, f as ApplyDnsResult, g as Asset, h as Automation, i as AutomationResult, j as AutomationRun, k as AutomationRunResponse, l as AutomationRunStatus, m as AutomationRunStep, n as AutomationRunStepStatus, o as AutomationStatus, p as AutomationStep, q as AutomationTrigger, B as BatchSendEmailResult, r as BounceType, C as CategoryUnsubscribedErrorDetails, s as ConnectTwilioParams, t as ContactWebhookEventPayload, u as CreateApiKeyParams, v as CreateApiKeyResult, w as CreateAutomationParams, x as CreateDomainParams, y as CreateDomainResult, z as CreateMigrationParams, E as CreateSuppressionParams, F as CreateTemplateParams, H as CreateTenantParams, I as CreateWebhookParams, J as DEFAULT_API_BASE_URL, K as DailyRampLimitErrorDetails, L as DeleteTenantResult, M as DeliverabilityBucket, N as DeliverabilityDomainInsight, O as DeliverabilityInsightsResult, P as DeliverabilityMailServerRelay, Q as DeliverabilityWindow, R as DmarcDailyPoint, T as DmarcMonitoring, U as DmarcMonitoringDisabled, V as DmarcReadiness, W as DmarcReadinessVerdict, X as DmarcSource, Y as DmarcSourceStatus, Z as DmarcStatus, _ as DnsProviderName, $ as Domain, a0 as DomainBimiAnalysis, a1 as DomainDetailResult, a2 as DomainDmarcAnalysis, a3 as DomainDnsAnalysis, a4 as DomainStatus, a5 as DomainTlsMode, a6 as DomainTrackingDns, a7 as DomainTrackingStatus, a8 as EmailListItem, a9 as EmailWebhookEventPayload, aa as EmailWebhookEventType, ab as EnableDmarcParams, ac as EnableDmarcResult, ad as EnrollmentSkip, ae as EventRecord, G as Groundmail, af as GroundmailOptions, ag as HeldBackErrorDetails, ah as HeldBackReason, ai as HeldBackRecipient, aj as ListApiKeysParams, ak as ListApiKeysResult, al as ListAutomationRunsParams, am as ListAutomationRunsResult, an as ListAutomationsResult, ao as ListDomainsParams, ap as ListDomainsResult, aq as ListEmailsParams, ar as ListEmailsResult, as as ListReceivedEmailsParams, at as ListReceivedEmailsResult, au as ListSuppressionsParams, av as ListSuppressionsResult, aw as ListTemplatesParams, ax as ListTemplatesResult, ay as ListTenantDomainsResult, az as ListTenantsParams, aA as ListTenantsResult, aB as MailServerSigningStatus, aC as MailStream, aD as Migration, aE as MigrationDnsChange, aF as MigrationDnsPlan, aG as MigrationDomainItem, aH as MigrationItemStatus, aI as MigrationProvider, aJ as MigrationResource, aK as MigrationSummary, aL as MigrationTemplateItem, aM as MigrationTotals, aN as MigrationWebhookItem, aO as ReceivedEmail, aP as ReceivedEmailAttachment, aQ as ReceivedEmailAttachmentMeta, aR as RemoteApplyDnsCredentials, aS as RunMigrationOptions, aT as SendEmailParams, S as SendEmailResult, aU as StreamDeliverability, aV as SuppressedErrorDetails, aW as Suppression, aX as Template, aY as TemplateFormat, aZ as TemplateLintWarning, a_ as TemplateStarter, a$ as TemplateStatus, b0 as TemplateVersion, b1 as Tenant, b2 as TenantPauseSource, b3 as TenantRamp, b4 as TenantStats, b5 as TenantStatsResult, b6 as TenantStatus, b7 as TenantStreamPolicy, b8 as TestEmailWebhookParams, b9 as TestEmailWebhookResult, ba as TriggerEventParams, bb as TriggerEventResult, bc as TwilioIntegrationResponse, bd as TwilioIntegrationStatus, be as UpdateAutomationParams, bf as UpdateDomainParams, bg as UpdateEmailParams, bh as UpdateTemplateParams, bi as UpdateTenantParams, bj as UpdateWebhookParams, bk as ValidateEmailResult, bl as ValidationReason, bm as ValidationVerdict, bn as VerifyDomainResult, bo as WebhookEmailTag, bp as WebhookEndpoint, bq as WebhookEndpointWithSecret, br as WebhookEventType, bs as mergeMigrations } from './client-CTG4zTKw.js';
1
+ import { A as ApiErrorBody, D as DnsRecord } from './client-NSj8n5sB.js';
2
+ export { a as ApiErrorCode, b as ApiKey, c as ApiKeyScope, d as ApplyDnsParams, e as ApplyDnsRecordResult, f as ApplyDnsResult, g as Asset, h as Automation, i as AutomationResult, j as AutomationRun, k as AutomationRunResponse, l as AutomationRunStatus, m as AutomationRunStep, n as AutomationRunStepStatus, o as AutomationStatus, p as AutomationStep, q as AutomationTrigger, B as BatchSendEmailResult, r as BounceType, C as CategoryOptOut, s as CategoryOptOutCategory, t as CategoryUnsubscribedErrorDetails, u as ConnectTwilioParams, v as ContactWebhookEventPayload, w as CreateApiKeyParams, x as CreateApiKeyResult, y as CreateAutomationParams, z as CreateDomainParams, E as CreateDomainResult, F as CreateMigrationParams, H as CreateSuppressionParams, I as CreateTemplateParams, J as CreateTenantParams, K as CreateWebhookParams, L as DEFAULT_API_BASE_URL, M as DailyRampLimitErrorDetails, N as DeleteTenantResult, O as DeliverabilityBucket, P as DeliverabilityDomainInsight, Q as DeliverabilityInsightsResult, R as DeliverabilityMailServerRelay, T as DeliverabilityWindow, U as DmarcDailyPoint, V as DmarcMonitoring, W as DmarcMonitoringDisabled, X as DmarcReadiness, Y as DmarcReadinessVerdict, Z as DmarcSource, _ as DmarcSourceStatus, $ as DmarcStatus, a0 as DnsProviderName, a1 as Domain, a2 as DomainBimiAnalysis, a3 as DomainDetailResult, a4 as DomainDmarcAnalysis, a5 as DomainDnsAnalysis, a6 as DomainStatus, a7 as DomainTlsMode, a8 as DomainTrackingDns, a9 as DomainTrackingStatus, aa as EmailListItem, ab as EmailWebhookEventPayload, ac as EmailWebhookEventType, ad as EnableDmarcParams, ae as EnableDmarcResult, af as EnrollmentSkip, ag as EventRecord, G as Groundmail, ah as GroundmailAccessToken, ai as GroundmailOptions, aj as GroundmailTokenOptions, ak as GroundmailTokenProvider, al as HeldBackErrorDetails, am as HeldBackReason, an as HeldBackRecipient, ao as ListApiKeysParams, ap as ListApiKeysResult, aq as ListAutomationRunsParams, ar as ListAutomationRunsResult, as as ListAutomationsResult, at as ListCategoryOptOutsParams, au as ListCategoryOptOutsResult, av as ListDomainsParams, aw as ListDomainsResult, ax as ListEmailsParams, ay as ListEmailsResult, az as ListReceivedEmailsParams, aA as ListReceivedEmailsResult, aB as ListSuppressionsParams, aC as ListSuppressionsResult, aD as ListTemplatesParams, aE as ListTemplatesResult, aF as ListTenantDomainsResult, aG as ListTenantsParams, aH as ListTenantsResult, aI as MailServerSigningStatus, aJ as MailStream, aK as Migration, aL as MigrationDnsChange, aM as MigrationDnsPlan, aN as MigrationDomainItem, aO as MigrationItemStatus, aP as MigrationProvider, aQ as MigrationResource, aR as MigrationSummary, aS as MigrationTemplateItem, aT as MigrationTotals, aU as MigrationWebhookItem, aV as ReceivedEmail, aW as ReceivedEmailAttachment, aX as ReceivedEmailAttachmentMeta, aY as RemoteApplyDnsCredentials, aZ as RemoveCategoryOptOutOptions, a_ as RunMigrationOptions, a$ as SendEmailParams, S as SendEmailResult, b0 as StreamDeliverability, b1 as SuppressedErrorDetails, b2 as Suppression, b3 as Template, b4 as TemplateFormat, b5 as TemplateLintWarning, b6 as TemplateStarter, b7 as TemplateStatus, b8 as TemplateVersion, b9 as Tenant, ba as TenantPauseSource, bb as TenantRamp, bc as TenantStats, bd as TenantStatsResult, be as TenantStatus, bf as TenantStreamPolicy, bg as TestEmailWebhookParams, bh as TestEmailWebhookResult, bi as TriggerEventParams, bj as TriggerEventResult, bk as TwilioIntegrationResponse, bl as TwilioIntegrationStatus, bm as UpdateAutomationParams, bn as UpdateDomainParams, bo as UpdateEmailParams, bp as UpdateTemplateParams, bq as UpdateTenantParams, br as UpdateWebhookParams, bs as ValidateEmailResult, bt as ValidationReason, bu as ValidationVerdict, bv as VerifyDomainResult, bw as WebhookEmailTag, bx as WebhookEndpoint, by as WebhookEndpointWithSecret, bz as WebhookEventType, bA as mergeMigrations, bB as normalizeAccessToken } from './client-NSj8n5sB.js';
3
3
 
4
4
  type GroundmailErrorOptions = {
5
5
  code?: string;
package/dist/index.js CHANGED
@@ -6,9 +6,10 @@ import {
6
6
  buildSignatureHeader,
7
7
  mergeMigrations,
8
8
  mergeSpfInclude,
9
+ normalizeAccessToken,
9
10
  signWebhookPayload,
10
11
  verifyWebhookSignature
11
- } from "./chunk-QBGTN2WD.js";
12
+ } from "./chunk-NQWM7F3N.js";
12
13
 
13
14
  // src/simulator.ts
14
15
  var SIMULATOR_DOMAIN = "simulator.groundmail.dev";
@@ -42,6 +43,7 @@ export {
42
43
  isTestApiKey,
43
44
  mergeMigrations,
44
45
  mergeSpfInclude,
46
+ normalizeAccessToken,
45
47
  signWebhookPayload,
46
48
  simulatorAddress,
47
49
  verifyWebhookSignature
package/dist/payload.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Groundmail } from './client-CTG4zTKw.js';
1
+ import { G as Groundmail } from './client-NSj8n5sB.js';
2
2
 
3
3
  /**
4
4
  * Minimal Payload `SendEmailOptions` / address shapes used by this adapter.
package/dist/payload.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_API_BASE_URL,
3
3
  Groundmail
4
- } from "./chunk-QBGTN2WD.js";
4
+ } from "./chunk-NQWM7F3N.js";
5
5
 
6
6
  // src/payload.ts
7
7
  function resolveApiKey(args) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groundmail",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "description": "Groundmail transactional email API client",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -89,7 +89,7 @@
89
89
  "prepublishOnly": "npm run build && npm run build:nodemailer-bridge"
90
90
  },
91
91
  "dependencies": {
92
- "groundmail-nodemailer": "0.15.9"
92
+ "groundmail-nodemailer": "0.15.11"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@types/nodemailer": "^8.0.1",