mailcheck
Code Issues Pull requests Projects Releases Packages Wiki Activity Actions
Check settings for mailservers over the network, with nagios compatibility
6 commits 1 branch 0 tags 102 KiB
- Go 99.4%
- Makefile 0.6%
- MX records, sorted by preference
- implicit-MX fallback to A/AAAA when no MX exists
- A and AAAA resolution
- IPv4/IPv6 selection
- TCP SMTP connectivity
- SMTP greeting and EHLO
- STARTTLS support and negotiation
- optional implicit TLS (`--implicit-tls`, useful for port 465)
- certificate parsing, hostname/PKIX verification, issuer, dates and expiry
- TLS 1.2/1.3 and modern AEAD cipher classification
- TLSA lookup and certificate/public-key matching for TLSA usages 0-3
- DNSSEC indication using the AD bit returned by the selected recursive resolver
- SPF record discovery and basic syntax/lookup-limit checks
- DMARC record parsing and policy checks
- DKIM selector checks, including RSA and Ed25519 public-key validation
- human, JSON and Nagios/Icinga output
main
HTTPS
Download ZIP Download TAR.GZ Download BUNDLE Open with VS Code Open with VSCodium Open with Intellij IDEA
| Mark Janssen 0d34ea12fb
Working: version 5 | 2026-10-05 21:45:16 +02:00 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -------------------------- |
| go.mod | Attempt 2 | 2026-10-05 21:21:18 +02:00 |
| go.sum | Working: version 5 | 2026-10-05 21:45:16 +02:00 |
| LICENSE | Attempt 2 | 2026-10-05 21:21:18 +02:00 |
| main.go | Working: version 5 | 2026-10-05 21:45:16 +02:00 |
| Makefile | Initial broken version | 2026-10-05 21:11:00 +02:00 |
| README.md | Working: version 5 | 2026-10-05 21:45:16 +02:00 |
| smtp\_response\_test.go | Working: version 5 | 2026-10-05 21:45:16 +02:00 |
mailcheck
`mailcheck` is a small command-line SMTP/DNS/TLS diagnostic tool written in Go. It checks whether a domain appears correctly configured to receive SMTP mail and can emit Nagios/Icinga-compatible output.
Checks
Build
Requires Go 1.23 or newer.
go build -o mailcheck .For a Linux install:
install -m 0755 mailcheck /usr/local/bin/mailcheckExamples
./mailcheck example.com
./mailcheck example.com --show-expiry
./mailcheck example.com --ipv4
./mailcheck example.com --ipv6
./mailcheck example.com --host mail.example.net
./mailcheck example.com --host mail.example.net --address 192.0.2.25
./mailcheck example.com --dkim selector1,selector2
./mailcheck example.com --json
./mailcheck example.com --nagios
./mailcheck example.com --port 465 --implicit-tls
./mailcheck example.com --dns 1.1.1.1When `--host` is supplied, that hostname is used for TLS SNI/name validation and TLSA lookup. `--address` controls the TCP destination without changing the TLS hostname. If only `--address` is supplied, the domain itself is used as the TLS hostname; for accurate SMTP certificate/DANE testing, supplying the actual MX hostname is preferable.
Nagios exit status
0 OK
1 WARNING
2 CRITICAL
3 UNKNOWNExample:
MAILCHECK WARNING - mx.example.net/192.0.2.25 SMTP=OK TLS=OK TLSA=WARNING | duration_ms=142DNSSEC / DANE note
The program requests EDNS DNSSEC data and reports DNSSEC as secure when the recursive resolver returns the DNS AD (Authenticated Data) bit. It does not implement a complete DNSSEC validator itself. For production DANE monitoring, point `--dns` at a validating recursive resolver you trust.
TLSA matching implements the TLSA selector and matching-type operations and checks usages 0-3 against the certificate chain. The result should be read together with the DNSSEC status: a matching TLSA record obtained without DNSSEC validation is not equivalent to authenticated DANE.
SPF / DKIM / DMARC scope
These checks are deliberately DNS-policy diagnostics, not a complete mail-authentication implementation.
SPF checks the record syntax, multiple-record condition, terminal policy, and the ten-DNS-lookup limit at the top level. It does not simulate every possible sender IP through a complete recursive SPF evaluation.
DKIM requires selectors because DNS does not provide a universal way to enumerate all selectors. Example:
./mailcheck example.com --dkim selector1,googleThe DKIM check validates the public-key encoding and RSA key size / Ed25519 key length, but it does not verify a signed message.
DMARC validates the record and key policy tags but does not evaluate an actual message's SPF/DKIM alignment.
Security / operational considerations
The SMTP test performs a real TCP connection to the target's port 25 (or the explicitly selected port). It does not send mail or authenticate.
TLS certificate verification is performed separately from the TLS handshake so that a certificate that is not publicly trusted can still be inspected and compared with a DANE TLSA record. This is intentional for SMTP/DANE diagnostics.
The default TLS client minimum is TLS 1.2. A server that only supports TLS 1.0/1.1 will therefore fail the modern TLS check rather than being silently accepted.
Suggested future extensions
DKIM input
`--dkim` accepts either selectors or complete DKIM owner names. For example:
mailcheck --dkim 2025a,2025b maniac.nl
mailcheck --dkim 2025a._domainkey.maniac.nl.,2025b._domainkey.maniac.nl. maniac.nlA complete owner name is used as-is; it is not prefixed with the domain a second time.
DNS implementation
DNS queries are implemented using the upstream `github.com/miekg/dns` library (v1.1.70), not a hand-written DNS packet encoder/decoder. It provides native RR parsing, UDP/TCP transport, EDNS0 and DNSSEC-related support.
The tool requests DNSSEC data with the EDNS DO bit and reports the resolver's Authenticated Data (AD) bit separately. An AD=true result means the configured recursive resolver authenticated the response; it does not mean `mailcheck` itself is acting as a validating recursive resolver.
DKIM selectors
`--dkim` accepts either selectors:
mailcheck maniac.nl --dkim 2025a,2025bor complete owner names:
mailcheck maniac.nl --dkim 2025a._domainkey.maniac.nl.,2025b._domainkey.maniac.nl.The latter are queried exactly as supplied (apart from normalizing the trailing DNS root dot).
Command-line option order
Both forms are accepted:
mailcheck maniac.nl --json --dkim 2025a
mailcheck --json --dkim 2025a maniac.nlSMTP/TLS diagnostics
The SMTP probe reports the connection as a sequence of stages: TCP, SMTP greeting, EHLO, STARTTLS, and TLS. A failure at an earlier stage no longer incorrectly marks later stages as failures; later stages are reported as `UNKNOWN` because they could not be tested.
Use `--debug` to print the SMTP/TLS exchange diagnostics to stderr without putting protocol chatter into JSON or Nagios stdout:
mailcheck --debug --host mail.example.net example.comFor example, a TCP timeout is reported as `SMTP=CRITICAL` while TLS and TLSA remain `UNKNOWN`, with the underlying socket error included in the summary.
TLSA is reported separately as:
This distinction prevents a failed TCP connection from being reported as a TLS certificate failure.