Spam filtering, for the most part, happens behind a curtain. When Gmail marks an email as spam, nobody outside its closed walls gets to see why. SpamAssassin is the odd exception. It shows its work, hands over a number, and labels every single rule that produced it.
That openness is both a blessing and a curse. Most of us see numbers as the whole truth, so numbers get screenshotted, forwarded to a developer with three question marks, and treated as a guaranteed problem. They do matter, but pure numbers give a far narrower answer than we’re hoping to get.
SpamAssassin has been scoring mail since 2001 and still powers nearly every deliverability testing tool you’ve ever used, yet it almost certainly had no say in where your last campaign landed.
So what is its score made of, who is running it, and why does one email come back with two different totals on two different days? All three have satisfying answers, and by the end of this article, these reports will stop reading like ransom notes.
Key Takeaways
- A SpamAssassin score measures the weighted spam-filtering rules an email triggers. A lower score is better, with 5.0 used as the default spam threshold.
- Your score can vary between tests because SpamAssassin rules and thresholds depend on how each server is configured.
- A low SpamAssassin score does not guarantee inbox placement because Gmail and other major mailbox providers use their own filtering and reputation signals.
Twenty-five years on, still going strong
Some industry experts argue that SpamAssassin is a relic, propped up by hosting companies too busy to replace it. Given the version numbers in most tutorials, that claim is understandable, but it’s not entirely true.
The project released its first version in April 2001 and shipped 4.0.2 in August 2025. The 4.0 line brought native UTF-8 handling so the filter could properly evaluate mail in languages other than English, along with improved detection of dangerous Office macros. SpamAssassin is being updated continuously through a channel called sa-update, independently of the software itself, which is how a filter written before Gmail existed still catches spam invented last month.
However, that same longevity causes some blind spot. SpamAssassin was designed for a world where every mail server ran its own filter and needed a transparent, tunable, locally auditable way to sort mail. That world still exists in shared hosting and corporate gateways but not anymore at consumer scale, where a handful of providers each see billions of messages a day and can train on user behaviour instead of writing rules by hand.
That itself is not a downside. It’s two entirely different problems, solved by two entirely different tools, though only one of them will ever give you a report.
Where the points come from
The mechanism is almost disappointingly simple. SpamAssassin runs a message through hundreds of tests, and every test that matches contributes its point value to a running total, which is then evaluated by a setting called required_score. A matched test is called a hit. That’s it!
But notice what’s missing from that description: any feedback about your brand, your offer, or your writing. This is precisely why the old “avoid spammy words” advice has aged so badly. Most of the strict rules never look at the email copy at all.
What you see on a delivered message looks like this:
X-Spam-Status: No, score=1.4 required=5.0
tests=HTML_MESSAGE,DKIM_VALID,SPF_PASS
Three useful things there. score is your total, required is the threshold on that particular server, and tests labels everything that matched so you can reverse-engineer the problem. There’s also an X-Spam-Level header that renders the score as a row of asterisks, one per whole point, for administrators who prefer to skim.
Why 5.0 is stricter than intended
The 5.0 threshold has become gospel in email deliverability content, largely because it’s the default and because testing tools use it as the pass mark. The Apache documentation is noticeably less dramatic about it. It describes 5.0 as “quite aggressive,” recommends 8.0 or 10.0 for ISP-scale installations, and advises against deleting flagged mail at all, suggesting that anyone who insists on it should only do so above 15.0.
Now imagine a tool that just painted your 5.4 in urgent red. On a stock single-mailbox install, you failed, but on a mail provider configured the way the project itself recommends, you passed comfortably with room to spare.
Before that becomes too comforting, keep in mind that the score swings both ways. Administrators can go stricter just as easily, and plenty do, which is why “under 5” is a minimum rather than a target. Getting below 3.0 still calls for deliverability problems you’d expect with a high spam score.
Why your score changes between tests
![]()
A single rule can have up to four separate point values, and which one applies depends on two switches: whether the Bayesian classifier is enabled, and whether network tests are enabled. Both off, network only, Bayes only, or both on. Four configurations, four possible scores for the identical rule. If you’re running local SpamAssassin tests with network lookups disabled, you’re being graded by a different scoring set than the one your recipient’s server will use.
Bayesian filtering has a second quirk that almost nobody accounts for. The classifier stays dormant until it’s been trained on a minimum number of messages, defaulting to 200 spam and 200 non-spam. On a freshly built server, every BAYES rule contributes precisely nothing, because the filter hasn’t formed an opinion about anything yet. Your score isn’t wrong in that scenario. It’s just incomplete, and the report will never mention it.
The rules that punish perfectly ordinary marketing email
Opening the actual rules file makes the picture more concrete. An entire family of tests measures how much readable text accompanies your images, sorted into buckets:
- HTML_IMAGE_ONLY_04 – images with 0 to 400 bytes of words
- HTML_IMAGE_ONLY_16 – images with 1200 to 1600 bytes of words
- HTML_IMAGE_ONLY_28 – images with 2400 to 2800 bytes of words
- HTML_IMAGE_ONLY_32 – images with 2800 to 3200 bytes of words
It’s a ladder, and the rung you land on depends on how much copy there is relative to your imagery. Once your message contains at least 3,200 bytes of actual text (roughly 500 words), none of the HTML_IMAGE_ONLY rules match you at all, and you’ve crossed the threshold where the ratio is no longer suspicious.
Nearby you’ll find tests for a low ratio of text to image area, font colour suspiciously similar to the background, and huge font sizes. Structural tests, all of them, and yet not a single one is looking for the word “free” in your subject line.
There’s a nasty edge case here that catches transactional and announcement mail. The parser counts image tags without much interest in their dimensions, so the rule can match even when the only image in the message is a tracking pixel. A four-sentence shipping notification with an open tracker attached is, as far as this family of rules is concerned, a picture with some words next to it.
One line in your report you can safely ignore
If you see URIBL_BLOCKED in your report, ignore it. It doesn’t mean you’re on a blocklist. It means the query never completed, usually because the DNS resolver in use exceeded its free query allowance, which happens constantly on installations pointed at public resolvers. Apache’s own wiki treats it as a plain configuration problem and tells administrators to run a local caching nameserver.
It contributes essentially zero points. It’s a note about the server that scanned you, not about your domain, and it remains the single most reliable source of unnecessary panic in these reports.
The limit of what the score can tell you
So where does all this actually apply? SpamAssassin is usually found in shared hosting, where cPanel’s spam filtering feature is built on it, inside self-hosted gateway stacks using Exim, Postfix, MailScanner or Amavis, and as the scoring engine behind most pre-send testing tools. That covers an enormous number of business mailboxes and every deliverability report you’ve ever run.
It does not cover the destination that decides most of your campaign’s fate. Google’s description of Gmail filtering is machine learning trained on user feedback, evaluating IP characteristics, domains and subdomains, sender authentication, and user input, with the filters learning from what recipients do. No point totals, no rule names, no threshold you can test in advance.
This conclusion reframes the whole exercise. A 0.4 is genuine, useful confirmation that your HTML is well formatted, your authentication is valid, and your message structure won’t trigger a rules engine. It is not evidence that Gmail wants your mail, because what Gmail is measuring is what people do after the message lands, and no static scan can observe that. Both things can happen on the same send: a flawless report and the spam folder.
Conclusion
There’s a particular kind of dread that comes from a red bar and a list of rule names you didn’t write and can’t interpret, but hopefully this article has helped ease some of that.
SpamAssassin is a careful, honest, twenty-five-year-old piece of engineering that will tell you exactly what it found, which is essentially whether your message is put together properly. That’s an important question, and it deserves an answer. But the question that’s probably keeping you up at night is what happens after the message arrives, and no scanner has ever been able to see that far.
A better SpamAssassin score can reduce rule-based filtering issues, but it does not guarantee inbox placement. Gmail uses its own reputation and engagement signals to decide where your emails land. InboxAlly helps you strengthen those signals through realistic seed engagement, including opens, clicks, replies, and spam-folder rescues. Start a free trial and start working toward more consistent inbox placement.