CLI › check
check
propgate check <domain> needs no account, no config file, and no network
beyond DNS. It resolves against whichever server you point it at, defaulting
to the system resolver, using the same engine as the public checker and the
API.
propgate — DNS diagnosis from the terminal
propgate check <domain> [options]
Account and domains (see `propgate signup --help`)
propgate signup --email <address>
propgate confirm --email <address> --code <code>
propgate keys list | create <name> | revoke <prefix>
propgate domains add <domain> --profile <key> | list
Options
--selector <name> A DKIM selector to check. Repeatable.
--spf-include <name> An include: token that must authorise this domain.
--caa-issuer <name> A certificate authority that must be authorised.
--receives-mail This domain should receive mail, so undeliverable
mail is a problem. Unstated by default.
--only <kinds> Comma-separated: delegation, spf, dkim, dmarc, mx, caa.
--resolver <addr> Resolver to query, as address or address:port.
Defaults to the system resolver.
--trace Print every DNS query behind the answer.
--json Machine-readable output.
--help, --version
Exit codes
0 nothing to fix
1 something is wrong
2 a check could not be completed — which is not the same as a failureEvery flag
| Flag | What it does |
|---|---|
--selector <name> | A DKIM selector to check. Repeatable: pass it once per selector in use. |
--spf-include <name> | An include: token that must authorise this domain, after recursive expansion. |
--caa-issuer <name> | A certificate authority that must be authorised, climbed per RFC 8659. |
--receives-mail | This domain should receive mail, so undeliverable mail is a problem. Unstated by default. See "--receives-mail" below. |
--only <kinds> | Comma-separated subset of delegation, spf, dkim, dmarc, mx, caa. Runs all six when omitted. |
--resolver <addr> | Resolver to query, as address or address:port. Defaults to the system resolver, and the port is never assumed to be 53. |
--trace | Print every DNS query behind the answer: server, name, type, and outcome. |
--json | Machine-readable output. See "--json" below. |
--help, --version |
npx @propgate/cli check github.com --only spfgithub.com
! spf
- Part of this domain's SPF record changes for every connection, so it
cannot be checked from the published records alone.
%{i} needs something this check does not have
found: exists:%{i}._spf.mta.salesforce.com
SPF_MACRO_NOT_EVALUATED
! This domain's SPF record is close to the ten-lookup limit, so adding one
more sending service is likely to break it.
0 of the ten lookups are left, so the next sending service added is
likely to break SPF outright
found: 10 lookups
wanted: at most 7 lookups, to leave room to grow
SPF_LOOKUP_LIMIT_NEAR
1 thing worth looking atGitHub's SPF record works today and sits at exactly the ten DNS lookups RFC
7208 allows. The next include: anyone adds breaks mail delivery, with no
error at the moment of the edit. Finding that needs recursive include:
expansion with the lookup and void-lookup limits actually counted. A regex
over a TXT record cannot do it.
Asserting something specific fails loudly when it is missing:
npx @propgate/cli check example.com --only spf --spf-include _spf.google.comx spf
x This domain's SPF record does not authorise the sending service being
set up, so its messages will fail SPF.
add include:_spf.google.com before the all mechanism; added after it,
the term never runs
found: no include: or redirect= terms at all
wanted: include:_spf.google.com
SPF_SOURCE_NOT_AUTHORIZED
1 problem to fixExit codes
| Code | Meaning |
|---|---|
0 | Nothing to fix. Warnings count as nothing to fix — they describe something that works. |
1 | Something is wrong. |
2 | A check could not be completed. |
That third code is the one worth pausing on: it is not a failure. A
resolver that timed out, or a lookup that came back SERVFAIL, says nothing
about the domain. The resolver kept indeterminate separate from fail all
the way down specifically so this exit code could exist. Collapsing it into
1 is how a deployment gate starts blocking releases over someone else's bad
second, on a domain that was never actually misconfigured.
npx @propgate/cli check example.com --only spf,dkim --selector app || exit $?--receives-mail
Whether a null MX is correct depends entirely on what the domain is for, and no amount of looking at DNS reveals that: a sending-only domain and a domain that has forgotten to set up mail publish the identical record. The underlying model has three states: expects mail, does not, and unstated.
The flag itself can only reach two of them. Passing --receives-mail asserts
true; leaving it off leaves the check unstated. There is no flag for
asserting false, no way from the CLI to say "this domain deliberately sends
no mail", because a check that makes no claim already produces the right
answer for that domain: mx observes a null MX and reports it as
MX_NULL, informational, never a failure, without anyone having to say
anything.
Pass the flag and that same null MX becomes MX_MAIL_NOT_ACCEPTED, an error:
the check now knows mail was expected and cannot be delivered.
--json
npx @propgate/cli check example.com --only dmarc --json{
"checks": [
{
"findings": [],
"kind": "dmarc",
"lookups": [
{
"name": "_dmarc.example.com",
"purpose": "the domain's own DMARC policy",
"server": "1.1.1.1:53",
"status": "answered",
"type": 16
}
],
"verdict": "pass"
}
],
"domain": "example.com",
"verdict": "pass"
}Every result carries its derivation, not just the verdict: which lookups
happened, against which server, and what each returned. A verdict you cannot
audit is a verdict you have to take on faith. --trace prints the
same underlying data in human form alongside the findings, rather than as a
separate machine-readable document.