Send one message to a disposable address and 39 checks run against it. This page is all of them: what each one looks at, what it costs your score when it fails, and the section of the standard it comes from.
Nothing here is our opinion dressed as a rule. Where a check enforces something a standard says, the sentence from that standard is quoted underneath it. Where it enforces something Google or Yahoo requires instead, their page is linked. Where it is our own judgement, it says so.
Authentication
Whether the receiving server can prove the message came from where it says. This is the half of deliverability that is pure DNS, and the half Gmail and Yahoo made mandatory for bulk senders in 2024.
ARC chain auth.arc
ARC preserves the authentication result across a forwarder. Without it, a mailing list that appends a footer breaks your DKIM signature and the forwarded copy fails DMARC at the far end.
If it fails: Nothing to do as a sender. This matters if you run a list or a forwarder, and it explains why some of your mail fails DMARC after somebody forwards it.
Costs up to 2 points of 100 on our score.
RFC 7960 §1 — Introduction
DMARC with restrictive policies causes problems for many Mailing Lists.
RFC 8617 §2.1 — Evidence
In ARC's situation, the "evidence" is a message's authentication assessment at any point along the delivery path between origination and final delivery.
Google — Requirements for bulk senders (5,000+/day)
DKIM signature auth.dkim
DKIM signs parts of the message with a private key and publishes the public key in DNS. We verify every signature the message carries and report the signing domain, the selector and the key length.
If it fails: Turn on DKIM at your sending platform and publish the key it gives you. Use 2048 bits (1024 still verifies, but it is on its way out).
Costs up to 18 points of 100 on our score and up to 1 of 10 on the classic score.
RFC 6376 §3.5 — The DKIM-Signature Header Field
The signature of the email is stored in the DKIM-Signature header field.
RFC 6376 §6.1 — Extract Signatures from the Message
Verifiers MUST NOT attribute ultimate meaning to the order of multiple DKIM-Signature header fields.
Google — Turn on DKIM for your domain
Google — Requirements for bulk senders (5,000+/day)
DKIM alignment auth.dkim_alignment
A valid signature is not enough for DMARC. The signing domain has to match the domain in the From header, exactly or by organisational domain depending on the policy you published.
If it fails: Sign with your own domain rather than your platform's. Most platforms support this and call it a custom or authenticated sending domain.
Costs up to 10 points of 100 on our score and up to 1 of 10 on the classic score.
RFC 7489 §3.1.1 — DKIM-Authenticated Identifiers
DMARC permits Identifier Alignment, based on the result of a DKIM authentication, to be strict or relaxed.
Google — Add a DMARC record
Google — Requirements for bulk senders (5,000+/day)
DMARC result auth.dmarc
DMARC ties SPF and DKIM to the domain your reader sees and tells receivers what to do when neither aligns. We report the published policy and whether this message satisfied it.
If it fails: Publish a DMARC record. Start at p=none, read the reports for a few weeks, then move to quarantine once you know what else sends as you.
Costs up to 14 points of 100 on our score.
RFC 7489 §6.6.2 — Determine Handling Policy
DMARC evaluation can only yield a "pass" result after one of the underlying authentication mechanisms passes for an aligned identifier.
RFC 7489 §6.3 — General Record Format
DMARC records follow the extensible "tag-value" syntax for DNS-based key records defined in DKIM [DKIM].
Google — Requirements for bulk senders (5,000+/day)
Yahoo — Sender requirements and recommendations
Sender ID auth.sender_id
The same check as SPF, run against the domain in the From header rather than the envelope. It answers a different question: whether the domain your reader sees authorises the server that sent the message. A message can pass SPF on its envelope while the visible domain vouches for nobody.
If it fails: Publish SPF for the domain in your From header, not only for the bounce domain your platform gave you.
Costs up to 5 points of 100 on our score and up to 0.5 of 10 on the classic score.
RFC 4406 §4 — Record Selection
After the above steps, there should be one record remaining and evaluation can proceed.
SPF auth.spf
SPF is a DNS record listing which servers may send for your domain. The receiving server takes the address in the envelope, looks up that domain's record and checks whether the connecting IP is in it. We report the result and the number of DNS lookups the record needed, because evaluation stops at ten and anything past that is a permanent error rather than a pass.
If it fails: Publish a record that names your sending platform and nothing else. If yours is close to the ten-lookup limit, flatten the includes you do not use (a record that passes today starts failing the day a provider adds an include of its own).
Costs up to 18 points of 100 on our score and up to 1 of 10 on the classic score.
RFC 7208 §4.6.4 — DNS Lookup Limits
SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation, to avoid unreasonable load on the DNS. If this limit is exceeded, the implementation MUST return "permerror".
RFC 7208 §2.6 — Results of Evaluation
Section 4 defines check_host(), a model function definition that uses the inputs defined above and the sender's policy published in the DNS to reach a conclusion about client authorization.
Google — Define an SPF record
Google — Requirements for bulk senders (5,000+/day)
SPF alignment auth.spf_alignment
Whether the bounce address matches the From address a reader sees. SPF authorises the envelope, and DMARC only counts that authorisation when the two align.
If it fails: Ask your sending platform for a bounce subdomain of your own domain. If your DKIM is already aligned this is not urgent, but it leaves you without a fallback when DKIM breaks in transit.
Costs up to 5 points of 100 on our score and up to 0.5 of 10 on the classic score.
RFC 7489 §3.1.2 — SPF-Authenticated Identifiers
In relaxed mode, the [SPF]-authenticated domain and RFC5322.From domain must have the same Organizational Domain. In strict mode, only an exact DNS domain match is considered to produce Identifier Alignment.
RFC 7489 §6.6.2 — Determine Handling Policy
If one or more of the Authenticated Identifiers align with the RFC5322.From domain, the message is considered to pass the DMARC mechanism check.
Google — Add a DMARC record
Google — Requirements for bulk senders (5,000+/day)
Infrastructure and reputation
The machine and the address the message was sent from, and what the rest of the internet already thinks of them.
Sending hostname resolves infra.a_record
Whether the hostname announced at HELO has an address record at all.
If it fails: Publish an A record for the name your server announces.
Costs up to 5 points of 100 on our score and up to 3 of 10 on the classic score.
RFC 5321 §5.1 — Locating the Target Host
If an empty list of MXs is returned, the address is treated as if it was associated with an implicit MX RR, with a preference of 0, pointing to that host.
Google — MX record values and troubleshooting
Blocklists infra.dnsbl
Whether the sending IP is listed by any of the blocklists receivers actually consult. Our roster is checked against each zone's own documented test point rather than assembled from a web search, because a dead zone answers NXDOMAIN and that reads as "clean".
If it fails: Follow the delisting process on the listing operator's site. A listing on a major zone stops mail outright, so treat it before anything else on the page.
Costs up to 25 points of 100 on our score and up to 3 of 10 on the classic score.
RFC 5782 §2.1 — IP Address DNSxL
Each IPv4 address listed in the DNSxL has a corresponding DNS entry.
RFC 5782 §5 — Test and Contact Addresses
IPv4-based DNSxLs MUST contain an entry for 127.0.0.2 for testing purposes.
Google — Postmaster Tools: reputation and delivery errors
Google — Email sender guidelines
HELO name infra.helo
The name the sending server announces itself as at the start of the SMTP conversation. It has to be a fully qualified domain that resolves.
If it fails: Set your mail server's hostname to a real name in your domain, not to a container id or an internal name.
Costs up to 5 points of 100 on our score.
RFC 5321 §4.1.1.1 — Extended HELLO (EHLO) or HELLO (HELO)
The argument clause contains the fully-qualified domain name of the SMTP client, if one is available.
Google — Email sender guidelines
Google — Requirements for bulk senders (5,000+/day)
MX record infra.mx
Whether the domain in your From header can receive mail. Replies and bounces have nowhere to go without it, and filters treat a sending domain that cannot receive as a bad sign.
If it fails: Publish an MX record for the domain you send from, even if it only routes to a mailbox you read once a month.
Costs up to 5 points of 100 on our score and up to 3 of 10 on the classic score.
RFC 5321 §5.1 — Locating the Target Host
The lookup first attempts to locate an MX record associated with the name.
Google — MX record values and troubleshooting
Reverse DNS infra.rdns
Whether the sending IP resolves back to a hostname, and whether that hostname resolves forward to the same IP. The round trip is the point: a PTR pointing anywhere is easy, a matching pair is evidence the address is yours.
If it fails: Ask whoever owns the IP to set the PTR to a name you control, and make sure that name has an A record pointing back.
Costs up to 12 points of 100 on our score and up to 1.5 of 10 on the classic score.
RFC 1912 §2.1 — Inconsistent, Missing, or Bad Data
Make sure your PTR and A records match. For every IP address, there should be a matching PTR record in the in-addr.arpa domain.
Google — Email sender guidelines
Google — Requirements for bulk senders (5,000+/day)
Transport encryption infra.tls
Whether the message arrived over TLS, and with which cipher. Everything modern negotiates it; a message arriving in the clear says something about the sending setup.
If it fails: Enable STARTTLS on the sending server. Every mainstream platform does this already, so a failure here usually means a self-hosted relay in the path.
Costs up to 5 points of 100 on our score.
RFC 3207 §2 — STARTTLS Extension
The STARTTLS extension to SMTP is laid out as follows:
Google — Require TLS for secure message transport
Google — Requirements for bulk senders (5,000+/day)
Spam engines
What independent content filters make of the message. Two engines rather than one, because a single engine's score is that engine's opinion.
AI judge spam.ai_judge
A model estimates how a modern machine-learning filter would treat the message, from the technical findings and the content measurements. It sees the facts, not the body text.
If it fails: Detail only on its own. Its estimate feeds the combined verdict below.
Shown for detail. Never scored.
Combined verdict spam.panel
One number from the engines that answered, weighted so the loudest is not simply averaged away. SpamAssassin and Postmark count as a single vote because they share a rule base.
If it fails: Work through the individual findings. This row moves when they do.
Costs up to 25 points of 100 on our score.
Google — Why Gmail marks messages as spam
How this score is calculated
Postmark SpamCheck spam.postmark
A third opinion, off by default. Its endpoint takes the whole message and we cannot redact any of it without destroying what is being measured, so switching it on means accepting that every tested message is copied to a third party.
If it fails: Nothing to do. When it is off the check reports that it is off, which is not the same as a pass.
Shown for detail. Never scored.
Rspamd spam.rspamd
A second, independently developed filter. It disagrees with SpamAssassin often enough to be worth asking, which is the reason it is here.
If it fails: Detail only. This engine's opinion is folded into the combined verdict rather than scored on its own.
Shown for detail. Never scored.
SpamAssassin spam.spamassassin
The classic rule-based filter, still the engine behind most email testing tools. Every rule that fired is listed with its weight.
If it fails: Read the rules that fired rather than the total. Most are cheap to clear once you can see which ones they are.
Costs up to 3 of 10 on the classic score.
Google — Why Gmail marks messages as spam
Apache SpamAssassin — rule documentation
Content
The message itself: its structure, its links, its images, the things a filter reads before it decides.
Image alt text content.alt_attributes
Whether images carry alt attributes. Mail clients block remote images by default, so for the first few seconds the alt text is your message.
If it fails: Write alt text that carries the meaning, and never leave the main visual without one.
Costs up to 4 points of 100 on our score and up to 0.5 of 10 on the classic score.
Google — Email sender guidelines
Link availability content.broken_links
Whether the links in the message resolve. A dead link in a newsletter costs trust immediately, and filters notice too.
If it fails: Fix or remove them. Check the tracking domain as well: an expired one breaks every link at once.
Costs up to 5 points of 100 on our score and up to 1 of 10 on the classic score.
Google — Why Gmail marks messages as spam
Script and iframe content.forbidden_tags
Whether the HTML contains tags no mail client will run. They are stripped at best and treated as an evasion signal at worst.
If it fails: Remove script, iframe, object and embed. Anything interactive belongs behind a link.
Costs up to 10 points of 100 on our score and up to 1 of 10 on the classic score.
Google — Email sender guidelines
Text to HTML balance content.html_text_ratio
How much of the message is markup against how much is readable text. A page of markup wrapped around one sentence is a shape filters recognise.
If it fails: Write a text part that says what the HTML says, rather than a placeholder.
Costs up to 3 points of 100 on our score and up to 0.3 of 10 on the classic score.
RFC 2046 §5.1.4 — Alternative Subtype
Systems should recognize that the content of the various parts are interchangeable.
Google — Why Gmail marks messages as spam
Text and HTML parts content.html_version
Whether the message carries a plain text alternative alongside the HTML. Some filters weigh its absence, and every screen reader wants one.
If it fails: Send multipart/alternative with a real text version, not an empty part or a line saying to view it in a browser.
Costs up to 5 points of 100 on our score.
RFC 2046 §5.1.4 — Alternative Subtype
The "multipart/alternative" type is syntactically identical to "multipart/mixed", but the semantics are different. In particular, each of the body parts is an "alternative" version of the same information.
Google — Email sender guidelines
HTML size content.html_weight
How large the HTML part is. Gmail clips a message past roughly 102 KB and hides the rest behind a link, which takes your unsubscribe footer with it.
If it fails: Trim inline CSS and repeated style blocks (most templates fit in a third of the limit once the unused rules are gone).
Costs up to 3 points of 100 on our score and up to 0.3 of 10 on the classic score.
Google — Email sender guidelines
Image weight content.images_weight
The total size of the images the message pulls in. Heavy images make a message slow on a phone, and image-only mail is a shape filters treat with suspicion.
If it fails: Compress them and make sure the message still reads with images off.
Costs up to 3 points of 100 on our score and up to 0.3 of 10 on the classic score.
Google — Email sender guidelines
Link reputation content.malicious_links
Whether any link is listed by a threat feed. One listed link blocks the message regardless of everything else being right.
If it fails: Remove it. If it is your own domain, you have a compromise to deal with before you send anything else.
Costs up to 40 points of 100 on our score.
Google — Why Gmail marks messages as spam
Attachment scanning content.malware
Whether attachments carry known malware. On deployments where the scanner is switched off, this reports that it did not run rather than reporting clean.
If it fails: If this fires, stop sending and find out what is on the machine that built the message.
Costs up to 60 points of 100 on our score.
Google — Why Gmail marks messages as spam
ClamAV — how detection works
Subject line content.subject
Length, capitalisation and the patterns filters score. We measure the decoded subject, so a Cyrillic or CJK line is judged as text rather than as its encoding.
If it fails: Keep it under about 60 characters, drop the shouting and the exclamation marks.
Costs up to 3 points of 100 on our score.
RFC 5322 §2.2 — Header Fields
Header fields are lines beginning with a field name, followed by a colon (":"), followed by a field body, and terminated by CRLF.
RFC 2047 §2 — Syntax of encoded-words
An 'encoded-word' is defined by the following ABNF grammar.
Google — Why Gmail marks messages as spam
Shortened links content.url_shortener
Whether links go through a public shortener. Shorteners hide the destination, which is exactly what filters are trained to distrust.
If it fails: Link your own domain, or use your platform's tracking domain on a subdomain of yours.
Costs up to 5 points of 100 on our score and up to 0.5 of 10 on the classic score.
Google — Why Gmail marks messages as spam
Recommendations
Worth doing and never scored. Nothing in this section can cost points, which is a product decision the tests enforce.
BIMI advisory.bimi
Whether the domain publishes a BIMI record, which puts a logo next to your messages in some clients. It needs an enforcing DMARC policy first, and a verified mark certificate that costs money.
If it fails: Worth doing once DMARC is at quarantine or reject and the volume justifies the certificate.
Advisory. Costs nothing.
BIMI — draft specification, not yet an RFC
DKIM key age and length advisory.dkim_key_rotation
The length of the signing key and how long it has been in use. Short keys are cheaper to attack offline every year that passes.
If it fails: Move to 2048 bits and rotate on a schedule. Publish the new selector, switch signing to it, then retire the old one.
Advisory. Costs nothing.
RFC 8301 §3.2 — Key Sizes
Since short RSA keys more easily succumb to off-line attacks, Signers MUST use RSA keys of at least 1024 bits for all keys. Signers SHOULD use RSA keys of at least 2048 bits.
Google — Turn on DKIM for your domain
DNSSEC advisory.dnssec
Whether the domain is signed. SPF, DKIM and DMARC all live in DNS, so an attacker who can forge DNS answers can forge all three.
If it fails: Enable it at your registrar. It is usually one switch, and the registrar handles the rest.
Advisory. Costs nothing.
RFC 4033 §2 — Definitions of Important DNSSEC Terms
Authentication Chain: An alternating sequence of DNS public key (DNSKEY) RRsets and Delegation Signer (DS) RRsets
MTA-STS advisory.mta_sts
Whether the domain publishes a policy telling other servers to refuse unencrypted delivery to you. It protects mail sent to you rather than mail you send.
If it fails: Publish the TXT record and the policy file over HTTPS (an afternoon of work, and it closes a downgrade attack).
Advisory. Costs nothing.
RFC 8461 §3 — Policy Discovery
To discover if a recipient domain implements MTA-STS, a sender need only resolve a single TXT record.
TLS reporting advisory.tls_rpt
Whether the domain asks for reports when somebody fails to deliver to it over TLS. Pairs with MTA-STS: the policy without the reporting leaves you unable to tell whether it is working.
If it fails: Add the TXT record with an address that receives the daily reports.
Advisory. Costs nothing.
RFC 8460 §3 — Reporting Policy
A domain publishes a record to its DNS indicating that it wishes to receive reports.