[TUTORIAL] Integrate rspamd as custom script

Tutorial: Integrating Rspamd as a Custom Script in Proxmox Mail Gateway


Proxmox Mail Gateway allows advanced customization with a custom script for spam and virus checks. This tutorial will show you how to integrate Rspamd to evaluate spam scores and return results back to PMG.


1. Requirements

  • A running cluster of rspamd
    It can be on the same host as PMG or a remote server, however I suggest a remote server.
    I will just present a very simple single node installation.
  • PMG properly installed and configured.
  • Basic knowledge of shell scripting.



2. Enable the Custom Script in PMG

  1. Open the PMG configuration file:

    nano /etc/pmg/pmg.conf

  2. Enable the custom check script by adding or updating the following section:

    section: admin
    custom_check 1
    custom_check_path /usr/local/bin/pmg-custom-check
  3. Install jq - because the script needs it

    apt install jq



3. Install and Configure Rspamd

Install Rspamd:​


On the same server (or another server):

apt update && apt install rspamd

Enable HTTP API in Rspamd:​


Edit the Rspamd controller worker configuration file:

nano /etc/rspamd/rspamd.conf and update the following section so that the controller is available on remote.
On local setup, you can ignore this step. However, the script uses a password.
Code:
worker "controller" {
    bind_socket = "0.0.0.0:11334";
    bind_socket = "[::]:11334";
    password="use-a-strong-password";
    enable_password = true;
    .include "$CONFDIR/worker-controller.inc"
    .include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/worker-controller.inc"
    .include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/worker-controller.inc"
}


Restart Rspamd:

systemctl restart rspamd



4. Create the Custom Script

  1. Create the script file:
    nano /usr/local/bin/pmg-custom-check
  2. Add the following script to integrate with Rspamd:

Code:
#!/bin/bash

API_URL="http://<your rspamd host>:11334/checkv2"
API_PASSWORD="your-strong-password"

if [ "$#" -ne 2 ]; then
  echo "usage: $0 APIVERSION QUEUEFILENAME" 1>&2
  exit 1
fi

apiver="$1"
queue_file="$2"

if [ "$apiver" != "v1" ]; then
  echo "wrong APIVERSION: $apiver" 1>&2
  exit 2
fi

# Call rspamd via HTTP API
rspamd_output=$(curl -s --data-binary @"$queue_file" -H "Password: $API_PASSWORD" "$API_URL")
if [ $? -ne 0 ]; then
  echo "Error contacting rspamd" 1>&2
  exit 3
fi

# Extract spam score from JSON response
spam_score=$(echo "$rspamd_output" | jq -r '.score')

# Validate spam score
if [[ ! $spam_score =~ ^-?[0-9]+(\.[0-9]+)?$ ]]; then
  echo "Error parsing rspamd output" 1>&2
  exit 4
fi

# Output for PMG
echo "v1"
if (( $(echo "$spam_score > 0" | bc -l) )); then
  echo "SCORE: $spam_score"
else
  echo "OK"
fi

  1. Save and make the script executable:
    chmod +x /usr/local/bin/pmg-custom-check



5. Testing the Custom Script

Prepare a Test Email File​


Create a sample email file (email.eml) in RFC 822 format:

Code:
From: test@example.com
To: recipient@example.com
Subject: Test Email

This is a test email for Rspamd integration.

Run the Script Manually​


Test the custom script with the email file:

/usr/local/bin/pmg-custom-check v1 email.eml

Expected Output:
  • If spam score > 0:
    v1
    SCORE: 1.1
  • If spam score <= 0:
    v1
    OK


6. Fine-Tuning Rspamd Configuration

Disable Greylisting (Optional)​


If greylisting is not needed, disable it in /etc/rspamd/local.d/greylist.conf:

enabled = false;

Restart Rspamd:
systemctl restart rspamd

Conclusion​


With this setup, Proxmox Mail Gateway is now integrated with Rspamd for custom spam checking. Rspamd will evaluate emails, assign spam scores, and return results to PMG. Fine-tune Rspamd settings to match your environment, and monitor logs to ensure smooth operation.

I suggest also using a reverse http proxy to upgrade to https if your cluster does not have a secure local network.
Notice: Spam scores are added to the scores calculated by proxmox. Please ensure your filtering can keep up with these added values :)

Let me know if you encounter issues or need further guidance!
 
Last edited:
Thanks for your tutorial.
How would PMG treat two spam scores?
AIUI the custom filter is run before spamassassin. If SA remains enabled, is it an aggregate or is the rspamd score superseded by the SA one?
 
Thanks for the tutorial. i already got better scores for spammy messages.
Many spammy messages used to blow through bare PMG. (coming from spam sources with valid SPF, DKIM and DMARC..., not from a ROKSO, , valid DNS setup just being the average spam for furniture etc. obviously using several source mail addresses related but different / per message etc. )
But when forwarded to a gmail account get blocked as spam...
 
Hello,

I would allow negative output as well (supported since patch in summer), this allows more push to ham in case of LLM with gpt module.

Thanks a lot for the rspam integration.

I run Rspamd with GPT included with local Ollama LLM model (llama3.1) to check emails for spam with surprising good results. It is very promising because I had a bunch of AI generated spam which is filtered out correctly due to this custom integration.

Code:
# Output for PMG
echo "v1"
if (( $(echo "$spam_score < -25" | bc -l) )) || (( $(echo "$spam_score > 25" | bc -l) )); then
       echo "OK"
else
       formatted_score=$(printf "%.1f" "$spam_score")
       echo "SCORE: $formatted_score"
fi
 
Last edited:
Looking back in statistics, i see Until i activated and integrated rspamd, ALL spam scores were in effect 0. (according to statistics).
(which explains the pass through of almost anything).
Also explains the rspamd effectivly be the only one working so there is No double score. (In case there would be a double score the raising the threshholds should suffice, i had no need to do that.).
 
more modules, better training, only solution with chatGPT spam identification. My spam identification success rate improved a lot wit rspamd.
 
  • Like
Reactions: hoanv9
How is your usage of rspamd?
I have noticed an increasing number of spams, and the spamassassin rules are not filtering well, while rspam has interesting modules to test