Integrating Roundcube "Mark as Junk" Plugin with SpamAssassin (Bayes) Train on DirectAdmin

This tutorial provides a complete, production-ready guide to integrating the Mark as Junk plugin in Roundcube Webmail with SpamAssassin (sa-learn) on a DirectAdmin server (compatible with DirectAdmin v1.677+ CustomBuild changes). Using sudoers permissions for the webapps user ensures that Bayes training updates the correct per-user SpamAssassin database securely.

Prerequisites: Root SSH access to your DirectAdmin server running CustomBuild and SpamAssassin.

Step 1: Create the Main Learning Script

Create the master script that receives the email payload from Roundcube and passes it to sa-learn under the specific DirectAdmin user context:

cat > /usr/local/bin/rc-sa-learn.sh << 'SCRIPT'
#!/bin/bash
TYPE="$1"
DOMAIN="$2"
MSGFILE="$3"

DAUSER=$(grep -i "^${DOMAIN}:" /etc/virtual/domainowners 2>/dev/null | awk -F': ' '{print $2}' | tr -d '[:space:]')

if [ -z "$DAUSER" ]; then
    echo "$(date): ERROR - could not resolve DA user for domain $DOMAIN" >> /var/log/rc-sa-learn.log
    exit 1
fi

BAYESPATH="/home/${DAUSER}/.spamassassin/bayes"

if [ "$TYPE" = "spam" ]; then
    sudo -u "$DAUSER" /usr/bin/sa-learn --spam --dbpath="$BAYESPATH" "$MSGFILE" >> /var/log/rc-sa-learn.log 2>&1
elif [ "$TYPE" = "ham" ]; then
    sudo -u "$DAUSER" /usr/bin/sa-learn --ham --dbpath="$BAYESPATH" "$MSGFILE" >> /var/log/rc-sa-learn.log 2>&1
fi

if [ $? -ne 0 ]; then
    echo "$(date): WARNING - sa-learn failed for user $DAUSER (missing sudoers entry? run /root/bootstrap-sa-learn-sudoers.sh)" >> /var/log/rc-sa-learn.log
fi
SCRIPT

chmod +x /usr/local/bin/rc-sa-learn.sh
touch /var/log/rc-sa-learn.log
chown webapps:webapps /var/log/rc-sa-learn.log
chmod 640 /var/log/rc-sa-learn.log

Step 2: Automate Sudoers Rules for New Users (DirectAdmin Hook)

Set up a DirectAdmin post-user-creation script to automatically grant the webapps user passwordless sudo permissions for running sa-learn under newly created accounts:

mkdir -p /usr/local/directadmin/scripts/custom

cat > /usr/local/directadmin/scripts/custom/user_create_post.sh << 'SCRIPT'
#!/bin/sh
DAUSER="${username}"

if [ -z "$DAUSER" ]; then
    exit 0
fi

SUDOFILE="/etc/sudoers.d/sa-learn-${DAUSER}"

if [ ! -f "$SUDOFILE" ]; then
    cat > "$SUDOFILE" << EOF
webapps ALL=(${DAUSER}) NOPASSWD: /usr/bin/sa-learn --spam --dbpath=/home/${DAUSER}/.spamassassin/bayes *
webapps ALL=(${DAUSER}) NOPASSWD: /usr/bin/sa-learn --ham --dbpath=/home/${DAUSER}/.spamassassin/bayes *
EOF
    chmod 440 "$SUDOFILE"
    visudo -cf "$SUDOFILE" >/dev/null 2>&1 || rm -f "$SUDOFILE"
fi

exit 0;
SCRIPT

chmod 700 /usr/local/directadmin/scripts/custom/user_create_post.sh
chown diradmin:diradmin /usr/local/directadmin/scripts/custom/user_create_post.sh

Step 3: Provision Sudoers Rules for Existing Users

Create and execute a bootstrap script to generate the appropriate sudoers entries for all existing DirectAdmin users:

cat > /root/bootstrap-sa-learn-sudoers.sh << 'SCRIPT'
#!/bin/bash
while IFS=': ' read -r DOMAIN DAUSER; do
    DAUSER=$(echo "$DAUSER" | tr -d '[:space:]')
    [ -z "$DAUSER" ] && continue
    SUDOFILE="/etc/sudoers.d/sa-learn-${DAUSER}"
    if [ ! -f "$SUDOFILE" ]; then
        cat > "$SUDOFILE" << EOF
