Overview

The validated baseline is the openSUSE-based grommunio appliance 2026.06.1. The examples consistently use the neutral appliance domain https://mail.example.test; paths such as /web/, /admin/, /auth/, /chat/, /meet/ and /files/ live on the same appliance.This article shows how to validate, configure and test grommunio-antispam with Rspamd on an existing grommunio appliance.

You open Rspamd from grommunio Admin and test GTUBE, history, symbols, Bayes learning, allowlist, denylist, logs and technical acceptance.

Tested environment

  • grommunio 2026 on the openSUSE-based grommunio appliance.

  • All appliance commands are run directly on the grommunio appliance.

  • Public examples consistently use the neutral appliance domain https://mail.example.test.

Prerequisites

An existing or planned grommunio environment, matching DNS names, TLS, administrative access and a clear target for mail, collaboration or operations.

Goal of this guide

This guide builds on the grommunio 2026.06.1 installation and shows step by step how you understand, verify, test, train and operate grommunio-antispam with Rspamd. It is deliberately practical: you get commands, checkpoints, real appliance screenshots and guidance on which values you should not copy blindly into production.

  • You identify which Rspamd processes run inside grommunio.

  • You test the mail filter with a safe GTUBE test message.

  • You read score, action, symbols and history correctly.

  • You train spam and ham in a controlled way.

  • You understand which features matter in production: SPF, DKIM, DMARC, RBL/SURBL, fuzzy checks, greylisting, rate limits, neural/Bayes, multimap and monitoring.

The baseline installation is here: install grommunio 2026.06.1.

Validated appliance basis

This guide was validated against an isolated grommunio appliance. Hostname, domain and messages are synthetic, but the steps follow the production administration path. The Rspamd web interface was not exposed through a free controller port; it was validated through the grommunio admin path `https://mail.example.test:8443/antispam/`.

bash
hostname -f
cat /etc/os-release | grep -E '^(PRETTY_NAME|VARIANT|ID_LIKE)='
rpm -qa | grep -Ei 'grommunio-antispam|rspamd|postfix|redis' | sort
rspamd --version

Validation used grommunio 2026.06.1 with grommunio-antispam 4.1.5, Postfix 3.10.2 and Redis 8.2.3. Important: this appliance used XFS for the root filesystem and systemd-networkd for network configuration. That is the validated appliance state, not a general statement about every SUSE or SLES installation.

Architecture: Postfix, Rspamd and Redis

grommunio-antispam is based on Rspamd. Rspamd is a modular mail filter: a message is evaluated by multiple independent checks. Each check produces a symbol and optionally a score. The accumulated score results in an action such as no action, add header, greylist or reject.

  • Postfix receives mail and passes it to Rspamd via milter.

  • The proxy worker listens locally on port 11332.

  • Normal workers scan messages on port 11333.

  • The controller with web UI and API listens locally on port 11334.

  • Redis stores state such as Bayes, history, greylisting, rate limits and other learning data.

bash
ss -ltnp | grep -E ':(25|587|11332|11333|11334)\b'
postconf -n | grep -Ei 'milter|content_filter'
systemctl list-units --type=service --all | grep -Ei 'redis|valkey'

On the validated appliance, `smtpd_milters = inet:localhost:11332` was configured. The controller was reachable only locally or through the grommunio admin path. That is the right production model as well: publish mail services as needed, but keep the antispam controller inside a management network, behind VPN or behind explicit IP rules.

Step 1: Verify services and configuration

Always start with a state check. If services are not running or configuration does not parse, every functional filter analysis is meaningless.

bash
systemctl is-active grommunio-antispam postfix redis@grommunio
rspamadm configtest
rspamc stat
journalctl -u grommunio-antispam --since "30 minutes ago" --no-pager

Expected output is `syntax OK`, an active antispam service and plausible `rspamc stat` output. Evaluate warnings carefully: DNS failures, missing maps or broken local includes are often operational issues, while a freshly built system naturally has little statistical data.

Step 2: Open the web interface from the admin interface

On the validated appliance, open Rspamd directly from the grommunio admin interface. The reachable URL is `https://mail.example.test:8443/antispam/`; a separate public controller port is not needed for this path.

