DNS guide · mail policy and TLS

DNS, SPF, DMARC and TLS Expiry Command-Line Guide

DNS and certificate checks are small enough for a shell script but subtle enough to cause outages when reduced to one boolean. These recipes show direct commands and a single-request API alternative. Run them against the exact hostname or domain your application uses, and record timestamps because DNS and certificates change.

PRACTICAL · COMMAND LINE READY

How do I check SPF and DMARC records?

Query the domain’s TXT records for SPF and query `_dmarc.` for DMARC. Confirm there is at most one SPF policy and inspect the DMARC policy value.

dig +short TXT example.com | grep -i 'v=spf1'
dig +short TXT _dmarc.example.com | grep -i 'v=dmarc1'

# one JSON response
curl -sG https://dns.lifestep.io/domain --data name=example.com | jq '{spf:.spf_record,dmarc:.dmarc_record,has_spf,has_dmarc}'

Why it works: SPF authorizes sending hosts, while DMARC applies alignment and tells receivers what to do when authentication fails. Multiple SPF TXT records are a configuration error, not two policies that combine. DMARC reporting and enforcement are separate decisions: a record with `p=none` is useful for observation but does not quarantine or reject spoofed mail. DNS TXT answers can be split into quoted chunks, so production parsers should join them according to DNS rules.

When does my TLS certificate expire from the command line?

Use OpenSSL to perform a TLS handshake and print `notAfter`, or call the API and read its computed day count. Include `-servername` so virtual hosts return the certificate for the requested hostname.

host=example.com
printf '' | openssl s_client -connect "$host:443" -servername "$host" 2>/dev/null | openssl x509 -noout -enddate

# machine-readable days
curl -sG https://dns.lifestep.io/domain --data name="$host" | jq -r .tls.days_until_expiry

Why it works: The certificate presented by a server depends on SNI, which is why `-servername` matters on shared infrastructure. `notAfter` is an expiry timestamp, not proof that the full chain, hostname policy, cipher configuration, or renewal automation is correct. In CI, parse a trusted date format and fail with a warning window—for example, 21 days—rather than waiting for the exact expiry moment.

What is a dig alternative that makes one request?

Use the domain-info endpoint once and read all returned fields with `jq`. It combines common DNS records, SPF/DMARC presence, and TLS metadata in one JSON response.

curl -sG https://dns.lifestep.io/domain --data name=example.com | jq '{resolves,mx,ns,spf:.spf_record,dmarc:.dmarc_record,tls:.tls}'

Why it works: A single HTTP request reduces shell orchestration and gives automation one response shape to log and validate. It is not the same as one DNS packet: the service performs several lookups and a TLS handshake on your behalf, so its result reflects the service’s resolver and network path. Use direct `dig` or a resolver you control when you need authoritative troubleshooting, and use the API for a compact health snapshot.

A small production checklist

Make the command deterministic before putting it in automation. Pin the input hostname or filename, set a timeout, capture the exit status, and emit a concise error that a build log can explain. Treat an empty answer differently from a transport failure: an empty DNS record, a workbook with no matching package member, and an unavailable endpoint are different states. Test one known-good fixture and one deliberately bad fixture so a future dependency or API change cannot silently turn a failure into a pass. Prefer machine-readable JSON when an API provides it, but retain the original command for local diagnosis. If the result controls a user-facing decision, show the reason and a timestamp rather than only a green or red label. These habits keep a useful one-liner understandable when it becomes a scheduled check.