Hello everyone,
If you're running Rspamd with DirectAdmin, you have a powerful anti-spam engine. However, the default setup often lacks a critical feature: automatic learning. Without it, Rspamd can't learn from your users' actions (like moving an email to Junk), and its accuracy won't improve over time.
This guide will walk you through the complete, step-by-step process of enabling Rspamd's learning feature with Dovecot using the more modern and powerful Dovecot Sieve method. This is the secure, robust, and professional way, with no insecure file permissions and no sudo.
Prerequisites:
## Step 1: Configure Dovecot for Sieve Actions
First, we'll tell Dovecot to enable the necessary Sieve plugins and define the actions that will trigger our learning scripts.
1. Enable Sieve in LMTP Protocol:
The lmtp protocol needs to know about the Sieve plugin. We'll create a dedicated file to ensure this setting is applied.
Check if lmtp is enable at:
If you see something like this, skip next step:
Paste the following into this new file (SKIP this if you have the file above):
2. Configure IMAP Sieve Actions:
This is the core of the configuration. We will create a new file to control what happens when a user moves an email.
Create and edit the file /etc/dovecot/conf.d/99-imap-sieve.conf:
Paste the entire configuration below. This enables the required plugins and tells Dovecot to run specific Sieve scripts when a message is moved to or from the Junk or spam folders.
## Step 2: Create the Sieve and Shell Scripts
Now we'll create the actual scripts that Dovecot will execute.
1. Create the directory:
2. Create the report-spam.sieve script:
This script pipes the email to our shell script to learn as "spam".
Paste this in:
3. Create the report-ham.sieve script:
Paste this in:
4. Create the rspamd-learn.sh shell script:
This is the script that does the actual work of talking to Rspamd.
Paste this in:
5. Set final permissions:
Make the shell script executable and compile the Sieve scripts.
## Step 3: Configure Rspamd for Secure Socket Access
This is the key to a secure, sudo-less setup. We will configure Rspamd's socket so Dovecot can access it directly via group permissions.
1. Allow Rspamd to Manage Group Permissions:
The Rspamd process (_rspamd user) needs permission to assign the socket file to the dovecot group. We grant this by adding the _rspamd user to that group.
2. Create the Rspamd Controller Override File:
This file will force our secure configuration to be loaded.
Paste the following secure configuration:
## Step 4: Final Restart and Verification
Let's apply everything and confirm it's working.
1. Check Dovecot configuration for syntax errors:
(If it returns your configuration without errors, you're good).
2. Restart both services:
3. Verify the socket permissions. Run this command:
The output should show _rspamd as the owner and dovecot as the group:
4. Test it!
##
Troubleshooting
Problem: Emails Are Not Being Delivered After Setup (Stuck in Queue)
After following the guide, you might encounter a situation where new emails are successfully processed by Rspamd but never appear in the user's inbox. This happens when there is a miscommunication between Exim (the mail carrier) and Dovecot (the mailbox).
Symptoms:
Explanation of the Cause:
This error means a "broken contract" between Exim and Dovecot. Exim is trying to deliver the email, but Dovecot's delivery service (LMTP) is either not running or is misconfigured and immediately closing the connection. This often happens because our new Sieve configuration can unintentionally disable or conflict with the default LMTP service settings.
The solution is a two-part process:
Part A: Ensure Dovecot is running its LMTP service correctly using a modern and reliable UNIX socket.
Part B: Ensure Exim knows the correct address of this new socket.
The Solution:
1. Fix the Dovecot Side (The Mailbox):
First, we need to ensure Dovecot's LMTP service is running and listening on a socket.
You can verify the socket was created with: ls -l /var/run/dovecot/lmtp
2. Fix the Exim Side (The Mail Carrier):
Now we must update Exim's "GPS" to deliver to the new socket address. The safest and most reliable way to do this in DirectAdmin is to let CustomBuild rewrite the configuration.
Run the following commands:
This command will automatically detect that Dovecot is using a socket and will generate a new /etc/exim.conf with the correct transport settings, changing the delivery method from the old dovecot_lmtp_udp to the new dovecot_lmtp (via socket).
3. Verify the Fix and Clear the Queue:
Exim will have been restarted by the build script. Now, force it to re-process all the stuck emails in its queue, ignoring the old retry timers:
Watch the queue count drop to zero:
You can also watch the Exim log (tail -f /var/log/exim/mainlog) to see a flood of successful deliveries ending with T=dovecot_lmtp completed.
Your email delivery will now be fully functional.
If something isn't working, these commands are your best friends:
If you're running Rspamd with DirectAdmin, you have a powerful anti-spam engine. However, the default setup often lacks a critical feature: automatic learning. Without it, Rspamd can't learn from your users' actions (like moving an email to Junk), and its accuracy won't improve over time.
This guide will walk you through the complete, step-by-step process of enabling Rspamd's learning feature with Dovecot using the more modern and powerful Dovecot Sieve method. This is the secure, robust, and professional way, with no insecure file permissions and no sudo.
Prerequisites:
- A DirectAdmin server with Rspamd and Dovecot (version 2.4+ recommended) installed.
- Pigeonhole Sieve is enabled by default in recent DirectAdmin versions. This guide assumes it is active.
- Pigeonhole Sieve enabled in CustomBuild. If you're not sure, run this:
Code:da config-set pigeonhole yes
Code:da build dovecot_conf
## Step 1: Configure Dovecot for Sieve Actions
First, we'll tell Dovecot to enable the necessary Sieve plugins and define the actions that will trigger our learning scripts.
1. Enable Sieve in LMTP Protocol:
The lmtp protocol needs to know about the Sieve plugin. We'll create a dedicated file to ensure this setting is applied.
Check if lmtp is enable at:
Code:
cat /etc/dovecot/conf/lmtp.conf
Code:
#add sieve to end of line in:
#/etc/dovecot/conf/lmtp_mail_plugins.conf
#mail_plugins = $mail_plugins sieve
# LMTP socket for local delivery from exim
service lmtp {
executable = lmtp -L
process_min_avail = 16
unix_listener lmtp {
user = mail
group = mail
mode = 0660
}
}
lmtp_rcpt_check_quota = yes
protocol lmtp {
!include lmtp_mail_plugins.conf
log_path = /var/log/dovecot-lmtp-errors.log
info_log_path = /var/log/dovecot-lmtp.log
quota_full_tempfail = no
}
Code:
nano /etc/dovecot/conf.d/20-lmtp-sieve.conf
Code:
protocol lmtp {
mail_plugins = $mail_plugins sieve
}
2. Configure IMAP Sieve Actions:
This is the core of the configuration. We will create a new file to control what happens when a user moves an email.
Create and edit the file /etc/dovecot/conf.d/99-imap-sieve.conf:
Code:
nano /etc/dovecot/conf.d/99-imap-sieve.conf
Code:
# Enable the IMAP Sieve plugin
protocol imap {
mail_plugins = $mail_plugins imap_sieve
}
#Enable required Sieve extensions
sieve_plugins {
sieve_imapsieve = yes
sieve_extprograms = yes
}
sieve_global_extensions {
vnd.dovecot.pipe = yes
}
#Set the directory for our learning scripts
sieve_pipe_bin_dir = /usr/local/bin/dovecot-sieve
# --- Main Logic: Define actions for specific mailboxes ---
namespace inbox {
# ACTION: When a message is MOVED TO these folders, learn it as SPAM.
# The "auto = create" will create these folders for new users if they don't exist.
mailbox "Junk" {
auto = create
sieve_script = report-spam
}
mailbox "spam" {
auto = create
sieve_script = report-spam
}
# ACTION: When a message is MOVED FROM these folders, learn it as HAM.
imapsieve_from1 = Junk
imapsieve_from2 = spam
}
# --- Script Definitions ---
# This links the script names above to the actual script files on disk.
plugin {
sieve_script_name = report-spam
sieve_script_path = /usr/local/bin/dovecot-sieve/report-spam.sieve
sieve_script_is_active = yes
sieve_script_name = report-ham
sieve_script_path = /usr/local/bin/dovecot-sieve/report-ham.sieve
sieve_script_is_active = yes
}
Pro Tip: Your users might use different folder names (e.g., Lixo, Spam). You can find the exact folder names for a user with the command: doveadm mailbox list -u [email protected]
## Step 2: Create the Sieve and Shell Scripts
Now we'll create the actual scripts that Dovecot will execute.
1. Create the directory:
Code:
mkdir -p /usr/local/bin/dovecot-sieve
2. Create the report-spam.sieve script:
This script pipes the email to our shell script to learn as "spam".
Code:
nano /usr/local/bin/dovecot-sieve/report-spam.sieve
Code:
require ["vnd.dovecot.pipe"];
pipe "rspamd-learn.sh" [ "spam" ];
3. Create the report-ham.sieve script:
Code:
nano /usr/local/bin/dovecot-sieve/report-ham.sieve
Code:
require ["vnd.dovecot.pipe", "copy", "environment", "imapsieve"];
if environment :matches "imap.mailbox" "Spam" {
stop;
}
if environment :matches "imap.mailbox" "Trash" {
stop;
}
pipe :copy "rspamd-learn.sh" [ "ham" ];
4. Create the rspamd-learn.sh shell script:
This is the script that does the actual work of talking to Rspamd.
Code:
nano /usr/local/bin/dovecot-sieve/rspamd-learn.sh
Code:
#!/bin/bash
# A simple, secure learning script without sudo
SOCKET_PATH="/var/run/rspamd/rspamd_controller.sock"
ACTION="$1"
if [ "$ACTION" = "spam" ]; then
# Execute rspamc directly as the email user
cat | /usr/bin/rspamc -h "$SOCKET_PATH" learn_spam >/dev/null 2>&1
elif [ "$ACTION" = "ham" ]; then
cat | /usr/bin/rspamc -h "$SOCKET_PATH" learn_ham >/dev/null 2>&1
fi
5. Set final permissions:
Make the shell script executable and compile the Sieve scripts.
Code:
chmod +x /usr/local/bin/dovecot-sieve/rspamd-learn.sh
sievec /usr/local/bin/dovecot-sieve/report-spam.sieve
sievec /usr/local/bin/dovecot-sieve/report-ham.sieve
## Step 3: Configure Rspamd for Secure Socket Access

This is the key to a secure, sudo-less setup. We will configure Rspamd's socket so Dovecot can access it directly via group permissions.
1. Allow Rspamd to Manage Group Permissions:
The Rspamd process (_rspamd user) needs permission to assign the socket file to the dovecot group. We grant this by adding the _rspamd user to that group.
Code:
usermod -a -G dovecot _rspamd
2. Create the Rspamd Controller Override File:
This file will force our secure configuration to be loaded.
Code:
nano /etc/rspamd/override.d/worker-controller.inc
Code:
# /etc/rspamd/override.d/worker-controller.inc
#Secure configuration for Dovecot integration without sudo.
#owner=_rspamd: The user who owns the socket.
#group=dovecot: The group who owns the socket.
#mode=0660: Allows read/write for the owner AND the group, but NO ONE else.
bind_socket = "/var/run/rspamd/rspamd_controller.sock owner=_rspamd group=dovecot mode=0660";
#Explicitly enable the learn commands on this socket.
allow_learn = true;
## Step 4: Final Restart and Verification

Let's apply everything and confirm it's working.
1. Check Dovecot configuration for syntax errors:
Code:
doveconf -N
2. Restart both services:
Code:
systemctl restart rspamd
systemctl restart dovecot
3. Verify the socket permissions. Run this command:
Code:
ls -l /var/run/rspamd/rspamd_controller.sock
Code:
srw-rw---- 1 _rspamd dovecot 0 Oct 12 01:10 /var/run/rspamd/rspamd_controller.sock
4. Test it!
- Log in to Roundcube webmail.
- Drag a spam email from your Inbox to your Junk/Spam folder.
- Open the Rspamd web UI in DirectAdmin and check the Learns count for BAYES_SPAM. It should increase!
- Drag the email back to your Inbox. The Learns count for BAYES_HAM should now increase.
##

Problem: Emails Are Not Being Delivered After Setup (Stuck in Queue)
After following the guide, you might encounter a situation where new emails are successfully processed by Rspamd but never appear in the user's inbox. This happens when there is a miscommunication between Exim (the mail carrier) and Dovecot (the mailbox).
Symptoms:
- You check the Exim queue and see a large number of emails stuck:
Code:da exim -bpc
- You check the Exim main log and find this specific error:
Code:tail -f /var/log/exim/mainlog
Code:T=dovecot_lmtp_udp defer (-1): LMTP connection closed after initial connection
Explanation of the Cause:
This error means a "broken contract" between Exim and Dovecot. Exim is trying to deliver the email, but Dovecot's delivery service (LMTP) is either not running or is misconfigured and immediately closing the connection. This often happens because our new Sieve configuration can unintentionally disable or conflict with the default LMTP service settings.
The solution is a two-part process:
Part A: Ensure Dovecot is running its LMTP service correctly using a modern and reliable UNIX socket.
Part B: Ensure Exim knows the correct address of this new socket.
The Solution:
1. Fix the Dovecot Side (The Mailbox):
First, we need to ensure Dovecot's LMTP service is running and listening on a socket.
You can verify the socket was created with: ls -l /var/run/dovecot/lmtp
2. Fix the Exim Side (The Mail Carrier):
Now we must update Exim's "GPS" to deliver to the new socket address. The safest and most reliable way to do this in DirectAdmin is to let CustomBuild rewrite the configuration.
Run the following commands:
Code:
da build update
da build exim_conf
3. Verify the Fix and Clear the Queue:
Exim will have been restarted by the build script. Now, force it to re-process all the stuck emails in its queue, ignoring the old retry timers:
Code:
da exim -qff
Code:
da exim -bpc
Your email delivery will now be fully functional.
If something isn't working, these commands are your best friends:
- Check Dovecot logs for Sieve errors: journalctl -u dovecot --since "1 minute ago" | grep -i sieve
- Watch Dovecot logs in real-time: journalctl -u dovecot -f
- Watch Rspamd logs: journalctl -u rspamd -f
Last edited: