Email server diagnostics
Claude Code agent skills by Arova AI
npx -y skills add arova-ai/agent-skills --skill email-server-diagnosticsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Diagnose and analyze self-hosted email server configurations. Checks DNS records (MX, SPF, DKIM, DMARC, MTA-STS, TLSRPT, rDNS, autodiscover, BIMI, DANE/TLSA), TLS certificates (HTTPS, IMAPS, SMTPS, protocol versions), port connectivity, IP/domain blacklist status, SPF lookup limits, open relay, IPv6 consistency, and server internals (Postfix, Dovecot, mailboxes, DKIM keys, mail queue). Also validates against Google/Yahoo/Microsoft 2024-2025 bulk sender requirements. Use this skill whenever the user mentions email server health checks, mail deliverability issues, DNS configuration for email, email authentication setup (SPF/DKIM/DMARC), mail server migration, diagnosing why emails go to spam or get rejected, or checking compliance with Gmail/Outlook sender policies. Also trigger when the user asks to set up or verify a mail domain, check email security, audit an existing mail server (mailcow, iRedMail, Postfix, etc.), or investigate email bounces.
SKILL.md
14.8 KB, ~4.0k tokens by cl100k_base, as published. Nobody here has run it
Email Server Diagnostics
Perform a comprehensive diagnostic analysis of a self-hosted email service. Identify misconfigurations, missing records, and security issues that affect deliverability and security, then produce a clear report with prioritized recommendations.
Information Gathering
Before running checks, establish:
- Mail domain(s) — the part after @ in email addresses (e.g.,
example.com) - Mail hostname — server FQDN, usually the MX target (e.g.,
mail.example.com) - Server public IP — the IP external mail servers connect to
- Server access — SSH credentials or other access (for internal checks)
- Mail server software — mailcow, iRedMail, Postfix/Dovecot standalone, etc.
If not all provided, infer from DNS: MX → hostname → A → IP. Ask for the rest.
Diagnostic Sequence
Run external checks (1-5) first — they need no server access. Internal checks (6) require SSH.
1. DNS Records
For each mail domain, check every record below using dig.
| Record | Lookup | What to verify |
|---|---|---|
| MX | dig MX <domain> +short | Points to correct hostname; priority reasonable; no stale entries |
| A / AAAA | dig A <hostname> + dig AAAA <hostname> | Resolves to expected IP; if AAAA exists, IPv6 must be fully configured |
| SPF | dig TXT <domain> +short | Has v=spf1; includes server IP or MX; ends -all or ~all; exactly ONE SPF record (multiple = error) |
| DKIM | dig TXT <selector>._domainkey.<domain> | Valid public key; try selectors: dkim, default, mail, s1, selector1, selector2, k1 |
| DMARC | dig TXT _dmarc.<domain> | v=DMARC1; policy quarantine or reject for production; has rua= for reporting |
| rDNS (PTR) | dig -x <ip> +short | Matches mail hostname exactly |
| Forward-confirmed rDNS | PTR → A lookup | PTR hostname must resolve back to the original IP |
| MTA-STS | dig TXT _mta-sts.<domain> + curl https://mta-sts.<domain>/.well-known/mta-sts.txt | TXT has v=STSv1; id=...; policy file accessible over HTTPS |
| TLSRPT | dig TXT _smtp._tls.<domain> | Has v=TLSRPTv1; rua=mailto:... |
| DANE/TLSA | dig TLSA _25._tcp.<hostname> | If DNSSEC enabled, TLSA record should exist (usage 3, selector 1, type 1 recommended) |
| BIMI | dig TXT default._bimi.<domain> | Optional; requires DMARC p=reject/quarantine with pct=100 |
| Autodiscover | dig A autodiscover.<domain> + dig A autoconfig.<domain> | Records exist for mail client auto-configuration |
| SRV | dig SRV _imaps._tcp.<domain>, _submission._tcp.<domain>, etc. | Service records for IMAP, SMTP, CalDAV, CardDAV |
Also check for stale records: old provider DKIM CNAMEs (e.g., gm1._domainkey → gandimail.net), conflicting SPF records, orphaned MX entries.
SPF Deep Validation
SPF has strict limits that are almost never checked manually but cause silent failures:
-
DNS lookup count (max 10): Count all
include,a,mx,redirect,existsmechanisms recursively. Exceeding 10 = PermError = SPF fails.# To count, recursively resolve each include and count mechanisms dig TXT <domain> +short # start here, then follow each include -
Void lookup limit (max 2): DNS queries that return NXDOMAIN or empty count as void lookups. More than 2 = PermError. Often caused by stale
include:references to decommissioned services. -
Common SPF mistakes to flag:
+allor?all(too permissive)- Deprecated
ptrmechanism - Multiple SPF TXT records on same domain
aandmxmechanisms when they add no value (wastes DNS lookups)
DKIM Validation
- Key length: Extract from DNS TXT and check. 1024-bit = WARNING (should rotate to 2048-bit). 2048-bit = OK.
- Key rotation: Flag if
t=y(testing mode) is still set in production. - Selector naming: Date-based selectors (e.g.,
jan2025) indicate good rotation practice. - 2048-bit chunking: Keys > 255 chars must be split into multiple quoted strings in DNS TXT; verify the record parses correctly.
2. TLS / SSL Certificates
Check certs on all mail protocols. For each, verify: not self-signed, not expired, correct CN/SAN, chain complete.
# HTTPS (web UI)
echo | openssl s_client -connect <ip>:443 -servername <hostname> 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates -ext subjectAltName
# IMAPS
echo | openssl s_client -connect <ip>:993 -servername <hostname> 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates
# SMTPS
echo | openssl s_client -connect <ip>:465 -servername <hostname> 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates
# SMTP STARTTLS (port 25)
echo | openssl s_client -connect <ip>:25 -starttls smtp -servername <hostname> 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates
# Submission STARTTLS (port 587)
echo | openssl s_client -connect <ip>:587 -starttls smtp -servername <hostname> 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates
TLS Protocol Version Check
Flag deprecated protocols. Minimum acceptable is TLS 1.2.
# Check if TLS 1.0/1.1 still accepted (should NOT be)
openssl s_client -connect <ip>:25 -starttls smtp -tls1 2>&1 | grep "Protocol"
openssl s_client -connect <ip>:25 -starttls smtp -tls1_1 2>&1 | grep "Protocol"
Flag: self-signed certs, expired certs, wrong CN, mismatched certs across protocols, TLS < 1.2 still enabled.
3. Port Connectivity & SMTP Banner
Test all standard ports:
| Port | Protocol | Purpose |
|---|---|---|
| 25 | SMTP | Incoming mail |
| 80 | HTTP | Web UI, ACME challenges |
| 110 | POP3 | Mail retrieval (legacy) |
| 143 | IMAP | Mail retrieval |
| 443 | HTTPS | Web UI, autodiscover |
| 465 | SMTPS | Submission (implicit TLS) |
| 587 | Submission | Submission (STARTTLS) |
| 993 | IMAPS | Secure IMAP |
| 995 | POP3S | Secure POP3 |
| 4190 | Sieve | Mail filtering |
nc -z -w5 <ip> <port> && echo "open" || echo "closed"
SMTP banner check (port 25):
echo "EHLO test" | nc -w5 <ip> 25
Verify: correct hostname in banner, STARTTLS advertised, 250 response codes.
HELO hostname consistency: The SMTP banner hostname should match the PTR record, which should match the A record. This three-way match (forward-confirmed reverse DNS) is critical for deliverability.
4. IP & Domain Reputation (Blacklists)
Check the server IP against major DNSBLs. A listing on any of these significantly impacts deliverability.
# Reverse the IP octets for DNSBL query
# For IP 1.2.3.4, query 4.3.2.1.<dnsbl-zone>
# NXDOMAIN = clean; any A record (127.0.0.x) = listed
IP="<server-ip>"
REV=$(echo $IP | awk -F. '{print $4"."$3"."$2"."$1}')
for bl in zen.spamhaus.org b.barracudacentral.org bl.spamcop.net dnsbl.sorbs.net; do
result=$(dig +short ${REV}.${bl} 2>/dev/null)
if [ -z "$result" ]; then echo "$bl: CLEAN"
else echo "$bl: LISTED ($result)"; fi
done
# Domain blacklists
for bl in dbl.spamhaus.org multi.surbl.org multi.uribl.com; do
result=$(dig +short <domain>.${bl} 2>/dev/null)
if [ -z "$result" ]; then echo "$bl: CLEAN"
else echo "$bl: LISTED ($result)"; fi
done
Also check IPv6 if AAAA records exist (IPv6 has separate reputation from IPv4).
5. Open Relay Test
Verify the server rejects relay attempts from unauthenticated sources. An open relay will get blacklisted very quickly.
# Connect from an external host without authentication and try to relay
# This should be REJECTED
(echo "EHLO test"; sleep 1; echo "MAIL FROM:<[email protected]>"; sleep 1; echo "RCPT TO:<[email protected]>"; sleep 1; echo "QUIT") | nc -w10 <ip> 25
Expected: 554 or 550 reject on the RCPT TO command (relay denied). If you get 250 OK on RCPT TO for an external recipient, the server is an open relay — this is CRITICAL.
6. Server Internal Checks (requires SSH)
Adapt to the specific mail software. Database credentials can usually be found in the main config file.
Mailcow
# Key config values from mailcow.conf
grep -E "^(MAILCOW_HOSTNAME|SKIP_LETS_ENCRYPT|ENABLE_IPV6|ACL_ANYONE|HTTP_REDIRECT)" \
/opt/mailcow-dockerized/mailcow.conf
# Extract DB credentials
DBUSER=$(grep ^DBUSER /opt/mailcow-dockerized/mailcow.conf | cut -d= -f2)
DBPASS=$(grep ^DBPASS /opt/mailcow-dockerized/mailcow.conf | cut -d= -f2)
REDIS_PASS=$(grep ^REDISPASS /opt/mailcow-dockerized/mailcow.conf | cut -d= -f2)
# Domains
cd /opt/mailcow-dockerized
docker compose exec -T mysql-mailcow mysql -u$DBUSER -p$DBPASS mailcow \
-e "SELECT domain,active,backupmx FROM domain;"
# Mailboxes
docker compose exec -T mysql-mailcow mysql -u$DBUSER -p$DBPASS mailcow \
-e "SELECT username,domain,active,quota FROM mailbox;"
# Aliases
docker compose exec -T mysql-mailcow mysql -u$DBUSER -p$DBPASS mailcow \
-e "SELECT address,goto,active FROM alias WHERE address NOT LIKE '@%';"
# DKIM keys (stored in Redis)
docker compose exec -T redis-mailcow redis-cli -a "$REDIS_PASS" HGETALL DKIM_SELECTORS
docker compose exec -T redis-mailcow redis-cli -a "$REDIS_PASS" HKEYS DKIM_PRIV_KEYS
# ACME / Let's Encrypt status
docker compose logs acme-mailcow --tail 30
# Container health
docker compose ps --format "table {{.Name}}\t{{.Status}}"
# Postfix config highlights
docker compose exec -T postfix-mailcow postconf -n | \
grep -E "(myhostname|relayhost|smtpd_tls|smtpd_relay_restrictions)"
# Mail queue depth
docker compose exec -T postfix-mailcow postqueue -p | tail -1
# Rspamd stats
docker compose exec -T rspamd-mailcow rspamc stat 2>/dev/null | head -20
Generic Postfix/Dovecot
postconf -n | grep -E "(myhostname|mydestination|relay|smtpd_tls|smtp_tls|smtpd_relay)"
doveconf -n | grep -E "(ssl|auth_mechanisms|mail_location)"
postqueue -p | tail -1 # queue depth
Internal checks to verify:
- All containers/services running and healthy
- DKIM private keys exist and match DNS public key selector
- Let's Encrypt working (not self-signed fallback)
- Postfix
myhostnamematches DNS and rDNS - No open relay (
smtpd_relay_restrictionscontainsreject_unauth_destination) - Mail queue not backed up (>100 = investigate, >1000 = problem)
- Rspamd running and processing (not bypassed)
Google/Yahoo/Microsoft 2024-2025 Compliance Check
These requirements are now enforced with permanent rejections. Check compliance for domains sending to Gmail, Yahoo, or Outlook.com.
All senders must have:
- SPF or DKIM set up (at minimum)
- Valid PTR (forward-confirmed reverse DNS)
- TLS for mail transmission
- RFC 5322 compliant message formatting
- Spam rate < 0.3% (check via Google Postmaster Tools)
Bulk senders (>5,000 emails/day) must additionally have:
- Both SPF AND DKIM (not just one)
- DMARC with at least
p=noneand alignment pass - One-click unsubscribe headers (List-Unsubscribe + List-Unsubscribe-Post)
- ARC headers when forwarding messages
- From: domain aligned with SPF or DKIM domain
Microsoft Outlook (May 2025+):
- SPF, DKIM, and DMARC all required for >5,000 emails/day to Outlook/Hotmail/Live
Flag any non-compliance as WARNING or CRITICAL depending on sending volume.
IPv6 Consistency Check
Only if the mail hostname has an AAAA record. Having a partially configured IPv6 is worse than having none.
AAAA=$(dig AAAA <hostname> +short)
if [ -n "$AAAA" ]; then
echo "IPv6: $AAAA"
# Must have IPv6 PTR
dig -x $AAAA +short # should return the hostname
# Must be in SPF (ip6: mechanism)
dig TXT <domain> +short | grep -o "ip6:[^ ]*"
# Check IPv6 blacklists separately
fi
If AAAA exists but PTR is missing or SPF doesn't include it → CRITICAL (Gmail rejects immediately).
Diagnostic Report Format
## <domain> Email Server Diagnostic Report
### Server Overview
| Item | Value |
|---|---|
| Mail hostname | ... |
| Public IP | ... |
| rDNS (PTR) | ... |
| Server software | ... |
| Services status | X/Y running |
### Mailboxes & Aliases
(table of accounts and forwarding rules)
### DNS Records
| Record | Value | Status |
|---|---|---|
(OK / WARNING / MISSING / ERROR for each)
### SPF Analysis
- Record: `v=spf1 ...`
- DNS lookups used: X/10
- Void lookups: X/2
- Issues: (if any)
### DKIM Analysis
- Selector: ...
- Key length: ... bits
- Status: ...
### TLS Certificates
| Protocol | Port | Issuer | Expires | TLS Version | Status |
|---|---|---|---|---|---|
### Port Connectivity
| Port | Protocol | Status |
|---|---|---|
### Blacklist Status
| Blacklist | Status |
|---|---|
(CLEAN or LISTED for each)
### Compliance: Google/Yahoo/Microsoft Sender Requirements
(checklist with pass/fail for each requirement)
### Issues Found
1. **CRITICAL** — blocks delivery or causes rejection
2. **WARNING** — degrades deliverability or security
3. **INFO** — best-practice recommendations
### Recommended Actions
(numbered list, priority order, with specific commands or steps)
Severity Guidelines
CRITICAL (mail delivery blocked):
- MX record missing or wrong
- SPF/DKIM/DMARC completely absent
- SPF exceeds 10 DNS lookups
- TLS certificate expired or invalid on mail ports
- Port 25 unreachable
- Open relay detected
- IP listed on Spamhaus ZEN
- IPv6 AAAA exists but no IPv6 PTR
- HELO hostname doesn't match rDNS
WARNING (deliverability degraded):
- rDNS doesn't match mail hostname
- SPF uses
~allwith DMARCp=reject(inconsistent) - DMARC policy still at
p=nonein production - DKIM using 1024-bit key
- Self-signed certificates on any port
- MTA-STS missing
- Stale DNS records from old providers
- ACME/Let's Encrypt failing
- Mail queue > 100 messages
- TLS 1.0 or 1.1 still accepted
- Non-compliant with bulk sender requirements
INFO (best practices):
- TLSRPT not configured
- BIMI not set up (requires DMARC p=reject + pct=100)
- DANE/TLSA not configured (requires DNSSEC)
- ARC not configured for forwarding
- SRV records for autodiscover missing
- POP3 ports open but unused
- DKIM key rotation not evident (no date-based selectors)
- Void lookup count close to limit