Scan and Learn Mail Safely with rspamc
Whether you are debugging a false positive or training the spam filter, rspamc is the command-line client that talks to Rspamd directly. This guide gets you a repeatable way to submit a message, inspect the result, check the controller, and make a deliberate learning request. The examples follow the installed rspamc 3.8.1 client from package rspamd 3.8.1-1ubuntu3.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a shell, the rspamc package, access to an Rspamd scanner or controller, and a test message saved as a file. Reading scan results is normally unprivileged. Learning, fuzzy-storage changes and other state-changing controller commands may need the controller password, depending on how it is configured. This guide does not use sudo, restart a service, or edit Rspamd configuration.
1. Confirm the client before sending mail
Start with read-only checks. They need no elevated privileges and pin down exactly which binary and command vocabulary you are using:
$ command -v rspamc
/usr/bin/rspamc
$ dpkg-query -W -f='${Package} ${Version}\n' rspamd
rspamd 3.8.1-1ubuntu3
$ rspamc --commands
Rspamc commands summary:
symbols (normal ) scan message and show symbols (default command)
stat (control ) show rspamd statistics
uptime (control ) show rspamd uptime
...
The real output runs longer than this excerpt. The installed client also reports that normal requests use port 11333 by default, and control requests use port 11334. A local package can expose more options than an older manpage describes, so lean on rspamc --help and the installed manpage whenever a detail matters.
Checkpoint
You have confirmed the executable and version. If command -v finds nothing, install or repair the package through your normal system administration process before continuing.
2. Scan one message and show its symbols
Save a message as MESSAGE.eml, then submit it with the default scan command. A regular file works, and so does a directory for a batch scan; with no input file, the command reads standard input instead.
$ rspamc symbols MESSAGE.eml
symbols is the default command, so this is equivalent:
$ rspamc MESSAGE.eml
Successful output is a Rspamd report with the message score, action and matched symbols. The exact symbols and scores depend on your configuration and the message. Check the exit status when scripting:
$ rspamc symbols MESSAGE.eml
$ status=$?
$ printf 'rspamc exit status: %s\n' "$status"
rspamc exit status: 0
Exit status 0 means the operation succeeded, nothing about the message itself. Treat the score and action as the verdict of this Rspamd configuration, not a universal judgement.
3. Choose an output format for scripts
Use --json when another program needs structured output, and --human when a person needs a compact report. These change the output format only, never the filtering policy.
$ rspamc --json symbols MESSAGE.eml
$ rspamc --human symbols MESSAGE.eml
The human report starts with the score and the greylist, add-header and reject thresholds, followed by action and status fields. Need the response exactly as received? The manpage documents --raw. Keep machine-readable output separate from explanatory text if something downstream is parsing it.
For a remote scanner, specify its host and port explicitly rather than assuming the local defaults:
$ rspamc --connect=SCAN_HOST:11333 --json symbols MESSAGE.eml
Replace SCAN_HOST with a host you administer. Never drop a real password or a message with private data into a public issue, terminal recording or diagnostic paste.
4. Check the controller without changing state
The controller handles statistics, uptime, learning and other control requests. Read-only checks are worth running before you attempt a learning operation:
$ rspamc uptime
$ rspamc stat
$ rspamc counters
Expected output is command-specific status or statistics, and it varies with traffic. A connection error usually means the controller is not listening on the selected address, a firewall blocks it, or the client is pointed at the wrong port. Adding sudo fixes none of those.
Checkpoint
Confirm uptime or stat reaches the intended controller. If it does not, stop here and fix the endpoint or service access before sending any learning requests.
5. Learn a confirmed spam or ham message
Learning changes Rspamd's state. Verify the message and its label before running this step, and make sure your operating procedure actually permits training. The default classifier is bayes; use --classifier only when your deployment has another one configured.
Do not put a real password directly in a command that lands in shell history. Read it without echoing, then hand it to the client for this one process:
$ read -r -s -p 'Rspamd control password: ' RSPAMD_PASSWORD
$ printf '\n'
$ rspamc --password="$RSPAMD_PASSWORD" learn_spam MESSAGE.eml
$ unset RSPAMD_PASSWORD
Use learn_ham for a confirmed non-spam message:
$ read -r -s -p 'Rspamd control password: ' RSPAMD_PASSWORD
$ printf '\n'
$ rspamc --password="$RSPAMD_PASSWORD" learn_ham MESSAGE.eml
$ unset RSPAMD_PASSWORD
The controller may use one password for both read-only and privileged operations, or separate ones; the server configuration decides that. A successful client exit is not an audit trail on its own, so record which message was deliberately labelled according to your local process.
Warning
Do not use learn_spam or learn_ham as a quick way to test connectivity with an uncertain message. It changes training data and can affect future classifications. Recovery is deployment-specific: correct a mistaken label with the corresponding learning command only if your Rspamd training policy supports that correction.
6. Handle fuzzy-storage commands carefully
fuzzy_add and fuzzy_del also need message input. Fuzzy operations use --flag to select a storage set and --weight for the operation. Confirm both values with whoever owns the fuzzy storage before you change anything.
$ rspamc --password="$RSPAMD_PASSWORD" --flag=2 --weight=10 fuzzy_add MESSAGE.eml
Deletion is harder to undo than a scan and can remove a genuinely useful fuzzy hash. The manpage's own example targets another controller explicitly:
$ rspamc --password="$RSPAMD_PASSWORD" --connect=CONTROLLER_HOST:11334 --flag=2 fuzzy_del MESSAGE.eml
Replace the placeholders only after checking the target, flag and message. There is no generic client-side undo here: delete the wrong hash and you recover through your fuzzy-storage backup or administrator procedure instead.
7. Diagnose the common traps
- No input file means standard input. A command such as
rspamc statneeds no message, but scan and learning commands do. If a command seems to hang, check whether it is waiting on the terminal. - --connect selects the server, not access.
--connect=HOST:PORTpicks the endpoint. It grants nothing on its own. - Verbosity and timeout are not the same thing.
--verboseadds client detail;--timeout=SECONDSchanges how long the client waits, but never makes a slow controller healthy. - Concurrency defaults to 8.
--max-requestscontrols parallel requests. Keep batch sizes and concurrency modest on a busy host. - Metadata flags can lie about delivery.
--ip,--fromand--rcptemulate message metadata. Use them only for a test that genuinely needs that context, because they can make a result differ from the message's real delivery path.
Done means
- Client confirmed. You checked the installed
rspamcbinary and package version. - A known message scanned cleanly. You checked the exit status, not just the printed report.
- Output format chosen deliberately. JSON or human, picked on purpose.
- Controller verified read-only. A read-only command reached the right endpoint before anything else ran.
- Learning treated as privileged. Learning and fuzzy changes were handled as state-changing operations, not casual tests.
- Nothing leaked or overclaimed. No control password exposed, and no non-zero score mistaken for a final verdict.