Guide
Email Deliverability from the CLI
Email deliverability is the measure of whether your emails reach the recipient's inbox or get filtered into spam, bounced, or silently dropped. It depends on three authentication protocols (SPF, DKIM, DMARC), sender reputation, and message content. This guide shows how to inspect and debug every layer from the command line using Nylas CLI and standard DNS tools.
SPF: who is allowed to send from your domain
Sender Policy Framework (SPF) is a DNS record that tells receiving mail servers which IP addresses are authorized to send email on behalf of your domain. When a server receives an email from your domain, it checks the SPF record to see if the sending server's IP is on the list.
# Check SPF record for any domain
dig +short TXT example.com | grep spf
# Example output:
# "v=spf1 include:_spf.google.com include:servers.mcsv.net ~all"
# Break down what this means:
# v=spf1 → SPF version 1
# include:_spf.google.com → Google Workspace can send for this domain
# include:servers.mcsv.net → Mailchimp can send for this domain
# ~all → Soft-fail everything else (mark as suspicious but deliver)The policy at the end matters:
-all— hard fail. Reject emails from unauthorized servers. Strongest protection.~all— soft fail. Accept but mark as suspicious. Most common during setup.?all— neutral. No policy. Effectively useless.+all— allow all. Dangerous — anyone can spoof your domain.
Inspect SPF includes recursively
SPF records use include: directives that reference other domains. To see the full set of authorized IPs, you need to follow the chain:
# Follow the SPF include chain for Google Workspace
dig +short TXT _spf.google.com
# "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"
# See the actual IP ranges
dig +short TXT _netblocks.google.com
# "v=spf1 ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ..."
# Check if you are close to the DNS lookup limit (max 10 lookups)
# Count the number of include/redirect/a/mx mechanisms
dig +short TXT yourdomain.com | grep -oE 'include:|redirect=|a:|mx:' | wc -lSPF has a 10 DNS lookup limit. Exceeding it causes a permanent error (permerror), which means SPF effectively fails for every email. If you are using multiple email services (Google Workspace + Mailchimp + Salesforce + a transactional sender), you can hit this limit quickly.
DKIM: cryptographic email authentication
DomainKeys Identified Mail (DKIM) adds a cryptographic signature to outgoing emails. The sending server signs the message with a private key, and the receiving server verifies the signature using a public key published in DNS. This proves the email was actually sent by an authorized server and was not modified in transit.
# Check DKIM record for a domain
# You need to know the selector — common ones:
# google / default → Google Workspace
# s1 / s2 → Microsoft 365
# k1 → Mailchimp
# sm1 / sm2 → Salesforce
# Google Workspace DKIM
dig +short TXT google._domainkey.example.com
# Microsoft 365 DKIM
dig +short TXT selector1._domainkey.example.com
# Generic check (try common selectors)
for selector in google default s1 s2 selector1 selector2 k1 sm1; do
RESULT=$(dig +short TXT "$selector._domainkey.example.com" 2>/dev/null)
if [ -n "$RESULT" ]; then
echo "Found DKIM for selector: $selector"
echo "$RESULT"
echo "---"
fi
doneA valid DKIM record contains a public key (the p= field). If the record is empty or missing, DKIM signing is not configured for that selector.
DMARC: the policy that ties SPF and DKIM together
Domain-based Message Authentication, Reporting, and Conformance (DMARC) tells receiving servers what to do when an email fails SPF and DKIM checks. It also specifies where to send aggregate and forensic reports about authentication failures.
# Check DMARC record
dig +short TXT _dmarc.example.com
# Example output:
# "v=DMARC1; p=reject; rua=mailto:dmarc-reports@example.com; ruf=mailto:forensics@example.com; pct=100"
# Break down what this means:
# v=DMARC1 → DMARC version 1
# p=reject → Reject emails that fail both SPF and DKIM
# rua=mailto:dmarc-reports@example.com → Send aggregate reports here
# ruf=mailto:forensics@example.com → Send forensic (failure) reports here
# pct=100 → Apply to 100% of emailsDMARC policies in order of strictness:
p=none— monitor only. Receive reports but take no action. Start here.p=quarantine— send failing emails to spam. Intermediate step.p=reject— reject failing emails entirely. Full protection against spoofing.
Inspect authentication headers on received emails
The best way to verify your email authentication is working is to check the headers on emails you have received. Nylas CLI makes this straightforward:
# Read a message with full headers
nylas email read msg_abc123 --json \
| jq '.headers'
# Look for specific authentication headers
nylas email read msg_abc123 --json \
| jq '.headers | to_entries[] | select(.key | test("Authentication-Results|Received-SPF|DKIM-Signature|ARC"; "i"))'
# Example Authentication-Results header:
# Authentication-Results: mx.google.com;
# dkim=pass header.i=@example.com header.s=google;
# spf=pass (google.com: domain of sender@example.com designates 209.85.220.41 as permitted sender);
# dmarc=pass (p=REJECT) header.from=example.comThe Authentication-Results header is the single most useful header for debugging deliverability. It shows the pass/fail status of SPF, DKIM, and DMARC in one place.
Send test emails and verify authentication
The fastest way to test deliverability is to send an email and check the headers on the receiving end:
# Send a test email
nylas email send \
--to "test@gmail.com" \
--subject "Deliverability test" \
--body "Testing SPF, DKIM, and DMARC authentication."
# Then on the receiving end, check the authentication headers
# In Gmail: open the email → three dots → "Show original"
# Or if you have CLI access to the receiving account:
nylas email search "deliverability test" --limit 1 --json \
| jq '.[0].headers | to_entries[] | select(.key | test("Authentication|SPF|DKIM|DMARC"; "i"))'Diagnose common delivery failures
SPF failure: sending from an unauthorized server
# Symptom: emails going to spam or being rejected
# Check: is the sending server in the SPF record?
# Find your sending server's IP (from the email headers)
nylas email read msg_id --json \
| jq -r '.headers["Received"]' \
| grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
# Check if that IP is authorized by SPF
dig +short TXT yourdomain.com | grep spf
# If the sending IP is not in the SPF include chain, add itDKIM failure: signature mismatch or missing key
# Check if the DKIM key exists for the selector in the email
# Find the selector from the DKIM-Signature header:
nylas email read msg_id --json \
| jq -r '.headers["DKIM-Signature"]'
# Look for s=selector; in the output
# Then verify the public key exists in DNS
dig +short TXT selector._domainkey.yourdomain.com
# If empty: DKIM key not published. Add it to your DNS.DMARC failure: alignment issues
# DMARC requires alignment: the domain in From must match
# the domain that passed SPF or DKIM
# Check DMARC alignment mode
dig +short TXT _dmarc.yourdomain.com
# aspf=r → relaxed SPF alignment (subdomains OK)
# aspf=s → strict SPF alignment (exact match only)
# adkim=r → relaxed DKIM alignment
# adkim=s → strict DKIM alignment
# If you send from marketing.example.com but SPF/DKIM
# is set up for example.com, strict alignment will failCheck MX records and mail routing
MX (Mail Exchanger) records determine where incoming email is routed. If these are misconfigured, you will not receive email at all:
# Check MX records
dig +short MX example.com
# 10 alt1.aspmx.l.google.com.
# 5 aspmx.l.google.com.
# 20 alt2.aspmx.l.google.com.
# The number is the priority (lower = higher priority)
# Verify the MX servers are reachable
for mx in $(dig +short MX example.com | awk '{print $2}'); do
echo -n "$mx: "
dig +short A "$mx"
doneVerify TLS encryption
Modern email should always use TLS in transit. Check if a mail server supports STARTTLS:
# Check if a mail server supports STARTTLS
# Connect to the MX server on port 25 and check for STARTTLS
echo "EHLO test.example.com" | ncat -w 5 aspmx.l.google.com 25
# Check the TLS certificate
openssl s_client -connect aspmx.l.google.com:25 -starttls smtp < /dev/null 2>/dev/null \
| openssl x509 -noout -subject -datesDeliverability checklist
Run through this checklist when debugging delivery issues:
| Check | Command | Expected result |
|---|---|---|
| SPF record exists | dig +short TXT example.com | Contains v=spf1 |
| SPF not too many lookups | Count includes | 10 or fewer |
| DKIM key published | dig +short TXT selector._domainkey.example.com | Contains p= public key |
| DMARC policy set | dig +short TXT _dmarc.example.com | Contains v=DMARC1 |
| MX records resolve | dig +short MX example.com | Returns mail servers |
| Auth headers pass | nylas email read --json | SPF=pass, DKIM=pass, DMARC=pass |
| TLS supported | openssl s_client -starttls smtp | Valid certificate |
Automate deliverability monitoring
Set up a script that periodically checks your email authentication and alerts on failures:
#!/bin/bash
# deliverability-check.sh — run with cron or in CI
DOMAIN="yourdomain.com"
ERRORS=0
# Check SPF
SPF=$(dig +short TXT "$DOMAIN" | grep "v=spf1")
if [ -z "$SPF" ]; then
echo "FAIL: No SPF record found for $DOMAIN"
ERRORS=$((ERRORS + 1))
else
echo "PASS: SPF record found"
fi
# Check DMARC
DMARC=$(dig +short TXT "_dmarc.$DOMAIN")
if [ -z "$DMARC" ]; then
echo "FAIL: No DMARC record found for $DOMAIN"
ERRORS=$((ERRORS + 1))
else
echo "PASS: DMARC record found"
# Warn if policy is none
if echo "$DMARC" | grep -q "p=none"; then
echo "WARN: DMARC policy is 'none' — no enforcement"
fi
fi
# Check DKIM (try common selectors)
DKIM_FOUND=false
for selector in google default s1 selector1; do
DKIM=$(dig +short TXT "$selector._domainkey.$DOMAIN" 2>/dev/null)
if [ -n "$DKIM" ]; then
echo "PASS: DKIM record found for selector '$selector'"
DKIM_FOUND=true
break
fi
done
if [ "$DKIM_FOUND" = false ]; then
echo "WARN: No DKIM record found for common selectors"
fi
# Check MX
MX=$(dig +short MX "$DOMAIN")
if [ -z "$MX" ]; then
echo "FAIL: No MX records found for $DOMAIN"
ERRORS=$((ERRORS + 1))
else
echo "PASS: MX records found ($(echo "$MX" | wc -l | tr -d ' ') servers)"
fi
# Summary
echo "---"
if [ $ERRORS -gt 0 ]; then
echo "RESULT: $ERRORS failures found. Fix before sending email."
exit 1
else
echo "RESULT: All checks passed."
fiSending best practices from the CLI
When sending email through Nylas CLI, the authentication (SPF, DKIM) is handled by the provider. Your job is to ensure the content and sending patterns do not trigger spam filters:
- Use a real reply-to address — do not send from no-reply addresses. Receiving servers score emails higher when replies are possible.
- Keep subject lines honest — avoid all-caps, excessive punctuation, and spam trigger words in the subject.
- Include plain text — when sending HTML email, always include a plain text alternative. Nylas CLI sends plain text by default.
- Warm up new accounts — if using a new email account, start with low volume and increase gradually over 2-4 weeks.
- Monitor bounces — check for bounce notifications and remove invalid addresses promptly.
# Send a well-formed email through authenticated channels
nylas email send \
--to "recipient@company.com" \
--subject "Q2 report summary" \
--body "Hi Team, please find the Q2 summary below. Let me know if you have questions."
# Check for bounce notifications
nylas email search "delivery failure undeliverable returned mail" --jsonFrequently asked questions
My SPF record is correct but emails still go to spam. Why?
SPF is necessary but not sufficient. Check DKIM and DMARC as well. Also check sender reputation — new domains or domains with a history of spam need time to build reputation. Content analysis (spam-like language, excessive links) can also trigger filters regardless of authentication.
How long does it take for DNS changes to propagate?
SPF, DKIM, and DMARC records typically propagate within 5-60 minutes, depending on TTL values. Use dig +trace TXT _dmarc.example.com to check propagation status from authoritative nameservers.
Do I need all three (SPF, DKIM, DMARC)?
Yes. Major providers (Google, Microsoft, Yahoo) require all three as of 2024. Missing any one of them significantly increases the chance of your emails being filtered or rejected.
How do I check deliverability for emails sent by AI agents?
The same way — check authentication headers on the receiving end. If your agent sends email through nylas email send, the email goes through the authenticated provider (Gmail, Outlook, etc.) with proper SPF, DKIM, and DMARC. The provider handles the authentication; you handle the content quality.
Next steps
- Send email from the terminal — complete guide to CLI email
- Why Gmail API breaks AI agents — authentication complexity compared
- GPG encrypted email from the CLI — add end-to-end encryption
- Full command reference — every flag and option