groundmail 0.29.0 → 0.29.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.
package/dist/authjs.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Groundmail } from './client-B9Pa_09D.js';
1
+ import { G as Groundmail } from './client-BkJCGT45.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-ZH3KZR7I.js";
4
+ } from "./chunk-PMQDWLBY.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-B9Pa_09D.js';
1
+ import { S as SendEmailResult, G as Groundmail } from './client-BkJCGT45.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-ZH3KZR7I.js";
4
+ } from "./chunk-PMQDWLBY.js";
5
5
 
6
6
  // src/better-auth.ts
7
7
  function linkHtml(label, url) {
@@ -70,6 +70,13 @@ function isSpfRecord(value) {
70
70
  return value.trim().toLowerCase().startsWith("v=spf1");
71
71
  }
72
72
 
73
+ // src/dns/dmarc.ts
74
+ var KEPT_DMARC_DETAIL = "You already have a DMARC record. Nothing to change.";
75
+ var ALREADY_SET_DETAIL = "Already set. Nothing to change.";
76
+ function isDmarcValue(value) {
77
+ return /^v=dmarc1\b/i.test(value.trim().replace(/^"/, ""));
78
+ }
79
+
73
80
  // src/dns/cloudflare.ts
74
81
  function relativeName(fqdn2, zone) {
75
82
  const domain = zone.replace(/\.$/, "").toLowerCase();
@@ -125,6 +132,10 @@ function createCloudflareProvider(options) {
125
132
  const recordType = record.type.toUpperCase();
126
133
  const name = relativeName(record.host, zoneName);
127
134
  const absoluteName = name === "@" ? zoneName : `${name}.${zoneName}`;
135
+ if (record.already_set) {
136
+ results.push({ purpose: record.purpose, host: record.host, action: "unchanged", detail: ALREADY_SET_DETAIL });
137
+ continue;
138
+ }
128
139
  if (recordType === "CNAME") {
129
140
  const target = record.value.replace(/\.$/, "").toLowerCase();
130
141
  const existingList2 = await cf(
@@ -266,10 +277,13 @@ function createCloudflareProvider(options) {
266
277
  });
267
278
  continue;
268
279
  }
280
+ if (record.purpose === "DMARC" && (existingList || []).some((r) => isDmarcValue(r.content))) {
281
+ results.push({ purpose: record.purpose, host: record.host, action: "unchanged", detail: KEPT_DMARC_DETAIL });
282
+ continue;
283
+ }
269
284
  const replaceable = (existingList || []).find((r) => {
270
285
  if (record.purpose === "Domain ownership") return r.content.includes("groundmail-verify=");
271
286
  if (record.purpose === "DKIM") return r.content.toLowerCase().includes("v=dkim1");
272
- if (record.purpose === "DMARC") return r.content.toLowerCase().includes("v=dmarc1");
273
287
  return false;
274
288
  });
275
289
  if (replaceable) {
@@ -329,7 +343,6 @@ function ownedTxt(purpose, value) {
329
343
  const lower = value.toLowerCase();
330
344
  if (purpose === "Domain ownership") return lower.includes("groundmail-verify=");
331
345
  if (purpose === "DKIM") return lower.includes("v=dkim1");
332
- if (purpose === "DMARC") return lower.includes("v=dmarc1");
333
346
  return false;
334
347
  }
335
348
  async function applyToRecordStore(zone, records, store) {
@@ -341,6 +354,10 @@ async function applyToRecordStore(zone, records, store) {
341
354
  const name = relativeName2(record.host, zone);
342
355
  const value = normalizeValue(type, record.value);
343
356
  const done = (action, detail) => results.push({ purpose: record.purpose, host: record.host, action, ...detail ? { detail } : {} });
357
+ if (record.already_set) {
358
+ done("unchanged", ALREADY_SET_DETAIL);
359
+ continue;
360
+ }
344
361
  if (type === "CNAME") {
345
362
  const existing = at("CNAME", name)[0];
346
363
  if (existing && normalizeValue(type, existing.value) === value) {
@@ -388,6 +405,10 @@ async function applyToRecordStore(zone, records, store) {
388
405
  done("unchanged");
389
406
  continue;
390
407
  }
408
+ if (record.purpose === "DMARC" && sameName.some((row) => isDmarcValue(normalizeValue(type, row.value)))) {
409
+ done("unchanged", KEPT_DMARC_DETAIL);
410
+ continue;
411
+ }
391
412
  const replaceable = sameName.find((row) => ownedTxt(record.purpose, normalizeValue(type, row.value)));
392
413
  if (replaceable) {
393
414
  await store.update(replaceable, { name, type, value });
@@ -521,6 +542,10 @@ function createGoDaddyKeyProvider(options) {
521
542
  for (const record of records) {
522
543
  const recordType = record.type.toUpperCase();
523
544
  const name = relativeName3(record.host, zone);
545
+ if (record.already_set) {
546
+ results.push({ purpose: record.purpose, host: record.host, action: "unchanged", detail: ALREADY_SET_DETAIL });
547
+ continue;
548
+ }
524
549
  if (recordType === "CNAME") {
525
550
  const target = record.value.replace(/\.$/, "");
526
551
  const existing2 = await gd(
@@ -622,10 +647,13 @@ function createGoDaddyKeyProvider(options) {
622
647
  results.push({ purpose: record.purpose, host: record.host, action: "unchanged" });
623
648
  continue;
624
649
  }
650
+ if (record.purpose === "DMARC" && list.some((r) => isDmarcValue(r.data))) {
651
+ results.push({ purpose: record.purpose, host: record.host, action: "unchanged", detail: KEPT_DMARC_DETAIL });
652
+ continue;
653
+ }
625
654
  const replaceableIndex = list.findIndex((r) => {
626
655
  if (record.purpose === "Domain ownership") return r.data.includes("groundmail-verify=");
627
656
  if (record.purpose === "DKIM") return r.data.toLowerCase().includes("v=dkim1");
628
- if (record.purpose === "DMARC") return r.data.toLowerCase().includes("v=dmarc1");
629
657
  return false;
630
658
  });
631
659
  const next = replaceableIndex >= 0 ? list.map(
@@ -913,6 +941,10 @@ function createVercelProvider(options) {
913
941
  for (const record of records) {
914
942
  const recordType = record.type.toUpperCase();
915
943
  const name = relativeName4(record.host, zone);
944
+ if (record.already_set) {
945
+ results.push({ purpose: record.purpose, host: record.host, action: "unchanged", detail: ALREADY_SET_DETAIL });
946
+ continue;
947
+ }
916
948
  if (recordType === "CNAME") {
917
949
  const target = record.value.replace(/\.$/, "").toLowerCase();
918
950
  const existing = cached.find(
@@ -978,7 +1010,7 @@ function createVercelProvider(options) {
978
1010
  }
979
1011
  if (record.purpose === "SPF") {
980
1012
  const spfRecords = cached.filter(
981
- (row) => row.type === "TXT" && row.name === "" && isSpfRecord(row.value)
1013
+ (row) => row.type === "TXT" && row.name === name && isSpfRecord(row.value)
982
1014
  );
983
1015
  const existing = spfRecords[0];
984
1016
  const includeHost = record.value.match(/include:([^\s]+)/i)?.[1] || "spf.groundmail.dev";
@@ -994,7 +1026,7 @@ function createVercelProvider(options) {
994
1026
  } else {
995
1027
  await vercel(`/v1/domains/records/${existing.id}`, {
996
1028
  method: "PATCH",
997
- body: JSON.stringify({ type: "TXT", name: "", value: merged, ttl: 60 })
1029
+ body: JSON.stringify({ type: "TXT", name, value: merged, ttl: 60 })
998
1030
  });
999
1031
  results.push({
1000
1032
  purpose: record.purpose,
@@ -1006,7 +1038,7 @@ function createVercelProvider(options) {
1006
1038
  } else {
1007
1039
  await vercel(`/v2/domains/${encodeURIComponent(zone)}/records`, {
1008
1040
  method: "POST",
1009
- body: JSON.stringify({ type: "TXT", name: "", value: merged, ttl: 60 })
1041
+ body: JSON.stringify({ type: "TXT", name, value: merged, ttl: 60 })
1010
1042
  });
1011
1043
  results.push({
1012
1044
  purpose: record.purpose,
@@ -1024,10 +1056,13 @@ function createVercelProvider(options) {
1024
1056
  results.push({ purpose: record.purpose, host: record.host, action: "unchanged" });
1025
1057
  continue;
1026
1058
  }
1059
+ if (record.purpose === "DMARC" && existingList.some((row) => isDmarcValue(row.value))) {
1060
+ results.push({ purpose: record.purpose, host: record.host, action: "unchanged", detail: KEPT_DMARC_DETAIL });
1061
+ continue;
1062
+ }
1027
1063
  const replaceable = existingList.find((row) => {
1028
1064
  if (record.purpose === "Domain ownership") return row.value.includes("groundmail-verify=");
1029
1065
  if (record.purpose === "DKIM") return row.value.toLowerCase().includes("v=dkim1");
1030
- if (record.purpose === "DMARC") return row.value.toLowerCase().includes("v=dmarc1");
1031
1066
  return false;
1032
1067
  });
1033
1068
  if (replaceable) {
package/dist/clerk.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Groundmail, S as SendEmailResult } from './client-B9Pa_09D.js';
1
+ import { G as Groundmail, S as SendEmailResult } from './client-BkJCGT45.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-ZH3KZR7I.js";
4
+ } from "./chunk-PMQDWLBY.js";
5
5
 
6
6
  // src/clerk.ts
7
7
  function resolveApiKey(options) {
@@ -958,6 +958,11 @@ type DnsRecord = {
958
958
  purpose: string;
959
959
  /** MX preference when `type` is `MX`. Mail hostname is in `value`. */
960
960
  priority?: number;
961
+ /**
962
+ * The domain already publishes a record that does this job (its own DMARC record).
963
+ * `value` is what is published now; nothing to add or change, and apply leaves it alone.
964
+ */
965
+ already_set?: boolean;
961
966
  };
962
967
  type CreateDomainParams = {
963
968
  name: string;
@@ -1015,9 +1020,11 @@ type VerifyDomainResult = {
1015
1020
  verified: boolean;
1016
1021
  checks?: {
1017
1022
  ownership: boolean;
1023
+ /** True when SPF needs nothing more. Always true for a main domain (example.com), which needs no SPF change. */
1018
1024
  spf: boolean;
1019
1025
  dkim: boolean;
1020
1026
  dmarc: boolean;
1027
+ return_path?: boolean;
1021
1028
  };
1022
1029
  auto?: boolean;
1023
1030
  inbound_configured?: boolean;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as ApiErrorBody, D as DnsRecord } from './client-B9Pa_09D.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 InReplyToEmail, ap as ListApiKeysParams, aq as ListApiKeysResult, ar as ListAutomationRunsParams, as as ListAutomationRunsResult, at as ListAutomationsResult, au as ListCategoryOptOutsParams, av as ListCategoryOptOutsResult, aw as ListDomainsParams, ax as ListDomainsResult, ay as ListEmailsParams, az as ListEmailsResult, aA as ListReceivedEmailsParams, aB as ListReceivedEmailsResult, aC as ListSuppressionsParams, aD as ListSuppressionsResult, aE as ListTemplatesParams, aF as ListTemplatesResult, aG as ListTenantDomainsResult, aH as ListTenantsParams, aI as ListTenantsResult, aJ as ListTestInboxEmailsParams, aK as ListTestInboxEmailsResult, aL as MailServerSigningStatus, aM as MailStream, aN as Migration, aO as MigrationDnsChange, aP as MigrationDnsPlan, aQ as MigrationDomainItem, aR as MigrationItemStatus, aS as MigrationProvider, aT as MigrationResource, aU as MigrationSummary, aV as MigrationTemplateItem, aW as MigrationTotals, aX as MigrationWebhookItem, aY as ReceivedEmail, aZ as ReceivedEmailAttachment, a_ as ReceivedEmailAttachmentMeta, a$ as RemoteApplyDnsCredentials, b0 as RemoveCategoryOptOutOptions, b1 as RunMigrationOptions, b2 as SendEmailParams, S as SendEmailResult, b3 as StreamDeliverability, b4 as SuppressedErrorDetails, b5 as Suppression, b6 as TEST_INBOX_WAIT_DEFAULT_MS, b7 as TEST_INBOX_WAIT_MAX_SECONDS, b8 as Template, b9 as TemplateFormat, ba as TemplateLintWarning, bb as TemplateStarter, bc as TemplateStatus, bd as TemplateVersion, be as Tenant, bf as TenantPauseSource, bg as TenantRamp, bh as TenantStats, bi as TenantStatsResult, bj as TenantStatus, bk as TenantStreamPolicy, bl as TestEmailWebhookParams, bm as TestEmailWebhookResult, bn as TestInbox, bo as TestInboxAddressOptions, bp as TestInboxEmail, bq as TestInboxEmailDetail, br as TestInboxHeader, bs as TestInboxResource, bt as TestInboxUsage, bu as TriggerEventParams, bv as TriggerEventResult, bw as TwilioIntegrationResponse, bx as TwilioIntegrationStatus, by as UpdateAutomationParams, bz as UpdateDomainParams, bA as UpdateEmailParams, bB as UpdateTemplateParams, bC as UpdateTenantParams, bD as UpdateWebhookParams, bE as ValidateEmailResult, bF as ValidationReason, bG as ValidationVerdict, bH as VerifyDomainResult, bI as WaitForTestEmailParams, bJ as WebhookEmailTag, bK as WebhookEndpoint, bL as WebhookEndpointWithSecret, bM as WebhookEventType, bN as mergeMigrations, bO as normalizeAccessToken } from './client-B9Pa_09D.js';
1
+ import { A as ApiErrorBody, D as DnsRecord } from './client-BkJCGT45.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 InReplyToEmail, ap as ListApiKeysParams, aq as ListApiKeysResult, ar as ListAutomationRunsParams, as as ListAutomationRunsResult, at as ListAutomationsResult, au as ListCategoryOptOutsParams, av as ListCategoryOptOutsResult, aw as ListDomainsParams, ax as ListDomainsResult, ay as ListEmailsParams, az as ListEmailsResult, aA as ListReceivedEmailsParams, aB as ListReceivedEmailsResult, aC as ListSuppressionsParams, aD as ListSuppressionsResult, aE as ListTemplatesParams, aF as ListTemplatesResult, aG as ListTenantDomainsResult, aH as ListTenantsParams, aI as ListTenantsResult, aJ as ListTestInboxEmailsParams, aK as ListTestInboxEmailsResult, aL as MailServerSigningStatus, aM as MailStream, aN as Migration, aO as MigrationDnsChange, aP as MigrationDnsPlan, aQ as MigrationDomainItem, aR as MigrationItemStatus, aS as MigrationProvider, aT as MigrationResource, aU as MigrationSummary, aV as MigrationTemplateItem, aW as MigrationTotals, aX as MigrationWebhookItem, aY as ReceivedEmail, aZ as ReceivedEmailAttachment, a_ as ReceivedEmailAttachmentMeta, a$ as RemoteApplyDnsCredentials, b0 as RemoveCategoryOptOutOptions, b1 as RunMigrationOptions, b2 as SendEmailParams, S as SendEmailResult, b3 as StreamDeliverability, b4 as SuppressedErrorDetails, b5 as Suppression, b6 as TEST_INBOX_WAIT_DEFAULT_MS, b7 as TEST_INBOX_WAIT_MAX_SECONDS, b8 as Template, b9 as TemplateFormat, ba as TemplateLintWarning, bb as TemplateStarter, bc as TemplateStatus, bd as TemplateVersion, be as Tenant, bf as TenantPauseSource, bg as TenantRamp, bh as TenantStats, bi as TenantStatsResult, bj as TenantStatus, bk as TenantStreamPolicy, bl as TestEmailWebhookParams, bm as TestEmailWebhookResult, bn as TestInbox, bo as TestInboxAddressOptions, bp as TestInboxEmail, bq as TestInboxEmailDetail, br as TestInboxHeader, bs as TestInboxResource, bt as TestInboxUsage, bu as TriggerEventParams, bv as TriggerEventResult, bw as TwilioIntegrationResponse, bx as TwilioIntegrationStatus, by as UpdateAutomationParams, bz as UpdateDomainParams, bA as UpdateEmailParams, bB as UpdateTemplateParams, bC as UpdateTenantParams, bD as UpdateWebhookParams, bE as ValidateEmailResult, bF as ValidationReason, bG as ValidationVerdict, bH as VerifyDomainResult, bI as WaitForTestEmailParams, bJ as WebhookEmailTag, bK as WebhookEndpoint, bL as WebhookEndpointWithSecret, bM as WebhookEventType, bN as mergeMigrations, bO as normalizeAccessToken } from './client-BkJCGT45.js';
3
3
 
4
4
  type GroundmailErrorOptions = {
5
5
  code?: string;
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  normalizeAccessToken,
13
13
  signWebhookPayload,
14
14
  verifyWebhookSignature
15
- } from "./chunk-ZH3KZR7I.js";
15
+ } from "./chunk-PMQDWLBY.js";
16
16
 
17
17
  // src/simulator.ts
18
18
  var SIMULATOR_DOMAIN = "simulator.groundmail.dev";
package/dist/payload.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Groundmail } from './client-B9Pa_09D.js';
1
+ import { G as Groundmail } from './client-BkJCGT45.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-ZH3KZR7I.js";
4
+ } from "./chunk-PMQDWLBY.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.29.0",
3
+ "version": "0.29.1",
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.17"
92
+ "groundmail-nodemailer": "0.15.18"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@types/nodemailer": "^8.0.1",