Which Zimbra SpamAssassin file should you edit?
For Zimbra Collaboration Suite 8.5 and later, Zimbra’s documentation places local SpamAssassin customizations in /opt/zimbra/data/spamassassin/localrules. A rule file with a .cf extension can live there; the Zimbra example uses a separate file for a custom rule. Older Zimbra releases used different locations, so verify the version and directory on your server before editing. The current package layout can also vary by release or deployment.
This guide adds a small, reversible site-wide rule, checks its syntax, reloads the mail-scanning service, and verifies a delivered message. It assumes you administer the Zimbra MTA. If you run multiple MTA servers, apply the file and reload SpamAssassin on each server that scans inbound mail.
Zimbra’s custom SpamAssassin rules guide documents the localrules path and the zmamavisdctl restart command. Its anti-spam guidance distinguishes the older ZCS 8 configuration from ZCS 8.5 and later.
What does a custom rule change?
A SpamAssassin rule detects a message feature, assigns a symbolic rule name, and contributes a score. SpamAssassin combines that score with other test results. Zimbra then applies its configured spam handling thresholds. A rule does not, by itself, guarantee that a message goes to Junk or is rejected: the rest of the message score and your server’s settings matter.
That distinction matters when choosing a score. Start with a modest value, inspect false positives, and raise it only when testing shows the signal is reliable. Avoid copying a high score from an example without checking your own required spam score and discard threshold.
Before you edit anything, what should you confirm?
- Release and path: Check your Zimbra version and whether
/opt/zimbra/data/spamassassin/localrules exists. The path in this guide applies to ZCS 8.5 and later according to Zimbra’s documentation. Do not assume it applies to older releases.
- Which host scans mail: Identify every MTA that runs Amavis/SpamAssassin. A rule installed on one server does not automatically appear on another independent MTA.
- Rule intent: Pick a specific, repeatable message signal. Avoid rules that match broad words such as “free” or “offer” without additional evidence.
- Rollback: Record any existing file before changing it. Use a new, descriptive filename for a new rule, and do not overwrite an existing
.cf file accidentally.
These are server-level customizations, not mailbox filters. All users whose mail passes through the configured scanner may be affected.
How do you write a simple rule?
SpamAssassin supports rule types such as header, body, uri, and meta. A header rule is useful when a distinctive subject or header value is the signal. A body rule searches textual message content; SpamAssassin’s documentation notes that ordinary body rules operate on decoded text and treat the Subject as part of the body by default. Use a URI rule when the condition is specifically about links.
Here is a deliberately narrow example that adds a small score when a test message’s subject contains a unique phrase. Replace the phrase with a signal you have verified in your own mail; this example is not a general spam signature.
header LOCAL_SUBJECT_REVIEW Subject =~ /\bExample Vendor Alert\b/i
score LOCAL_SUBJECT_REVIEW 2.0
describe LOCAL_SUBJECT_REVIEW Subject contains the review phrase
The symbolic name should be unique and use letters, digits, and underscores. The header line defines the match, score controls the points added when it hits, and describe supplies an explanation in SpamAssassin’s report. Keep the description short and make it clear to another administrator why the test exists.
SpamAssassin’s configuration reference documents header and body rule syntax, score behavior, and regular-expression details. The installed Zimbra SpamAssassin version may differ from the latest Apache documentation, so avoid relying on newer rule features until you confirm support locally.
How do you install the rule on Zimbra 8.5 and later?
- Connect to the MTA with an administrator account that can switch to the Zimbra service account.
- Check the installation and local-rules directory. For example:
su - zimbra
ls -ld /opt/zimbra/data/spamassassin/localrules
- Choose a filename that does not already exist, such as
local_subject_review.cf. Check first:
ls -l /opt/zimbra/data/spamassassin/localrules/local_subject_review.cf
If it exists, inspect it and select another name instead of overwriting it.
- Create the new file as the
zimbra user with your editor, and add the three rule lines above:
vi /opt/zimbra/data/spamassassin/localrules/local_subject_review.cf
- Save the file, then confirm the owner and contents:
ls -l /opt/zimbra/data/spamassassin/localrules/local_subject_review.cf
cat /opt/zimbra/data/spamassassin/localrules/local_subject_review.cf
If the directory is missing, stop and confirm the Zimbra release and its documented configuration layout. Do not create a similarly named directory in a guessed location; SpamAssassin will not necessarily load it.
How should you validate and reload it?
Run SpamAssassin’s syntax check before reloading. The Apache command-line documentation describes --lint as a rule-set and configuration syntax check. As the Zimbra user, run spamassassin --lint if that executable is available in the Zimbra environment. If the command is not found or does not load Zimbra’s configuration, locate the bundled executable and use the release-appropriate configuration path rather than testing against an unrelated system installation. A clean lint result checks syntax; it does not prove that your pattern will match the messages you intend.
SpamAssassin’s command reference explains the lint option. Once validation succeeds, restart Amavis as the zimbra user so the scanner loads the changed rules:
zmamavisdctl restart
Zimbra’s custom-rules example uses this service command. On a multi-MTA installation, repeat the file deployment and service restart on every applicable scanner. If your release uses a different service command, follow that release’s Zimbra documentation.
How can you tell whether the rule is working?
Send a controlled test message through the same inbound route users use. Use the exact subject phrase from the rule for one message, then send a similar message without it. Inspect the delivered message’s original headers, especially X-Spam-Status, for LOCAL_SUBJECT_REVIEW and the score contribution. Compare the two messages and review where Zimbra delivered each one.
The result is useful if the rule appears only on the intended test and the total score produces the handling you expect. If the test name is absent, verify that the message crossed this MTA, the filename ends in .cf, the file is in the correct localrules directory, the scanner restarted successfully, and the sample actually matches the regular expression. Remember that mail clients may hide diagnostic headers in their normal view; open the message source or full headers.
What if the rule creates false positives or does not match?
- Too many legitimate messages match: Lower the score or narrow the regular expression. Test with examples of both wanted and unwanted mail before raising a score.
- No messages match: Check the exact header name, capitalization-insensitive regular expression, escaping, file extension, path, and service restart. For URLs, evaluate a
uri rule rather than assuming a body rule is the best test.
- Lint reports an error: Correct the indicated line and rerun lint before restarting. A malformed custom rule can cause configuration problems or prevent expected tests from loading.
- Rule appears, but mail stays in Inbox: That can be normal if its added points do not push the total score over your configured spam threshold. Review the full
X-Spam-Status score and local handling thresholds.
To roll back, remove only the custom file you added, then restart Amavis again. If you changed an existing file, restore its saved copy and validate the configuration before reloading. Keep a short change log with the rule’s purpose, score, test messages, and rollback filename so future administrators can reassess it.
Version and behavior limits
Zimbra’s published path guidance explicitly covers ZCS 8.5 and later and documents a different layout for earlier versions. The exact bundled SpamAssassin version and thresholds are installation-specific. A valid rule can also behave differently with different message formats, relays, and mail-flow paths. Check your installed release’s documentation, test on a controlled route, and judge results from message headers and real false-positive samples rather than from the rule text alone.