Mail was just the start.
Try raden.se · platform:microsoft · missing:dmarc · municipalities missing:mta-sts
Mailsec is a small project I built to make it easier to quickly see which basic protections for email, DNS and related infrastructure are in place.
Every check states its source: a published DNS record, an SMTP connection to the MX, a file fetched over HTTPS or a lookup in an external registry. A check that could not be performed is reported as no response, not as failed.
All information in Mailsec is based on publicly available data. Besides scanning individual domains, Mailsec also shows statistics and leaderboards for large parts of the public sector. The score is there to give a quick overview, but also to be a bit of a driver for improvement, at least that's my hope :)
The total is 100 points spread over eight checks. The weight follows how much the check prevents someone from sending email in the domain's name: SPF and DMARC together account for 60 points, CAA and DANE for 5.
| Check | Max | How the points are set |
|---|---|---|
| SPF | 30 | -all gives 30, ~all 25, ?all or no all mechanism 5, +all 0. If the record has no all but has redirect=, the target's all mechanism applies. Deductions: record over 450 bytes (5), ptr (5), more than two void lookups in the chain (5), mechanisms after all (2), a public cloud range wider than /24 in your own records (5), provider networks copied into your own records instead of include: (5), a range in your own records that covers addresses registered to someone else (5); these three together cost at most 10. More than ten DNS lookups, multiple SPF records, a loop or an include without an SPF response is a PermError and gives 0. |
| DMARC | 30 | p=reject gives 30, p=quarantine 25. A record without a valid policy gives 5. p=none gives 0, as does a missing record. pct below 100, including 0, is treated as the next weaker policy (RFC 9989 appendix A.6), as is the testing mode t=y that replaced pct=0 in RFC 9989 (§4.7): reject gives 25 like quarantine, quarantine gives 0 like none. A subdomain without its own record is covered by the organizational domain's sp= (RFC 9989 §4.10.1). |
| MTA-STS | 15 | mode=enforce gives 15, mode=testing 10. mode=none, an invalid policy file or no policy gives 0. An enforce policy whose mx: patterns do not cover the domain's MX gives 10. |
| DNSSEC | 10 | DS in the parent zone matches DNSKEY and the signatures validate: 10. The DNSKEY signature cannot be confirmed: 5. Expired signatures, a broken chain of trust or no DNSSEC: 0. |
| TLS-RPT | 5 | A record with a valid rua=mailto: gives 5. A rua that is not mailto: gives 3, a record without rua gives 2. |
| PQC | 5 | 5 if all MX hosts accept hybrid key exchange (post-quantum) in TLS 1.3 at STARTTLS. Otherwise 0. |
| CAA | 3 | At least one issue or issuewild gives 3. CAA records without either give 1. |
| DANE | 2 | A TLSA record for the domain's MX gives 2. |
| Total | 100 |
| Grade | Score | Meaning |
|---|---|---|
| Excellent | 95-100 | All the heavy checks are in place, only details remain. |
| Good | 80-94 | The sender is protected, transport protection is incomplete. |
| Acceptable | 70-79 | The basics are there, but SPF, DMARC or MTA-STS is not fully tightened. |
| Needs action | 40-69 | SPF or DMARC is missing or in monitoring mode. |
| Critical | 0-39 | The domain can be spoofed. |
Infrastructure is not counted. STARTTLS, IPv6, ASN diversity, DKIM, BIMI, security.txt, on-premises Exchange and on-premises SharePoint are shown because they say something about operations, but they cannot be assessed fairly from the outside and do not affect the score. The number of addresses an SPF record allows is shown, not scored; most of it is usually the mail platform.
The platform in Profile is confirmed when the MX points to it, or when the domain both sends via Microsoft 365 (SPF or DKIM as a CNAME to it) and Autodiscover points to it. Otherwise it is likely: a filter in front of the MX does not show what is behind it. MTA and MX operator are read from what the server itself announces and from the MX name. When the platform is otherwise unknown and the Autodiscover host responds as Exchange, the platform is Exchange on-prem, confirmed by X-OWA-Version, X-FEServer or the OWA login redirect, and likely by Windows authentication on IIS alone.
On-premises Exchange is shown when the Autodiscover host the domain publishes responds as Exchange. The scanner makes one GET to /autodiscover/autodiscover.xml, without logging in. If the host redirects to the same path on another host, that redirect is followed once, so at most two GETs per domain. The version is the build the server announces in its own response headers (X-OWA-Version), compared with Microsoft's list of builds and Security Updates. It comes from the front end that answered: back end servers, Interim Updates and Emergency Mitigation Service mitigations are not visible, and a current build covers only that front end. The owner can confirm with Exchange Health Checker. A build is marked urgent when it predates the fix for a CVE in the CISA Known Exploited Vulnerabilities catalog or with a public proof of concept according to CISA SSVC, or when the version is out of support without Extended Security Updates; the CVEs and their fixed builds come from Microsoft's Security Update Guide. Hosts at Microsoft, by name or in AS8075, are never contacted. It does not affect the score.
On-premises SharePoint is shown when one of a few common host names under the domain, such as sharepoint, sp or extranet, answers a single GET with SharePoint's own response headers; the major build in MicrosoftSharePointTeamServices is compared with Microsoft's lifecycle and Security Update Guide, marked urgent on the same terms as Exchange, and SharePoint Online is never contacted. It is information only and does not affect the score.
Own networks in Profile come from the RIPE Database: the organization is matched on its registered name, or confirmed by Mailsec, and the networks registered to it are listed with their type and, where RIPEstat sees an announcement, the AS that routes them. PA space is assigned from an operator's allocation, PI and legacy space is held directly. An AS alone is never taken as proof. It is information only and does not affect the score.
Name servers shows each delegated name server: whether it answers authoritatively, whether it is not responding, whether the delegation is lame and whether the SOA serial differs between the servers. Different serials mean that the zone transfer is lagging behind (RFC 1034 §4.2).
A check that could not be performed, usually because of a temporary DNS error, is reported as no response instead of 0. No total score is shown then, and the domain is left out of the statistics until the check succeeds. Exception: PQC. If support cannot be determined because the MX is not responding or refuses the handshake, it gives 0 of 5 points and does not blank the grade.
The last successful result is shown for up to seven days when a check has no response. If the check's own endpoint (the policy host for MTA-STS, the web server, the MX) does not respond for seven days, the check counts as a fail: not responding. An error response that persists as long (HTTP 5xx, HTTP 429, or a connection closed after the request) counts as a fail in the same way. If the whole domain is silent to our vantage point, the counter pauses for up to seven days. A block against our vantage point is only reported where we have seen, from an unblocked address, the protection that blocks us. The scanner identifies itself as Mailsec in the User-Agent; bot protection that closes the connection for it is shown as bot protection where we have measured it, never as a fail.
Typeface: Workbench by Jens Kutílek, SIL Open Font License 1.1.