groundmail-cli 0.26.3 → 0.27.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 +15 -0
- package/dist/cli.js +79 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -63,6 +63,21 @@ SENDGRID_API_KEY=… groundmail migrate sendgrid --dry-run # import from SendG
|
|
|
63
63
|
|
|
64
64
|
Run `groundmail --help` or `groundmail <command> --help` for flags.
|
|
65
65
|
|
|
66
|
+
## Email testing
|
|
67
|
+
|
|
68
|
+
Your team has a test domain (`<team>.test.groundmail.dev`). Mail sent there from any provider is
|
|
69
|
+
caught and never delivered. Get a fresh address, have your app send to it, then wait for it:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
TO=$(groundmail test-inbox address --prefix signup) # signup-k3m9x2pq@acme.test.groundmail.dev
|
|
73
|
+
# …trigger your app's signup with $TO…
|
|
74
|
+
groundmail test-inbox wait --to "$TO" --timeout 30 # prints the subject, code and links
|
|
75
|
+
groundmail test-inbox wait --to "$TO" --json | jq -r .email.code
|
|
76
|
+
groundmail test-inbox list --to "$TO"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`wait` exits 2 when nothing arrives in time. Docs: https://docs.groundmail.dev/email-testing
|
|
80
|
+
|
|
66
81
|
## Tenants
|
|
67
82
|
|
|
68
83
|
If you send email for your own customers, give each one a tenant: its own domains,
|
package/dist/cli.js
CHANGED
|
@@ -1452,7 +1452,7 @@ function trimUrl(value) {
|
|
|
1452
1452
|
}
|
|
1453
1453
|
|
|
1454
1454
|
// package.json
|
|
1455
|
-
var version = "0.
|
|
1455
|
+
var version = "0.27.0";
|
|
1456
1456
|
|
|
1457
1457
|
// src/user-agent.ts
|
|
1458
1458
|
function buildUserAgent(own) {
|
|
@@ -3745,6 +3745,80 @@ Updated the DMARC record with ${result2.applied.provider}.`);
|
|
|
3745
3745
|
}
|
|
3746
3746
|
}
|
|
3747
3747
|
|
|
3748
|
+
// src/commands/test-inbox/test-inbox.ts
|
|
3749
|
+
function readFlag24(args, flag) {
|
|
3750
|
+
const index = args.indexOf(flag);
|
|
3751
|
+
if (index === -1) return void 0;
|
|
3752
|
+
return args[index + 1];
|
|
3753
|
+
}
|
|
3754
|
+
async function createTestInboxClient(apiKey, baseUrl) {
|
|
3755
|
+
const { Groundmail } = await import("groundmail");
|
|
3756
|
+
return new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
3757
|
+
}
|
|
3758
|
+
function formatTestEmail(email) {
|
|
3759
|
+
const lines = [
|
|
3760
|
+
`Subject: ${email.subject}`,
|
|
3761
|
+
`From: ${email.from}`,
|
|
3762
|
+
`To: ${email.to.join(", ")}`,
|
|
3763
|
+
`Code: ${email.code ?? "(none found)"}`
|
|
3764
|
+
];
|
|
3765
|
+
if (email.links.length) {
|
|
3766
|
+
lines.push("Links:");
|
|
3767
|
+
for (const link of email.links) lines.push(` ${link}`);
|
|
3768
|
+
} else {
|
|
3769
|
+
lines.push("Links: (none)");
|
|
3770
|
+
}
|
|
3771
|
+
lines.push(`Id: ${email.id}`);
|
|
3772
|
+
return lines.join("\n");
|
|
3773
|
+
}
|
|
3774
|
+
var USAGE = "Usage: groundmail test-inbox address [--prefix signup] | wait --to <address> [--timeout 30] [--since <iso>] [--json] | list [--to <address>] [--json]";
|
|
3775
|
+
async function runTestInboxCommand(subcommand, args, env = process.env) {
|
|
3776
|
+
if (!subcommand || !["address", "wait", "list"].includes(subcommand)) return { exitCode: 1, error: USAGE };
|
|
3777
|
+
const apiKey = readFlag24(args, "--api-key") || env.GROUNDMAIL_API_KEY;
|
|
3778
|
+
if (!apiKey) return { exitCode: 1, error: "Missing API key. Run groundmail login, set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
3779
|
+
const json = args.includes("--json");
|
|
3780
|
+
try {
|
|
3781
|
+
const client2 = await createTestInboxClient(apiKey, readFlag24(args, "--base-url"));
|
|
3782
|
+
if (subcommand === "address") {
|
|
3783
|
+
console.log(await client2.testInbox.address({ prefix: readFlag24(args, "--prefix") }));
|
|
3784
|
+
return { exitCode: 0 };
|
|
3785
|
+
}
|
|
3786
|
+
if (subcommand === "list") {
|
|
3787
|
+
const result = await client2.testInbox.list({
|
|
3788
|
+
to: readFlag24(args, "--to"),
|
|
3789
|
+
since: readFlag24(args, "--since"),
|
|
3790
|
+
limit: readFlag24(args, "--limit") ? Number(readFlag24(args, "--limit")) : void 0
|
|
3791
|
+
});
|
|
3792
|
+
if (json) console.log(JSON.stringify(result));
|
|
3793
|
+
else if (!result.emails.length) console.log("No test emails yet.");
|
|
3794
|
+
else {
|
|
3795
|
+
for (const email of result.emails) {
|
|
3796
|
+
console.log(`${email.received_at} ${email.id} ${email.to.join(", ")} ${email.subject}${email.code ? ` code ${email.code}` : ""}`);
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
return { exitCode: 0 };
|
|
3800
|
+
}
|
|
3801
|
+
const to = readFlag24(args, "--to");
|
|
3802
|
+
if (!to) return { exitCode: 1, error: "Missing --to. Usage: groundmail test-inbox wait --to signup-k3m9x2pq@acme.test.groundmail.dev" };
|
|
3803
|
+
const timeoutRaw = readFlag24(args, "--timeout");
|
|
3804
|
+
const seconds = timeoutRaw === void 0 ? 30 : Number(timeoutRaw);
|
|
3805
|
+
if (!Number.isFinite(seconds) || seconds < 0) return { exitCode: 1, error: "--timeout must be a number of seconds" };
|
|
3806
|
+
try {
|
|
3807
|
+
const email = await client2.testInbox.waitFor({ to, timeout: seconds * 1e3, since: readFlag24(args, "--since") });
|
|
3808
|
+
console.log(json ? JSON.stringify({ email }) : formatTestEmail(email));
|
|
3809
|
+
return { exitCode: 0 };
|
|
3810
|
+
} catch (error) {
|
|
3811
|
+
const status = error?.status;
|
|
3812
|
+
if (status === 408) {
|
|
3813
|
+
return { exitCode: 2, error: `No email to ${to} arrived within ${seconds} seconds.` };
|
|
3814
|
+
}
|
|
3815
|
+
throw error;
|
|
3816
|
+
}
|
|
3817
|
+
} catch (error) {
|
|
3818
|
+
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3748
3822
|
// src/help.ts
|
|
3749
3823
|
var USAGE_LINES = [
|
|
3750
3824
|
" groundmail login [--scope <scopes>] [--workspace <name>] sign in through the browser (OAuth; no key to copy)",
|
|
@@ -3768,6 +3842,9 @@ var USAGE_LINES = [
|
|
|
3768
3842
|
" groundmail dmarc disable example.com",
|
|
3769
3843
|
" groundmail received-emails list [--domain inbound.example.com]",
|
|
3770
3844
|
" groundmail received-emails get inb_...",
|
|
3845
|
+
" groundmail test-inbox address [--prefix signup] a fresh address on your team's test domain (mail there is caught, never delivered)",
|
|
3846
|
+
" groundmail test-inbox wait --to <address> [--timeout 30] [--since <iso>] [--json] wait for an email; prints its code and links (exit 2 on timeout)",
|
|
3847
|
+
" groundmail test-inbox list [--to <address>] [--since <iso>] [--json]",
|
|
3771
3848
|
' groundmail emails send --from you@domain.com --to user@example.com --subject "Hello" --html "<p>Hi</p>" [--category transactional|product|newsletter] [--unsubscribe] [--tenant <tenant>]',
|
|
3772
3849
|
" groundmail emails batch --file ./emails.json [--tenant <tenant>]",
|
|
3773
3850
|
" groundmail emails list [--limit 25] [--cursor \u2026] [--test | --live] [--tenant <tenant>] [--stream transactional|product|newsletter]",
|
|
@@ -3923,6 +4000,7 @@ async function main() {
|
|
|
3923
4000
|
if (command === "migrate") await finish(await runMigrateCommand(subcommand, rest));
|
|
3924
4001
|
if (command === "validate") await finish(await runValidateCommand([...subcommand ? [subcommand] : [], ...rest]));
|
|
3925
4002
|
if (command === "dmarc") await finish(await runDmarcCommand(subcommand, rest));
|
|
4003
|
+
if (command === "test-inbox") await finish(await runTestInboxCommand(subcommand, rest));
|
|
3926
4004
|
if (command === "domains") {
|
|
3927
4005
|
if (subcommand === "add" || subcommand === "create") {
|
|
3928
4006
|
const result = await runAddCommand(rest);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groundmail-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Groundmail CLI — send transactional email from the terminal",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"prepublishOnly": "npm run build"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"groundmail": "0.
|
|
41
|
+
"groundmail": "0.26.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"tsup": "^8.5.0",
|