@wraps.dev/cli 3.6.1 → 3.8.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/dist/cli.js CHANGED
@@ -27936,6 +27936,30 @@ function displayStatus(status2) {
27936
27936
  `${pc10.bold("Integration:")} ${pc10.cyan(status2.integrationLevel)}`,
27937
27937
  `${pc10.bold("Region:")} ${pc10.cyan(status2.region)}`
27938
27938
  ];
27939
+ if (status2.sending) {
27940
+ const { sandbox, sandboxUncertain } = status2.sending;
27941
+ if (sandboxUncertain) {
27942
+ infoLines.push(
27943
+ `${pc10.bold("Sending:")} ${pc10.yellow("could not determine (SES unreachable)")}`
27944
+ );
27945
+ } else if (sandbox) {
27946
+ infoLines.push(
27947
+ `${pc10.bold("Sending:")} ${pc10.yellow("SANDBOX")} ${pc10.dim("\u2014 you can only send to verified addresses")}`
27948
+ );
27949
+ } else {
27950
+ infoLines.push(`${pc10.bold("Sending:")} ${pc10.green("production")}`);
27951
+ }
27952
+ if (status2.sending.sentLast24Hours !== void 0 || status2.sending.max24HourSend !== void 0 || status2.sending.maxSendRate !== void 0) {
27953
+ infoLines.push(
27954
+ `${pc10.bold("Quota:")} ${pc10.cyan(`${status2.sending.sentLast24Hours ?? 0}/${status2.sending.max24HourSend ?? 0}`)} sent (24h) ${pc10.dim(`\xB7 max rate ${status2.sending.maxSendRate ?? 0}/s`)}`
27955
+ );
27956
+ }
27957
+ }
27958
+ if (status2.cloudFormationStacks && status2.cloudFormationStacks.length > 0) {
27959
+ infoLines.push(
27960
+ `${pc10.bold("CloudFormation stacks:")} ${pc10.cyan(status2.cloudFormationStacks.join(", "))}`
27961
+ );
27962
+ }
27939
27963
  if (status2.domains.length > 0) {
27940
27964
  const PURPOSE_DISPLAY = {
27941
27965
  transactional: "Transactional",
@@ -44912,10 +44936,14 @@ async function putTrackingDomain(sesv22, configSetName, trackingDomain, httpsPol
44912
44936
  new PutConfigurationSetTrackingOptionsCommand({
44913
44937
  ConfigurationSetName: configSetName,
44914
44938
  CustomRedirectDomain: trackingDomain,
44915
- ...httpsPolicy ? { HttpsPolicy: httpsPolicy } : {}
44939
+ HttpsPolicy: httpsPolicy
44916
44940
  })
44917
44941
  );
44918
44942
  }
44943
+ function trackingHttpsPolicy(trackingHttps) {
44944
+ return trackingHttps?.status === "active" ? "REQUIRE" : "OPTIONAL";
44945
+ }
44946
+ var HTTP_TRACKING_CONSEQUENCE = "Until then, https:// links in your emails will show recipients a certificate warning when clicked.";
44919
44947
  async function clearTrackingDomain(region, configSetName) {
44920
44948
  const ses = new SESClient4({ region });
44921
44949
  await ses.send(
@@ -45902,7 +45930,12 @@ async function applyTrackingDomain(ctx, value) {
45902
45930
  const host = value.toLowerCase();
45903
45931
  let appliedAt;
45904
45932
  try {
45905
- await putTrackingDomain(ctx.sesClient, ctx.candidate.configSetName, host);
45933
+ await putTrackingDomain(
45934
+ ctx.sesClient,
45935
+ ctx.candidate.configSetName,
45936
+ host,
45937
+ trackingHttpsPolicy(ctx.candidate.trackingHttps)
45938
+ );
45906
45939
  appliedAt = (/* @__PURE__ */ new Date()).toISOString();
45907
45940
  } catch (error) {
45908
45941
  if (!isTrackingDomainNotReady(error)) {
@@ -46024,6 +46057,26 @@ async function applyTrackingHttps(ctx, enable) {
46024
46057
  validationRecordPushed: result.validationRecordPushed
46025
46058
  };
46026
46059
  }
46060
+ function reportTrackingHttpsEnabled(candidate, httpsResult, reopenHint) {
46061
+ if (candidate.trackingHttps?.status === "active") {
46062
+ clack24.log.success(
46063
+ `HTTPS active (${candidate.trackingHttps.distributionDomain})`
46064
+ );
46065
+ return;
46066
+ }
46067
+ clack24.log.info(
46068
+ pc26.dim(
46069
+ `Certificate validation usually takes 5\u201330 minutes. ${reopenHint} ${HTTP_TRACKING_CONSEQUENCE}`
46070
+ )
46071
+ );
46072
+ if (httpsResult.pendingValidationRecord) {
46073
+ clack24.log.info(
46074
+ `${httpsResult.validationRecordPushed ? "Certificate validation record (created for you):" : "Add this DNS record to validate the certificate:"}
46075
+ ${pc26.cyan(httpsResult.pendingValidationRecord.name)}
46076
+ Type: ${httpsResult.pendingValidationRecord.type} Value: ${httpsResult.pendingValidationRecord.value}`
46077
+ );
46078
+ }
46079
+ }
46027
46080
  async function applyFlagMode(args) {
46028
46081
  const {
46029
46082
  opensFlag,
@@ -46154,6 +46207,25 @@ async function applyFlagMode(args) {
46154
46207
  } else {
46155
46208
  clack24.log.success(`Tracking domain set to ${trackingDomainFlag}`);
46156
46209
  await offerTrackingCname(ctx, trackingDomainFlag.toLowerCase());
46210
+ if (trackingHttpsFlag === void 0) {
46211
+ try {
46212
+ const httpsResult = await applyTrackingHttps(ctx, true);
46213
+ reportTrackingHttpsEnabled(
46214
+ candidate,
46215
+ httpsResult,
46216
+ `Re-run ${pc26.cyan(`wraps email domains config --domain ${candidate.domain} --tracking-https`)} once it's ISSUED.`
46217
+ );
46218
+ } catch (error) {
46219
+ clack24.log.warn(
46220
+ `Could not enable HTTPS for tracking links: ${describeTrackingHttpsError(error)}`
46221
+ );
46222
+ clack24.log.info(
46223
+ pc26.dim(
46224
+ `Retry later with: ${pc26.cyan(`wraps email domains config --domain ${candidate.domain} --tracking-https`)}. ${HTTP_TRACKING_CONSEQUENCE}`
46225
+ )
46226
+ );
46227
+ }
46228
+ }
46157
46229
  }
46158
46230
  trackCommand("email:domains:config", {
46159
46231
  success: true,
@@ -46393,24 +46465,11 @@ async function applyInteractiveMode(args) {
46393
46465
  }
46394
46466
  httpsProgress.stop();
46395
46467
  if (enabling) {
46396
- if (candidate.trackingHttps?.status === "active") {
46397
- clack24.log.success(
46398
- `HTTPS active (${candidate.trackingHttps.distributionDomain})`
46399
- );
46400
- } else {
46401
- clack24.log.info(
46402
- pc26.dim(
46403
- "Certificate validation usually takes 5\u201330 minutes. Reopen this menu once it's ISSUED."
46404
- )
46405
- );
46406
- if (httpsResult.pendingValidationRecord) {
46407
- clack24.log.info(
46408
- `${httpsResult.validationRecordPushed ? "Certificate validation record (created for you):" : "Add this DNS record to validate the certificate:"}
46409
- ${pc26.cyan(httpsResult.pendingValidationRecord.name)}
46410
- Type: ${httpsResult.pendingValidationRecord.type} Value: ${httpsResult.pendingValidationRecord.value}`
46411
- );
46412
- }
46413
- }
46468
+ reportTrackingHttpsEnabled(
46469
+ candidate,
46470
+ httpsResult,
46471
+ "Reopen this menu once it's ISSUED."
46472
+ );
46414
46473
  } else {
46415
46474
  clack24.log.success("HTTPS disabled for tracking links");
46416
46475
  }
@@ -46441,6 +46500,34 @@ async function applyInteractiveMode(args) {
46441
46500
  `Tracking domain set to ${value.toLowerCase()}`
46442
46501
  );
46443
46502
  await offerTrackingCname(ctx, value.toLowerCase());
46503
+ if (!candidate.trackingHttps) {
46504
+ const wantsHttps = await clack24.confirm({
46505
+ message: `Enable HTTPS for tracking links? ${pc26.dim("(creates a CloudFront distribution + certificate in your account)")}`,
46506
+ initialValue: true
46507
+ });
46508
+ if (!clack24.isCancel(wantsHttps) && wantsHttps) {
46509
+ const setupHttpsProgress = new DeploymentProgress();
46510
+ try {
46511
+ const httpsResult = await setupHttpsProgress.execute(
46512
+ "Enabling HTTPS",
46513
+ async () => applyTrackingHttps(ctx, true)
46514
+ );
46515
+ setupHttpsProgress.stop();
46516
+ reportTrackingHttpsEnabled(
46517
+ candidate,
46518
+ httpsResult,
46519
+ "Reopen this menu once it's ISSUED."
46520
+ );
46521
+ } catch (error) {
46522
+ setupHttpsProgress.stop();
46523
+ if (error instanceof WrapsError) {
46524
+ clack24.log.error(error.message);
46525
+ } else {
46526
+ throw error;
46527
+ }
46528
+ }
46529
+ }
46530
+ }
46444
46531
  break;
46445
46532
  }
46446
46533
  case "delivery": {
@@ -46874,7 +46961,8 @@ async function verifyDomain(options) {
46874
46961
  await putTrackingDomain(
46875
46962
  sesClient,
46876
46963
  targetConfigSetName,
46877
- trackedEntry.trackingDomain
46964
+ trackedEntry.trackingDomain,
46965
+ trackingHttpsPolicy(trackedEntry.trackingHttps)
46878
46966
  );
46879
46967
  trackedEntry.trackingDomainAppliedAt = (/* @__PURE__ */ new Date()).toISOString();
46880
46968
  addDomainToMetadata(metadata, trackedEntry);
@@ -47263,7 +47351,12 @@ Run ${pc27.cyan("wraps email init")} first to deploy email infrastructure.
47263
47351
  if (trackingDomain) {
47264
47352
  await progress.execute("Setting custom tracking domain", async () => {
47265
47353
  try {
47266
- await putTrackingDomain(sesClient, configSetName, trackingDomain);
47354
+ await putTrackingDomain(
47355
+ sesClient,
47356
+ configSetName,
47357
+ trackingDomain,
47358
+ "OPTIONAL"
47359
+ );
47267
47360
  trackingDomainAppliedAt = (/* @__PURE__ */ new Date()).toISOString();
47268
47361
  } catch (error) {
47269
47362
  if (!isTrackingDomainNotReady(error)) throw error;
@@ -47317,7 +47410,7 @@ Run ${pc27.cyan("wraps email init")} first to deploy email infrastructure.
47317
47410
  );
47318
47411
  clack25.log.info(
47319
47412
  pc27.dim(
47320
- `Retry later with: ${pc27.cyan(`wraps email domains config --domain ${domain} --tracking-https`)}`
47413
+ `Retry later with: ${pc27.cyan(`wraps email domains config --domain ${domain} --tracking-https`)}. ${HTTP_TRACKING_CONSEQUENCE}`
47321
47414
  )
47322
47415
  );
47323
47416
  }
@@ -47325,7 +47418,7 @@ Run ${pc27.cyan("wraps email init")} first to deploy email infrastructure.
47325
47418
  if (trackingHttpsResult?.trackingHttps.status === "pending" && !isJsonMode()) {
47326
47419
  clack25.log.info(
47327
47420
  pc27.dim(
47328
- `Certificate validation usually takes 5\u201330 minutes. Then run: ${pc27.cyan(`wraps email domains config --domain ${domain} --tracking-https`)}`
47421
+ `Certificate validation usually takes 5\u201330 minutes. Then run: ${pc27.cyan(`wraps email domains config --domain ${domain} --tracking-https`)}. ${HTTP_TRACKING_CONSEQUENCE}`
47329
47422
  )
47330
47423
  );
47331
47424
  }
@@ -47512,6 +47605,7 @@ async function listDomains() {
47512
47605
  (identity) => identity.IdentityType === "DOMAIN" || identity.IdentityName && !identity.IdentityName.includes("@")
47513
47606
  );
47514
47607
  let trackedDomains = [];
47608
+ let trackingHttpsByDomain = /* @__PURE__ */ new Map();
47515
47609
  try {
47516
47610
  const awsIdentity = await validateAWSCredentials();
47517
47611
  const metadata = await loadConnectionMetadata(
@@ -47520,6 +47614,15 @@ async function listDomains() {
47520
47614
  );
47521
47615
  if (metadata) {
47522
47616
  trackedDomains = getAllTrackedDomains(metadata);
47617
+ const emailConfig = metadata.services.email?.config;
47618
+ trackingHttpsByDomain = new Map(
47619
+ (emailConfig?.additionalDomains ?? []).map(
47620
+ (d6) => [d6.domain, d6.trackingHttps]
47621
+ )
47622
+ );
47623
+ if (emailConfig?.domain && emailConfig.tracking?.httpsEnabled) {
47624
+ trackingHttpsByDomain.set(emailConfig.domain, { status: "active" });
47625
+ }
47523
47626
  }
47524
47627
  } catch {
47525
47628
  }
@@ -47574,7 +47677,8 @@ Run ${pc27.cyan("wraps email domains add")} to add a domain.
47574
47677
  managed: !!tracked,
47575
47678
  isPrimary: tracked?.isPrimary ?? false,
47576
47679
  purpose: tracked?.purpose,
47577
- trackingDomain: tracked?.trackingDomain ?? null
47680
+ trackingDomain: tracked?.trackingDomain ?? null,
47681
+ trackingHttps: trackingHttpsByDomain.get(d6.name)?.status ?? null
47578
47682
  };
47579
47683
  }),
47580
47684
  totalCount: sesDomains.length,
@@ -47588,7 +47692,7 @@ Run ${pc27.cyan("wraps email domains add")} to add a domain.
47588
47692
  const statusIcon = d6.verified ? pc27.green("\u2713") : pc27.yellow("\u23F1");
47589
47693
  const dkimIcon = d6.dkimStatus === "SUCCESS" ? pc27.green("\u2713 SUCCESS") : pc27.yellow(`\u23F1 ${d6.dkimStatus}`);
47590
47694
  const label = tracked.isPrimary ? pc27.dim("Primary") : pc27.dim(PURPOSE_LABELS[tracked.purpose || "other"] || "General");
47591
- const trackingSuffix = tracked.trackingDomain ? ` ${pc27.dim("\u2192")} ${tracked.trackingDomain}` : "";
47695
+ const trackingSuffix = tracked.trackingDomain ? ` ${pc27.dim("\u2192")} ${tracked.trackingDomain} ${trackingHttpsByDomain.get(d6.name)?.status === "active" ? pc27.dim("(https)") : pc27.yellow("(http)")}` : "";
47592
47696
  return ` ${statusIcon} ${pc27.bold(d6.name.padEnd(30))} ${label.padEnd(24)} DKIM: ${dkimIcon}${trackingSuffix}`;
47593
47697
  });
47594
47698
  clack25.note(managedLines.join("\n"), "Managed by Wraps");
@@ -51719,6 +51823,7 @@ async function emailStatus(options) {
51719
51823
  }
51720
51824
  }
51721
51825
  let stackOutputs = {};
51826
+ let cloudFormationStacks;
51722
51827
  try {
51723
51828
  await ensurePulumiWorkDir({ accountId: identity.accountId, region });
51724
51829
  const stack = await pulumi24.automation.LocalWorkspace.selectStack({
@@ -51727,17 +51832,32 @@ async function emailStatus(options) {
51727
51832
  });
51728
51833
  stackOutputs = await stack.outputs();
51729
51834
  } catch (_error) {
51730
- progress.stop();
51731
- clack35.log.error("No email infrastructure found");
51732
- console.log(
51733
- `
51835
+ const cfCheck = await findWrapsCloudFormationStacks(region);
51836
+ if (cfCheck.checked && cfCheck.stacks.length > 0) {
51837
+ cloudFormationStacks = cfCheck.stacks;
51838
+ } else {
51839
+ progress.stop();
51840
+ clack35.log.error("No email infrastructure found");
51841
+ if (!cfCheck.checked) {
51842
+ console.log(
51843
+ pc37.dim(
51844
+ "\nCould not check for CloudFormation stacks (missing cloudformation:DescribeStacks).\n"
51845
+ )
51846
+ );
51847
+ }
51848
+ console.log(
51849
+ `
51734
51850
  Run ${pc37.cyan("wraps email init")} to deploy email infrastructure.
51735
51851
  `
51736
- );
51737
- process.exit(1);
51738
- return;
51852
+ );
51853
+ process.exit(1);
51854
+ return;
51855
+ }
51739
51856
  }
51740
- const domains = await listSESDomains(region);
51857
+ const [domains, sesAccountStatus] = await Promise.all([
51858
+ listSESDomains(region),
51859
+ getSESAccountStatus(region)
51860
+ ]);
51741
51861
  const { SESv2Client: SESv2Client12, GetEmailIdentityCommand: GetEmailIdentityCommand7 } = await import("@aws-sdk/client-sesv2");
51742
51862
  const sesv2Client = new SESv2Client12({ region });
51743
51863
  const metadata = await loadConnectionMetadata(identity.accountId, region);
@@ -51800,7 +51920,16 @@ Run ${pc37.cyan("wraps email init")} to deploy email infrastructure.
51800
51920
  customTrackingDomain: stackOutputs.customTrackingDomain?.value,
51801
51921
  httpsEnabled: stackOutputs.httpsTrackingEnabled?.value,
51802
51922
  cloudFrontDomain: stackOutputs.cloudFrontDomain?.value
51803
- } : void 0
51923
+ } : void 0,
51924
+ sending: {
51925
+ sandbox: sesAccountStatus.isSandbox,
51926
+ sandboxUncertain: sesAccountStatus.sandboxUncertain ?? false,
51927
+ max24HourSend: sesAccountStatus.sendQuota?.max24HourSend,
51928
+ maxSendRate: sesAccountStatus.sendQuota?.maxSendRate,
51929
+ sentLast24Hours: sesAccountStatus.sendQuota?.sentLast24Hours,
51930
+ enforcementStatus: sesAccountStatus.enforcementStatus
51931
+ },
51932
+ cloudFormationStacks
51804
51933
  };
51805
51934
  if (isJsonMode()) {
51806
51935
  jsonSuccess("email.status", statusData);
@@ -52654,6 +52783,32 @@ import { join as join14 } from "path";
52654
52783
 
52655
52784
  // ../template-render/src/mustache-case.ts
52656
52785
  init_esm_shims();
52786
+ var HANDLEBARS_BLOCK_HELPERS = /* @__PURE__ */ new Set(["if", "unless", "each", "with"]);
52787
+ function normalizePlainTextMustaches(text14, canonicalVars) {
52788
+ const canonicalByLower = /* @__PURE__ */ new Map();
52789
+ for (const name of canonicalVars) {
52790
+ canonicalByLower.set(name.toLowerCase(), name);
52791
+ }
52792
+ function restoreIdentifier(name) {
52793
+ return canonicalByLower.get(name.toLowerCase()) ?? name;
52794
+ }
52795
+ return text14.replace(
52796
+ /\{\{([#/]?)([A-Z][A-Z0-9_]*(?:\.[A-Z0-9_]+)*)((?:\s+[A-Z0-9_.]+)*)\s*\}\}/g,
52797
+ (match, sigil, name, args) => {
52798
+ const lower = name.toLowerCase();
52799
+ const isHelper = lower === "else" || HANDLEBARS_BLOCK_HELPERS.has(lower);
52800
+ const restoredArgs = args.split(/\s+/).filter(Boolean).map(restoreIdentifier).join(" ");
52801
+ if (isHelper) {
52802
+ const suffix = restoredArgs ? ` ${restoredArgs}` : "";
52803
+ return `{{${sigil}${lower}${suffix}}}`;
52804
+ }
52805
+ if (!args && canonicalByLower.has(lower)) {
52806
+ return `{{${sigil}${canonicalByLower.get(lower)}}}`;
52807
+ }
52808
+ return match;
52809
+ }
52810
+ );
52811
+ }
52657
52812
  function toSesVariableName(name) {
52658
52813
  if (!name.includes(".")) {
52659
52814
  return name;
@@ -53127,37 +53282,6 @@ import pc40 from "picocolors";
53127
53282
 
53128
53283
  // src/utils/email/template-render.ts
53129
53284
  init_esm_shims();
53130
-
53131
- // src/utils/email/template-mustache-case.ts
53132
- init_esm_shims();
53133
- var HANDLEBARS_BLOCK_HELPERS = /* @__PURE__ */ new Set(["if", "unless", "each", "with"]);
53134
- function normalizePlainTextMustaches(text14, canonicalVars) {
53135
- const canonicalByLower = /* @__PURE__ */ new Map();
53136
- for (const name of canonicalVars) {
53137
- canonicalByLower.set(name.toLowerCase(), name);
53138
- }
53139
- function restoreIdentifier(name) {
53140
- return canonicalByLower.get(name.toLowerCase()) ?? name;
53141
- }
53142
- return text14.replace(
53143
- /\{\{([#/]?)([A-Z][A-Z0-9_]*(?:\.[A-Z0-9_]+)*)((?:\s+[A-Z0-9_.]+)*)\s*\}\}/g,
53144
- (match, sigil, name, args) => {
53145
- const lower = name.toLowerCase();
53146
- const isHelper = lower === "else" || HANDLEBARS_BLOCK_HELPERS.has(lower);
53147
- const restoredArgs = args.split(/\s+/).filter(Boolean).map(restoreIdentifier).join(" ");
53148
- if (isHelper) {
53149
- const suffix = restoredArgs ? ` ${restoredArgs}` : "";
53150
- return `{{${sigil}${lower}${suffix}}}`;
53151
- }
53152
- if (!args && canonicalByLower.has(lower)) {
53153
- return `{{${sigil}${canonicalByLower.get(lower)}}}`;
53154
- }
53155
- return match;
53156
- }
53157
- );
53158
- }
53159
-
53160
- // src/utils/email/template-render.ts
53161
53285
  async function renderTemplateWithProxy(Component) {
53162
53286
  const accessedProps = /* @__PURE__ */ new Set();
53163
53287
  const props = new Proxy({}, {
@@ -68345,50 +68469,90 @@ function showHelp() {
68345
68469
  );
68346
68470
  console.log("Email Commands:");
68347
68471
  console.log(
68348
- ` ${pc72.cyan("email init")} Deploy new email infrastructure`
68472
+ ` ${pc72.cyan("email init")} Deploy new email infrastructure`
68473
+ );
68474
+ console.log(
68475
+ ` ${pc72.cyan("email check")} Check email deliverability for a domain`
68476
+ );
68477
+ console.log(
68478
+ ` ${pc72.cyan("email connect")} Connect to existing AWS SES`
68479
+ );
68480
+ console.log(
68481
+ ` ${pc72.cyan("email status")} Show email infrastructure details`
68482
+ );
68483
+ console.log(
68484
+ ` ${pc72.cyan("email plan")} Show SES pricing plan and cheaper options`
68485
+ );
68486
+ console.log(` ${pc72.cyan("email test")} Send a test email`);
68487
+ console.log(
68488
+ ` ${pc72.cyan("email verify")} Verify domain DNS records`
68489
+ );
68490
+ console.log(
68491
+ ` ${pc72.cyan("email sync")} Apply CLI updates to infrastructure`
68492
+ );
68493
+ console.log(` ${pc72.cyan("email upgrade")} Add features`);
68494
+ console.log(
68495
+ ` ${pc72.cyan("email restore")} Restore original configuration`
68496
+ );
68497
+ console.log(
68498
+ ` ${pc72.cyan("email destroy")} Remove email infrastructure`
68499
+ );
68500
+ console.log(
68501
+ ` ${pc72.cyan("email doctor")} Diagnose and clean up email infrastructure`
68502
+ );
68503
+ console.log(` ${pc72.cyan("email domains add")} Add a domain to SES`);
68504
+ console.log(` ${pc72.cyan("email domains list")} List all domains`);
68505
+ console.log(` ${pc72.cyan("email domains remove")} Remove a domain`);
68506
+ console.log(
68507
+ ` ${pc72.cyan("email domains verify")} Check domain verification status`
68349
68508
  );
68350
68509
  console.log(
68351
- ` ${pc72.cyan("email check")} Check email deliverability for a domain`
68510
+ ` ${pc72.cyan("email domains get-dkim")} Show DKIM tokens for a domain`
68352
68511
  );
68353
68512
  console.log(
68354
- ` ${pc72.cyan("email connect")} Connect to existing AWS SES`
68513
+ ` ${pc72.cyan("email domains config")} Configure domain tracking, TLS, and archiving`
68355
68514
  );
68356
68515
  console.log(
68357
- ` ${pc72.cyan("email status")} Show email infrastructure details`
68516
+ ` ${pc72.cyan("email inbound init")} Enable inbound email receiving`
68358
68517
  );
68359
68518
  console.log(
68360
- ` ${pc72.cyan("email plan")} Show SES pricing plan and cheaper options`
68519
+ ` ${pc72.cyan("email inbound status")} Show inbound email status`
68361
68520
  );
68362
- console.log(` ${pc72.cyan("email test")} Send a test email`);
68363
- console.log(` ${pc72.cyan("email verify")} Verify domain DNS records`);
68364
68521
  console.log(
68365
- ` ${pc72.cyan("email sync")} Apply CLI updates to infrastructure`
68522
+ ` ${pc72.cyan("email inbound verify")} Verify inbound DNS records`
68366
68523
  );
68367
- console.log(` ${pc72.cyan("email upgrade")} Add features`);
68368
68524
  console.log(
68369
- ` ${pc72.cyan("email restore")} Restore original configuration`
68525
+ ` ${pc72.cyan("email inbound test")} Send test email and verify receipt`
68370
68526
  );
68371
68527
  console.log(
68372
- ` ${pc72.cyan("email destroy")} Remove email infrastructure`
68528
+ ` ${pc72.cyan("email inbound add")} Add an inbound receiving domain`
68373
68529
  );
68374
68530
  console.log(
68375
- ` ${pc72.cyan("email doctor")} Diagnose and clean up email infrastructure`
68531
+ ` ${pc72.cyan("email inbound remove")} Remove an inbound receiving domain`
68376
68532
  );
68377
- console.log(` ${pc72.cyan("email domains add")} Add a domain to SES`);
68378
- console.log(` ${pc72.cyan("email domains list")} List all domains`);
68379
- console.log(` ${pc72.cyan("email domains remove")} Remove a domain`);
68380
68533
  console.log(
68381
- ` ${pc72.cyan("email inbound init")} Enable inbound email receiving`
68534
+ ` ${pc72.cyan("email inbound destroy")} Remove inbound email infrastructure`
68382
68535
  );
68383
- console.log(` ${pc72.cyan("email inbound status")} Show inbound email status`);
68384
68536
  console.log(
68385
- ` ${pc72.cyan("email inbound verify")} Verify inbound DNS records`
68537
+ ` ${pc72.cyan("email reply init")} Set up signed reply-to threading`
68386
68538
  );
68387
68539
  console.log(
68388
- ` ${pc72.cyan("email inbound test")} Send test email and verify receipt`
68540
+ ` ${pc72.cyan("email reply rotate")} Rotate the reply-threading signing secret`
68389
68541
  );
68390
68542
  console.log(
68391
- ` ${pc72.cyan("email inbound destroy")} Remove inbound email infrastructure
68543
+ ` ${pc72.cyan("email reply status")} Show reply-threading status`
68544
+ );
68545
+ console.log(
68546
+ ` ${pc72.cyan("email reply destroy")} Remove reply-threading infrastructure`
68547
+ );
68548
+ console.log(
68549
+ ` ${pc72.cyan("email reply decode")} Decode a reply-to address`
68550
+ );
68551
+ console.log(
68552
+ ` ${pc72.cyan("email logs list")} List recent email sends`
68553
+ );
68554
+ console.log(
68555
+ ` ${pc72.cyan("email logs get")} Show details for one message
68392
68556
  `
68393
68557
  );
68394
68558
  console.log("Agent Commands:");
@@ -68422,7 +68586,10 @@ function showHelp() {
68422
68586
  ` ${pc72.cyan("email workflows validate")} Validate workflow files`
68423
68587
  );
68424
68588
  console.log(
68425
- ` ${pc72.cyan("email workflows push")} Push workflows to dashboard
68589
+ ` ${pc72.cyan("email workflows push")} Push workflows to dashboard`
68590
+ );
68591
+ console.log(
68592
+ ` ${pc72.cyan("workflow init")} Scaffold a cross-channel workflow (email \u2192 SMS)
68426
68593
  `
68427
68594
  );
68428
68595
  console.log("SMS Commands:");