I just launched gradients.sh. Come check it out →
Email SDK
ReferenceCLI commands

email-sdk doctor

Check configuration safely by default; explicitly authenticate and inspect Resend sender readiness without sending.

Safe default

After exporting server credentials:

Success prints resend looks configured.. Default doctor checks required configuration only: it does not contact the provider, authenticate, inspect domains, or prove deliverability. The CLI does not load .env files. Opt-out telemetry is enabled by default; set EMAIL_SDK_TELEMETRY=0 or DO_NOT_TRACK=1 to disable it.

Explicit non-sending live checks

--live contacts the provider to check authentication, never to send an email. Supported providers: Resend, Sequenzy, JetEmail, Primitive, Lettermint, and Lettr. Other adapters report an unsupported live check rather than pretending success.

AdapterProbeWhy it cannot send
ResendGET https://api.resend.com/domains?limit=100Read-only domain listing.
SequenzyGET https://api.sequenzy.com/api/v1/accountRead-only account/permission summary (account:read).
PrimitiveGET https://api.primitive.dev/v1/accountRead-only account info.
LettermintGET https://api.lettermint.co/v1/ping (x-lettermint-token)Documented status/authentication ping.
LettrGET https://app.lettr.com/api/auth/checkDocumented key-validation endpoint.
JetEmailPOST https://api.jetemail.com/email with body {}See below.

JetEmail transactional keys are scoped to the send endpoints and there is no documented authentication endpoint for them, so the probe posts an empty JSON object to /email with no sender, recipient, subject, or content; the API rejects it before anything can be queued. Only a 401 is a definite answer (invalid_credentials). Validation responses (400/422) and unexpected 2xx responses are reported as inconclusive, not as proof of authentication.

--from <address> requires --live and requests sender readiness. Currently only Resend supports this check, using sender-domain status/capability. Readiness does not prove recipient approval, sending permissions for every key, or inbox delivery. The shared resend.dev sender remains restricted to the account owner's recipient address; use your verified domain for other approved recipients.

Selection and options

Use --adapter <name> or --provider. Without either, doctor selects the first adapter with all required environment values. Explicit selection is recommended if several credentials are configured. Credential flags (for example --api-key, --api-token) override environment values; prefer environment variables to keep secrets out of command history. The CLI reads only the process environment: it never loads .env or .env.local files, so export credentials into the shell first.

Live requests are bounded to a 10 second timeout, never follow redirects, and send only the credential header plus Accept: application/json. The JetEmail probe body is an empty JSON object; no probe carries a sender, recipient, subject, or message content.

--base-url (or <ADAPTER>_BASE_URL, e.g. RESEND_BASE_URL) is a test-only override for local fixture servers. It accepts the provider's fixed HTTPS base or an explicit numeric-loopback HTTP(S) URL (http://127.0.0.1:<port> or http://[::1]:<port>); hostnames such as localhost, arbitrary remote origins, and URLs with userinfo, query, or fragment are rejected as a configuration failure before any credential is forwarded. Do not use real credentials with fixtures.

Structured results and exit status

--json returns { ok, adapter, checks }. The checks object always includes configuration, authentication, and sender, each with status and a sanitized actionable message. Default configuration-only success has configuration.status: "passed", while authentication and sender are "not_requested".

StatusMeaning / next action
passedThis requested check passed; not a delivery guarantee.
not_requestedThis check was not requested.
failedFix the reported configuration or check failure.
blockedA prerequisite check prevented this check.
unsupportedThis adapter does not implement the requested check.
invalid_credentialsReplace/review the server credential privately.
insufficient_permissionsThe key lacks diagnostic read scope (HTTP 403, or Resend's sending-only restricted_api_key 401); do not assume it cannot send.
inconclusiveProvider response did not establish the requested result (unexpected status such as 400/422/5xx, invalid JSON, or an unrecognized body). Never treated as authentication success.
rate_limitedThe provider returned HTTP 429. Wait and reduce probe frequency; this does not prove the key is invalid.
network_failureDNS, TLS, proxy, connection, or a rejected redirect prevented a response. Redirects are never followed.
timeoutThe request exceeded the 10 second bound; retry the non-sending check later.
not_readyThe Resend sender domain is missing, unverified, or has sending disabled. Complete domain setup in the dashboard.

Provider response bodies, raw network errors, credentials, sender addresses, and account or domain IDs are never printed in either output mode.

Exit codes

Exit codeWhen
0ok: true: configuration passed and every requested check (authentication, sender) is passed; not_requested checks do not fail.
1Any check is not passed/not_requested: missing configuration, --from without --live, unsupported live check, invalid credentials, insufficient permissions, inconclusive/rate-limited/network/timeout results, or an unverified (not_ready) sender.
1Usage errors (for example an unknown command) print one message to stderr.

No other exit codes are used. A sending-only Resend key may lack domain-list access: do not broaden a production key merely to turn a diagnostic green.

Usage errors include unsupported adapter, missing required environment, and no explicit/detectable adapter. Check the installed version with npx --package @opencoredev/email-sdk email-sdk version if flags are unrecognized.

Use send --dry-run next to validate the exact message. A subsequent live send requires separate approval of sender and recipient; its provider receipt is not inbox delivery.

Send command

Validate the exact message without provider delivery.

On this page