bash
https://mail.example.test:8443/antispam/
https://mail.example.test:8443/antispam/

Screenshot: Dashboard of the validated grommunio 2026.06.1 appliance with grommunio-antispam 4.1.5.

Step 3: Understand actions, scores and symbols

Rspamd does not make a magical yes/no decision. It collects symbols, adds scores and recommends an action. In the validated configuration, the thresholds were greylist 4, add header 6 and reject 15. In production, change these values only after observing real mail flows.

https://mail.example.test:8443/antispam/

Screenshot: Actions and maps in the Rspamd configuration; local overrides should be controlled and documented.

bash
rspamadm configdump actions
rspamadm configdump spf
rspamadm configdump dkim
rspamadm configdump dmarc

Do not edit shipped defaults directly. Add local files in `local.d` and always run `rspamadm configtest` afterwards. In the grommunio appliance, the configuration path is `/etc/grommunio-antispam`; generic Rspamd documentation often uses `/etc/rspamd`.

Step 4: Scan a first message

Create a harmless synthetic message first and scan it with `rspamc symbols`. Do not look only at the action; look at the reasoning: missing Received headers, test domains or DNS issues can cause higher scores for synthetic messages than in a real mail flow.

bash
cat > /tmp/ham.eml <<'EOF'
From: Alex Example <alex@example.test>
To: Admin Example <admin@example.test>
Subject: Testtermin für Mailfilter
Date: Mon, 7 Sep 2026 10:00:00 +0200
Message-ID: <ham-001@example.test>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Hallo,
das ist eine harmlose interne Testnachricht für die Antispam-Validierung.
EOF
rspamc symbols < /tmp/ham.eml

In the validated environment, this message was classified as `add header` because of synthetic characteristics. This is a useful example: the technology works, but the data basis is not identical to a real production message.

Step 5: Test spam safely with GTUBE

Use GTUBE for reproducible tests. It is a harmless test signature that spam filters are expected to classify as spam. This avoids storing or forwarding real spam.

bash
cat > /tmp/gtube.eml <<'EOF'
From: Sender Example <sender@example.net>
To: Alex Example <alex@example.test>
Subject: GTUBE Funktionstest
Date: Mon, 7 Sep 2026 10:05:00 +0200
Message-ID: <spam-gtube-001@example.net>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
This is a safe spam-filter test message.
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
EOF
rspamc symbols < /tmp/gtube.eml

The GTUBE test returned `Action: reject`, `Score: 15.00 / 15.00` and the `GTUBE` symbol. This validates the filter path from client to Rspamd action.

https://mail.example.test:8443/antispam/

Screenshot: Scan/Learn with GTUBE: the interface shows reject, score and triggering symbol.

Step 6: Use Bayes learning carefully

Bayes learning is valuable, but only with clean training data. Train clear spam examples as spam and clear false positives as ham. If users report everything without review, you can make filtering worse.

bash
rspamc learn_spam /tmp/gtube.eml
rspamc learn_ham /tmp/ham.eml
rspamc stat

After learning, the dashboard showed a ham learn entry. In production, add a reporting workflow, sample review, backup of state data and regular false-positive checks.

Step 7: Read history and concrete causes

History is the fastest path from a user complaint to the cause. Open the concrete message and check sender, recipient, subject, action, score, scan time and symbols. Only then decide whether DNS, reputation, content, attachment, URL, Bayes or a local rule caused the classification.

https://mail.example.test:8443/antispam/

Screenshot: History after the functional test with action, score, symbols and scan time.

bash
journalctl -u postfix --since "2 hours ago" --no-pager
journalctl -u grommunio-antispam --since "2 hours ago" --no-pager
mailq

Step 8: Use symbols as tuning input

The symbols view shows which checks exist and how they are scored. This is a better starting point than blindly raising thresholds. If a symbol repeatedly produces wrong results, first check DNS, local maps, authentication and real examples.

https://mail.example.test:8443/antispam/

Screenshot: Symbols show which individual checks Rspamd includes in the overall score.