webapps ALL=(${DAUSER}) NOPASSWD: /usr/bin/sa-learn --spam --dbpath=/home/${DAUSER}/.spamassassin/bayes *
webapps ALL=(${DAUSER}) NOPASSWD: /usr/bin/sa-learn --ham --dbpath=/home/${DAUSER}/.spamassassin/bayes *
EOF
        chmod 440 "$SUDOFILE"
        visudo -cf "$SUDOFILE" >/dev/null 2>&1 && echo "Provisioned: $DAUSER" || { rm -f "$SUDOFILE"; echo "FAILED (invalid): $DAUSER"; }
    fi
done < /etc/virtual/domainowners
SCRIPT

chmod +x /root/bootstrap-sa-learn-sudoers.sh
/root/bootstrap-sa-learn-sudoers.sh

Verify that the rules were created successfully:

ls /etc/sudoers.d/ | grep sa-learn

Step 4: CustomBuild Roundcube Customization Setup (DA 1.677+)

Copy configuration files from the new CustomBuild exposed directory (./configure/roundcube/) to the custom overrides directory (./custom/roundcube/):

# Create custom directories
mkdir -p /usr/local/directadmin/custombuild/custom/roundcube/plugins

# Copy default config file template
cp /usr/local/directadmin/custombuild/configure/roundcube/config.inc.php /usr/local/directadmin/custombuild/custom/roundcube/config.inc.php

# Enable markasjunk in active plugins list
RCPLUGINCONFIG="/usr/local/directadmin/custombuild/custom/roundcube/config.inc.php"


if ! grep -qE "['\"]markasjunk['\"]" "$RCPLUGINCONFIG"; then
  sed -i -E "s|(\\\$config\['plugins'\]\s*=\s*\[[^]]*)\]|\1, 'markasjunk']|" "$RCPLUGINCONFIG"
fi


grep -E "plugins" "$RCPLUGINCONFIG"

# Copy markasjunk plugin configuration to custom directory
mkdir -p /usr/local/directadmin/custombuild/custom/roundcube/plugins/markasjunk
cp /usr/local/directadmin/custombuild/configure/roundcube/plugins/markasjunk/config.inc.php.dist \
   /usr/local/directadmin/custombuild/custom/roundcube/plugins/markasjunk/config.inc.php

# Configure markasjunk plugin driver and commands
sed -i \
  -e "s|\$config\['markasjunk_learning_driver'\] = null;|\$config['markasjunk_learning_driver'] = 'cmd_learn';|" \
  -e "s|\$config\['markasjunk_spam_cmd'\] = null;|\$config['markasjunk_spam_cmd'] = '/usr/local/bin/rc-sa-learn.sh spam %d %f';|" \
  -e "s|\$config\['markasjunk_ham_cmd'\] = null;|\$config['markasjunk_ham_cmd'] = '/usr/local/bin/rc-sa-learn.sh ham %d %f';|" \
  -e "s|\$config\['markasjunk_debug'\] = false;|\$config['markasjunk_debug'] = true;|" \
  /usr/local/directadmin/custombuild/custom/roundcube/plugins/markasjunk/config.inc.php

Confirm the plugin configuration parameters:

grep -E "learning_driver|spam_cmd|ham_cmd|debug" /usr/local/directadmin/custombuild/custom/roundcube/plugins/markasjunk/config.inc.php

Step 5: Rebuild Roundcube and Restart Services

Rebuild Roundcube using CustomBuild to apply all custom options:

cd /usr/local/directadmin/custombuild
./build roundcube

systemctl restart spamd
da build exim_conf

Step 6: Verification and Logs

  1. Log into Roundcube Webmail interface.
  2. Select an email and click Mark as Junk (or As Not Junk).
  3. Check the log output to confirm successful processing:
    tail -20 /var/log/rc-sa-learn.log

Maintenance: Future Upgrade Workflow

When upgrading Roundcube via CustomBuild in DirectAdmin 1.677+, compare your custom options against the default options exposed in configure/roundcube:

# Check main configuration differences
diff /usr/local/directadmin/custombuild/custom/roundcube/config.inc.php /usr/local/directadmin/custombuild/configure/roundcube/config.inc.php

# Check plugin configuration differences
diff /usr/local/directadmin/custombuild/custom/roundcube/plugins/markasjunk/config.inc.php /usr/local/directadmin/custombuild/configure/roundcube/plugins/markasjunk/config.inc.php.dist

If new configuration options appear in the default files after an update, copy and adjust them within your custom/roundcube files.

  • 1 Users Found This Useful
Was this answer helpful?

Related Articles

How to Configure DirectAdmin Spam Protection

Configuring proper server-wide spam protection is essential for maintaining server reputation,...