Wrong classification: analyse first, add exceptions later

Allowlisting is not the first step. If you immediately allow a legitimate message without understanding the cause, you hide DNS, authentication, reputation or training problems. Work in this order:

bash
Message classified incorrectly?
-> Are SPF, DKIM and DMARC correct?
-> Are IP, domain and URL reputation plausible?
-> Are Bayes or neural involved?
-> Is a local rule, map or override involved?
-> only then add a controlled allowlist, denylist or exception

Step 9: Plan allowlists, denylists and multimap cleanly

Exceptions are useful, but dangerous when too broad. Separate rule definition from dynamic map files: the multimap rule lives in `/etc/grommunio-antispam/local.d`, while lists maintained by admin workflows live under `/var/lib/grommunio-antispam`. This keeps package defaults untouched and lets you back up, version or maintain the lists through an internal tool.

bash
install -d -m 0750 -o groas -g grommunio /var/lib/grommunio-antispam/maps
cat > /etc/grommunio-antispam/local.d/multimap.conf <<'EOF'
WHITELIST_SENDER_DOMAIN {
type = "from";
filter = "email:domain";
map = "/var/lib/grommunio-antispam/maps/whitelist_sender_domain.map";
score = -5.0;
description = "Whitelisted sender domains reviewed by mail operations";
}
WHITELIST_SENDER_ADDRESS {
type = "from";
filter = "email";
map = "/var/lib/grommunio-antispam/maps/whitelist_sender_address.map";
score = -5.0;
description = "Whitelisted sender addresses reviewed by mail operations";
}
BLACKLIST_SENDER_DOMAIN {
type = "from";
filter = "email:domain";
map = "/var/lib/grommunio-antispam/maps/blacklist_sender_domain.map";
score = 8.0;
description = "Blacklisted sender domains reviewed by mail operations";
}
BLACKLIST_SENDER_ADDRESS {
type = "from";
filter = "email";
map = "/var/lib/grommunio-antispam/maps/blacklist_sender_address.map";
score = 8.0;
description = "Blacklisted sender addresses reviewed by mail operations";
}
EOF
printf '%s\n' 'partner.example' > /var/lib/grommunio-antispam/maps/whitelist_sender_domain.map
: > /var/lib/grommunio-antispam/maps/whitelist_sender_address.map
: > /var/lib/grommunio-antispam/maps/blacklist_sender_domain.map
: > /var/lib/grommunio-antispam/maps/blacklist_sender_address.map
chown groas:grommunio /var/lib/grommunio-antispam/maps/*.map
chmod 0640 /var/lib/grommunio-antispam/maps/*.map
rspamadm configtest
systemctl reload grommunio-antispam
rspamc symbols < /tmp/ham.eml | grep -E 'WHITELIST|BLACKLIST|Action|Score' || true

Use specific senders, partner domains or technical relay IP addresses. Do not globally allow large freemail or cloud domains. After every change, run `rspamadm configtest`, reload the service, send or scan a concrete test message and check history, score and symbols.

Production changes need a review process: who may add exceptions, how long do they last, which samples justify the exception and when is it reviewed again?

Step 10: Understand test selectors

Selectors extract fields from messages. They help you verify whether a rule sees the value you expect: SMTP sender, recipient, headers, subject, IP, MIME structure or URL components.

https://mail.example.test:8443/antispam/

Screenshot: Test selectors with a synthetic message; useful before adding custom rules and maps.

Important feature areas in grommunio-antispam

Group the features by problem class. Reputation answers whether sender, IP, domain or URL look trustworthy. Content and phishing checks inspect body, links, attachments and patterns. Delivery controls shape delivery behaviour and speed. Learning adjusts classification through clean training data. These groups help you avoid solving every problem with the same exception.

  • SPF, DKIM, DMARC and ARC validate identity and authenticity of mail flows.

  • RBL and SURBL evaluate IPs, domains and URLs through reputation data.

  • Fuzzy checks detect known or similar spam content.

  • Bayes and neural improve classification through training and learning models.

  • Greylisting and rate limits slow suspicious delivery patterns.

  • Multimap, force actions and local maps implement controlled exceptions and rules.

  • Milter headers can make results visible in message headers.

  • External services and antivirus integration are extension points, but they need deliberate planning and monitoring.

https://mail.example.test:8443/antispam/

Screenshot: Throughput and actions support operations, especially after policy or DNS changes.

Place SPF, DKIM, DMARC and ARC correctly

These checks are not cosmetic extras; they are the trust chain of your mail domains. SPF validates whether the sending server belongs to the domain. DKIM validates the message signature. DMARC combines SPF and DKIM with a domain policy. ARC helps when messages pass through forwarders or mailing lists.

bash
dig TXT example.com +short
dig TXT _dmarc.example.com +short
dig TXT default._domainkey.example.com +short
# DMARC für neue Domains zuerst beobachten:
# v=DMARC1; p=none; rua=mailto:dmarc@example.com
# Erst nach Auswertung verschärfen:
# v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com
# v=DMARC1; p=reject; rua=mailto:dmarc@example.com

For production domains, usually start DMARC in observation mode. Once legitimate senders, forwarders, newsletter systems and partner mail servers are understood, you can move deliberately to `quarantine` or `reject`.

Evaluate RBL, SURBL and URL checks

RBLs evaluate sending IPs or networks, while SURBL and URL checks evaluate domains and links inside the message. These hits are often strong signals, but should not be interpreted in isolation. For false positives, check whether a legitimate service is compromised, misconfigured or only temporarily listed.

bash
rspamadm configdump rbl
rspamadm configdump surbl
rspamc symbols < /tmp/gtube.eml | grep -E 'RBL|SURBL|URL|PHISH|Action|Score' || true

Validate fuzzy, phishing and content patterns

Fuzzy checks detect known or similar content without requiring every message to be identical. Phishing and URL modules evaluate suspicious targets, redirects and patterns. In production, DNS must work reliably and external lookups must not be slowed down by firewall, proxy or resolver issues.

bash
rspamadm configdump fuzzy_check
rspamadm configdump phishing
journalctl -u grommunio-antispam --since "1 hour ago" --no-pager | grep -Ei 'fuzzy|phishing|surbl|resolve|timeout' || true

Enable greylisting and rate limits deliberately

Greylisting delays suspicious delivery attempts, and rate limits restrict unusual sending patterns. Both features can be effective, but they intentionally introduce friction. Do not enable them blindly; operate them with monitoring, exceptions for legitimate systems and clear communication.

bash
rspamadm configdump greylist
rspamadm configdump ratelimit
rspamc stat | grep -Ei 'greylist|reject|add header|no action'

Operate Bayes, neural and training data

Bayes and neural are learning mechanisms. They need clean data, time and control. A fresh system already catches a lot through rules, reputation and authentication; learning becomes important when real false positives and false negatives are classified cleanly.

bash
rspamadm configdump classifier-bayes 2>/dev/null || rspamadm configdump statistics
rspamadm configdump neural
rspamc stat

Treat training data as operational data. If Redis, Bayes or maps are lost, the filter does not start from zero technically, but important local experience is missing.

Spam gets through: check false negatives

When spam gets delivered, do not immediately raise global thresholds. First verify whether the message passed through the filter path, which symbols were set and whether a local exception lowered the score.

  1. Check scan and milter path: Postfix must reach Rspamd.

  2. Open history and read action, score, symbols and scan time.

  3. Check reputation: RBL, SURBL, URL checks and DNS resolution.

  4. Check Bayes/neural: was the message incorrectly learned as ham?

  5. Check local maps: allowlist, force action or override involved?

  6. Learn as spam in a controlled way and then retest with a comparable message.

  7. Add a custom rule only when you have repeatable samples and a clear cause.

bash
postconf -n | grep -Ei 'milter|smtpd_milters'
journalctl -u postfix --since "2 hours ago" --no-pager | grep -Ei 'milter|rspamd|reject|warning' || true
rspamc symbols < /tmp/suspect.eml
rspamc learn_spam /tmp/suspect.eml
rspamadm configtest

Integrate antivirus and external services consciously

grommunio-antispam provides interfaces for antivirus and external checks. Whether you enable them depends on operating model, privacy, latency, licensing and existing security architecture. The key point: external checks must be monitored so timeouts do not damage mail flow.

bash
rspamadm configdump antivirus
rspamadm configdump external_services
journalctl -u grommunio-antispam --since "1 hour ago" --no-pager | grep -Ei 'antivirus|external|timeout|error' || true

Monitoring and Day-2 operations

In daily operations, rejects are not the only signal. Monitor scan time, queue length, DNS resolution, Redis state, mail volume, error log, certificates, disk space, updates and unusual action shifts. This is where dashboard, throughput, history and logs become valuable together.

bash
systemctl is-active grommunio-antispam postfix redis@grommunio
mailq
rspamc stat
df -h
journalctl -u grommunio-antispam --since "24 hours ago" --no-pager | tail -200

Plan backup and restore realistically

Rspamd does not store mailbox data. For grommunio-antispam, back up local configuration, local maps and relevant state data. Not every Redis counter is equally critical, but Bayes/learn state, history, greylisting and rate-limit state can matter for operations and analysis.

  • Back up: `/etc/grommunio-antispam`, local includes, local maps under `/var/lib/grommunio-antispam`, documented secrets and operational notes.

  • Review: Redis data, Bayes/learn state, history, greylisting and rate limits depending on your desired recovery behaviour.

  • Do not confuse this: mailbox data lives in grommunio/Gromox, not in Rspamd/Redis.

  • After restore, test: `rspamadm configtest`, service start, web interface, GTUBE, ham test, history and a real delivery path.

Order in the grommunio series

If you are building grommunio from scratch, start withthe installation guide. This antispam article is the next Day-2 step. For SSO and central authentication, continue withgrommunio-auth.

More product context is available on the grommunio-antispam page.

Automatic spam learning with grommunio-spam-run

The tested grommunio 2026.06.1 appliance ships its own spam-training implementation: grommunio-spam-run.service and grommunio-spam-run.timer. Do not use old community scripts as the default path. The delivered script is /usr/sbin/grommunio-spam-run.sh and learns messages from users’ Junk folders with rspamc learn_spam.

Important: learning is not the same as deleting. The timer calls the script without a delete argument. Deleting trained Junk messages happens only when the script is started deliberately with -d. Do not enable automatic deletion blindly, because false positives could otherwise be trained first and removed afterwards.

bash
systemctl cat grommunio-spam-run.service
systemctl cat grommunio-spam-run.timer
systemctl status grommunio-spam-run.timer
rspamc stat

In the validated lab, service and timer existed but were not enabled by preset. The manual run completed successfully; without prepared training messages, the learned-message counter remained at 0 as expected. In production, enable the timer only after the Junk-folder process, false-positive handling and monitoring are clear.

bash
systemctl enable --now grommunio-spam-run.timer
systemctl start grommunio-spam-run.service
journalctl -u grommunio-spam-run.service --since "10 minutes ago"
rspamc stat

Automatic ham learning was not present as a dedicated grommunio ham-run timer in the installed appliance. Ham training therefore belongs in a controlled review process with validated samples, not in an invented timer recipe.

Result Validation / Technical Acceptance

Installation

Check
Check packages and components
Expected result
The component is fully installed
Status
PASS

Services

Check
Check systemd services
Expected result
The required services are active
Status
PASS

Network

Check
Check ports and URLs
Expected result
The component is reachable through the intended paths
Status
PASS

Core function

Check
Run standalone test
Expected result
The core function works before deeper integration
Status
PASS

Authentication

Check
Test SSO/login
Expected result
Login works through the intended path or is intentionally not required
Status
PASS or N/A

grommunio Web

Check
Check integration from Web
Expected result
The component is reachable or usable from grommunio Web
Status
PASS or N/A

End-to-end

Check
Test real user workflow
Expected result
The full workflow is reproducibly successful
Status
PASS

Restart

Check
Restart services
Expected result
The function remains available after service restart
Status
PASS

Logs

Check
Check relevant logs
Expected result
No blocking errors in the validated flow
Status
PASS