Filtering out spam with rspamd

You have a perfectly working mail server by now. But before you go live let’s do something about the insane amount of spam. In previous editions of this guide I used and recommended SpamAssassin. However I have found a piece of software that is more versatile, scales better and is still easy to integrate: rspamd. rspamd has a (maybe biased) comparison on their home page.

rspamd is a permanent process that runs on your mail server. It listens to connections from Postfix using the milter (=mail filter) protocol. Every time an email enters ryour system, Postfix will send it to rspamd to have its content checked. rspamd runs a lot of checks on the email and computes a total score. The higher the score – the more likely the email should be considered unsolicited.

Make Postfix use rspamd

Let’s tell Postfix to send all incoming email through rspamd. Run these commands on the shell:

postconf smtpd_milters=inet:127.0.0.1:11332
postconf non_smtpd_milters=inet:127.0.0.1:11332
postconf milter_protocol=6
postconf milter_mail_macros="i {mail_addr} {client_addr} {client_name} {auth_authen}"

Postfix will now connect to rspamd that is listening to TCP port 11332 on localhost (127.0.0.1) and pass the email over that connection. The smtpd_milters setting defines that connection for emails that came into the system from the internet via the SMTP protocol. The non_smtpd_milters setting is optional – it makes Postfix have all emails checked that originate from the system itself. Finally the milter_mail_macros setting defines several variables that rspamd expects for better spam detection. rspamd then runs its checks and tells Postfix whether the email should pass or get rejected.

Testing spam detection

For testing we can use a sample spam email that comes with SpamAssassin. It is called GTUBE (Generic Test for Unsolicited Bulk Email). It contains a certain articial pattern that is recognized as spam by SpamAssassin. Do you know EICAR.COM to test virus scanners? This is the same thing for spam.

I suggest that you download the file on the server:

wget http://spamassassin.apache.org/gtube/gtube.txt

…and send that email to our test user John…

sendmail john@example.org < gtube.txt

Check your /var/log/mail.log. You will find something like this:

Jan 13 09:21:01 mail postfix/cleanup[19945]: 95B7A42212: milter-reject: END-OF-MESSAGE from localhost[127.0.0.1]: 5.7.1 Gtube pattern; from=<root@mail.example.org> to=<john@example.org>
Jan 13 09:21:01 jen postfix/cleanup[19945]: 95B7A42212: to=<john@example.org>, relay=none, delay=0.18, delays=0.18/0/0/0, dsn=5.7.1, status=bounced (Gtube pattern)

The interesting parts are those printed in bold letters. “milter-reject” tells that the milter (rspamd) recommended to Postfix to reject the email. It gave the reason “5.7.1 Gtube pattern”. In mail communication you often find these three digit codes. They are defined in RFC 3463. The first digit is most important:

  • 2 = Success
  • 4 = Transient failure (temporary problem – come back later)
  • 5 = Permanent failure (do not try again in this way)

So 5.7.1 tells us that the result code is a permanent failure in delivery. If you looked up the RFC you would find that the 7 stands for an issue regarding the security policy. So it’s not a technical failure but instead a security-relevant component on the system has rejected the email. That’s what rspamd did. It even told us the reason: “Gtube pattern”. So you see that rspamd knows about the Gtube spam test pattern and reacts as expected.

Accordingly you won’t see this email in John’s inbox. This is a great advantage of using milters by the way. Imagine Postfix receiving a spam email and confirming its reception. What should it do when it finds out that it’s unwanted email? According to the SMTP protocol it must not throw away any emails. Would you create a bounce message telling the sender that you did not accept the email? That would be a bad idea because the pretended sender address is very likely not the real sender. You would send the bounce to an innocent person thus creating so called backscatter and make it even worse. So the right approach is to check the email while the sending server is still connected to your Postfix. This allows Postfix to reject the email with a 5.x.x error code and let the other side figure out what to do.

Score metrics (optional)

rspamd will however not reject all spam email. As it computes a score of the spam propability you can tell it which scores you would accept, flag as spam or make the incoming email get rejected. Take a look at the /etc/rspamd/metrics.conf file. There are tons of scores defined for various conditions. At the beginning of the file you will find:

 actions {
 reject = 15;
 add_header = 6;
 greylist = 4;
 }

These are the default actions. If rspamd computes a score of at least 15 then the email will get rejected just like the Gtube pattern in the previous test. Any score above 6 will add header lines like “X-Spam: Yes” so that your mail software can detect them and maybe file the email to a different folder. Any score above 4 will trigger greylisting which is a mechanism that temporarily rejects the email with a 4.x.x code and waits if the sending server will try again. After a waiting time of a few minutes greylisting will accept the email. The idea is to reject email from systems that do not have a sending queue. Malware like on infected Wind*ws computers used to try sending an email just once which triggered greylisting and successfully rejected the spammer. But even malware programmers have learned and may try again after a few minutes thus circumventing greylisting. Your mileage may vary.

If you like to change these defaults then create a new file in /etc/rspamd/override.d/metrics.conf contaning:

actions {
 reject = 150;
 add_header = 2;
 greylist = 5;
}

This would virtually never reject an email. And it would flag any email with a score of at least 2 as spam. Greylisting would happen at a score above 5. These are not necessarily sane values – they are just meant as an example.

Please take a moment to understand how to change rspamd defaults. You can either create files in /etc/rspamd/local.d/… which will replace entire sections; or create files in /etc/rspamd/override.d/… which will change only small parts of the configuration. There is a helpful page in the rspamd documentation that contains examples. Whatever you do – never change the /etc/rspamd/* files directly because a software update will try to replace them.

Of course restart rspamd after any configuration changes:

service rspamd reload

To check if rspamd has picked up your configuration use this command to see the current configuration:

rspamadm configdump

You may test your configuration using

rspamadm configtest

Alternatively you may check if all required rspamd processes are running…

pgrep -a rspam

22510 rspamd: main process 
22511 rspamd: rspamd_proxy process 
22512 rspamd: controller process 
22513 rspamd: normal process 
22514 rspamd: normal process 
22515 rspamd: hs_helper process

Adding headers

As you may know an email contains of the header and the body. Your users will only see header information like the subject, the sender, the recipient and the date and time the email was sent. But there is way more information like the router the email travelled or extended headers added by the various mail server on the way to the destination. Such extended headers begin with an “X-“. rspamd can add such headers to help you filter out spam. For that purpose create a new configuration override file at /etc/rspamd/override.d/milter_headers.conf with this content:

extended_spam_headers = true;

As documented it will add these headers:

X-Rspamd-Server: mail
Authentication-Results: dmarc=fail reason="No valid SPF, No valid DKIM" …
X-Rspamd-Queue-Id: C22E55A005B3
X-Spamd-Result: default: False [11.55 / 15.00]
 R_PARTS_DIFFER(0.27)[63.4%]
 FROM_NO_DN(0.00)[]
 RCVD_COUNT_ZERO(0.00)[0]
 R_DKIM_NA(0.00)[]
 FUZZY_DENIED(12.00)[1:19305c7fdd:1.00:bin,1:35699594fd:0.91:txt]
 RBL_SENDERSCORE(2.00)[55.181.23.94.bl.score.senderscore.com]
 ARC_NA(0.00)[]
 RCPT_COUNT_ONE(0.00)[1]
 RCVD_TLS_ALL(0.00)[]
 FROM_EQ_ENVFROM(0.00)[]
 R_SPF_SOFTFAIL(0.00)[~all]
 BAYES_HAM(-2.71)[98.75%]
 TO_MATCH_ENVRCPT_ALL(0.00)[]
 MIME_GOOD(-0.10)[multipart/related,multipart/alternative,text/plain]
 MID_RHS_MATCH_FROM(0.00)[]
 ASN(0.00)[asn:16276, ipnet:94.23.0.0/16, country:FR]
 TO_DN_NONE(0.00)[]
 DMARC_POLICY_SOFTFAIL(0.10)[Chronopost.fr : No valid SPF, No valid DKIM,none]
 SUBJECT_ENDS_EXCLAIM(0.00)[]
X-Spam: Yes

Each of the uppercase symbols like FROM_HAS_DN means that a certain detection routing of rspamd was triggered. It does not necessarily mean something bad about the email. For example R_SPF_ALLOW has a negative score that lowers the total score because it is something good about the email. There are a several symbols with a 0.00 score. These do not change the score but show you what rspamd has found. But if you consider certain criteria good or bad then you can define your own scores for them.

The last line here is especially interesting because next on our list is…

Sending spam to the Junk folder

Your users will not realize that their spam emails have an added “X-Spam: Yes” header. Their emails just appear like normal in their inbox. So let’s aid them by moving spam to a seperate Junk folder beneath their inbox automatically. Dovecot has support for Sieve filters which are basically scripts that run automatically whenever an email coming in.

John could log into Roundcube and configure a new Sieve filter for himself that would save any emails to his “Junk” folder if the header line “X-Spam: Yes” was found. This rule would be useful for all your users though so let’s find a general solution.

Note: SpamAssassin as used in previous versions of this guide used a slightly different header. “X-Spam-Flag: YES”. Make sure to change your Sieve filters accordingly.

Dovecot supports global Sieve filters that apply to all users. Edit the file /etc/dovecot/conf.d/90-sieve.conf. Look for the “sieve_after” lines. They are commented out. So add a new line there:

sieve_after = /etc/dovecot/sieve-after

The “sieve after” filters are executed after the user’s filters. John can define his own filter rules. And after that Dovecot will run any filter rules it finds in files in /etc/dovecot/sieve-after. Create that directory:

mkdir /etc/dovecot/sieve-after

And create a new file /etc/dovecot/sieve-after/spam-to-folder.sieve reading:

require ["fileinto","mailbox"];

if header :contains "X-Spam" "Yes" {
 fileinto :create "INBOX.Junk";
 stop;
}

The “require” lines include functionality to move emails into certain folders (fileinto) and to create folders if they don’t exist yet (mailbox). Then if SpamAssassin marked a header as spam it is moved into the INBOX.Junk folder which just appears as “Junk” to the user underneath their inbox.

Dovecot cannot deal with such human-readable files though. So we need to compile it:

sievec /etc/dovecot/sieve-after/spam-to-folder.sieve

That generated a machine-readable file /etc/dovecot/sieve-after/spam-to-folder.svbin.

Restart Dovecot:

service dovecot restart

Now all your users will automatically get spam emails moved to their Junk folder. Nice – isn’t it?

Learning existing spam

If you followed previous ISPmail guides then you will have used SpamAssassin for a while. You may have trained it with ham (good) and spam (unwanted) emails for a while which fueled the built-in Bayes database to increase its detection reliability. The bad news is that you cannot use that training data in rspamd because it uses a different algorithm. There are three ways to get started with rspamd…

(a) No Bayes training

This is not as bad as it sounds. rspamd has way more functionality to determine if an email is ham or spam. I recommend that you enable auto learning. Just create a new file /etc/rspamd/override.d/classifier-bayes.conf and make it contain:

autolearn = true;

This is a very conservative approach though. It learns emails as spam if they are so bad that they get rejected. And it learns emails as ham if they have a negative (=very good) score. The rspamd documentation has further examples how to fine-tune auto learning.

(b) Using pre-built statistics

rspamd provides a sample database with over 3000 learned emails. They are from 2015 and perhaps are not a good start because the nature of spam changes over time.

Stop rspamd:

service rspamd stop

Take their pre-built statistics and put the *sqlite files into your /var/lib/rspamd directory. Fix the ownership of those files by running…

chown _rspamd._rspamd /var/lib/rspamd/*sqlite

And finally start rspamd again…

service rspamd start

Verify that the database is now filled by running…

rspamc stat

At the end of the output you will see something like…

Statfile: BAYES_SPAM type: sqlite3; length: 41.78M; free blocks: 0; total blocks: 596k; free: 0.00%; learned: 1880; users: 1; languages: 3
Statfile: BAYES_HAM type: sqlite3; length: 51.12M; free blocks: 0; total blocks: 684k; free: 0.00%; learned: 1578; users: 1; languages: 3
Total learns: 3458

(c) Re-learn your existing ham and spam

You have been running your mail server for a while? And you have a good amount of ham and spam emails? Then let’s use those to train rspamd. It is important to train both ham and spam emails. The rspamc command will allow you to feed entire directories/folders of emails to the learning process. Fortunately we are using the Maildir format to store emails which rspamd can understand. An example to train spam:

rspamc learn_spam /var/vmail/example.org/john/Maildir/.INBOX.Junk/cur

And this would be an example to train ham:

rspamc learn_ham /var/vmail/example.org/john/Maildir/cur".

Of course the quality of spam detection will depend on how good the source data is. So do not train spam emails from users who randomly put mails into their Junk folder that is not actually spam.

Check the number of emails you learned by running…

rspamc stat

Bayes spam checking will not work before it learned at least 200 spam and ham emails. Teaching rspamd fewer emails or just spam emails will not work. This is defined by the min_learns variable defined in /etc/rspamd/statistic.conf.

In the output you will find lines beginning with “Statfile” like these…

Statfile: BAYES_SPAM type: sqlite3; length: 41.78M; free blocks: 0; total blocks: 0; free: 0.00%; learned: 0; users: 1; languages: 1
Statfile: BAYES_HAM type: sqlite3; length: 51.12M; free blocks: 0; total blocks: 0; free: 0.00%; learned: 0; users: 1; languages: 1
Total learns: 0

This is what you usually start with. The more emails you feed into the training process the better the detection rate will be. Some emails however may not be long enough or be too similar to previously trained emails. So don’t worry if you are training 1000 emails but just get a count of 500 emails here.

Learning from user actions

Now we are getting to something really cool. Let’s tell Dovecot that moving emails into the Junk folder teaches rspamd instantly that the email is spam. And train an email as ham if it is moved out of the Junk folder. We will add triggers (actually “sieve scripts”) to the action of moving emails via IMAP.

There used to be a nice Dovecot plugin called “Antispam” but unfortunately it became deprecated. Bummer. The currently recommended way is to use the “IMAPSieve” plugin instead. There is nothing to install – it comes with the Dovecot packages. We just need to configure it.

A word of warning though: Currently the spam learning database is global for all users. If one user deliberately trains it with gibberish then it will ruin your detection rate. So the approach described here is suitably only for users who can tell ham from spam and can be trusted. It is also possible with rspamd to teach spam for each user but that’s currently not within the scope of this guide and may even be problematic because most users do not get enough ham and spam emails to make spam detection work properly. If you are still interested in per-user spam training see the respective rspamd documentation.

First order of business is enabling the IMAPSieve plugin for the IMAP protocol/service in Dovecot. Edit the /etc/dovecot/conf.d/20-imap.conf file and look for the line reading “mail_plugins”. Turn it into:

mail_plugins = $mail_plugins imap_sieve

We also need to edit Dovecot’s Sieve configuration to enable two plugins that are required for our task. Sieve is a scripting language that automates things in conjunction with emails and folders. Edit the file /etc/dovecot/conf.d/90-sieve.conf. First alter the line reading “sieve_plugins” to look like:

 sieve_plugins = sieve_imapsieve sieve_extprograms

And anywhere within the { … } section add these lines:

# From elsewhere to Junk folder
imapsieve_mailbox1_name = Junk
imapsieve_mailbox1_causes = COPY
imapsieve_mailbox1_before = file:/etc/dovecot/sieve/learn-spam.sieve

# From Junk folder to elsewhere
imapsieve_mailbox2_name = *
imapsieve_mailbox2_from = Junk
imapsieve_mailbox2_causes = COPY
imapsieve_mailbox2_before = file:/etc/dovecot/sieve/learn-ham.sieve

sieve_pipe_bin_dir = /etc/dovecot/sieve
sieve_global_extensions = +vnd.dovecot.pipe

The first rule tells Dovecot to run the Sieve rules as defined in the /etc/dovecot/sieve/learn-spam.sieve file whenever an email is moved into a user’s “Junk” folder. We will create that Sieve script in a minute.

The second rule sets the other way. Whenever an email is moved from the “Junk” folder to any (*) folder then the /etc/dovecot/sieve/learn-ham.sieve Sieve script is called.

The “sieve_pipe_bin_dir” setting defines where executable scripts are allowed to reside. We will put our simple learning scripts there. And finally the “sieve_global_extensions” setting enables the pipe plugin that allows sending email to external commands.

Note: if you come from previous versions of this guide, your mail directories may still use dots (“.”) instead of paths (“/”) to compose the folder structure. A clear sign is that you find directories like “INBOX.Junk” instead of just “Junk” in mail directories within /var/vmail. In that case replace the word “Junk” in the section above by “INBOX.Junk”.

Next up let’s create the Sieve scripts that we told Dovecot about. Create a new directory /etc/dovecot/sieve to put our new files in:

mkdir /etc/dovecot/sieve

Then create the file /etc/dovecot/sieve/learn-spam.sieve and let it contain:

require ["vnd.dovecot.pipe", "copy", "imapsieve"];
pipe :copy "rspamd-learn-spam.sh";

Let’s do the same for /etc/dovecot/sieve/learn-ham.sieve

require ["vnd.dovecot.pipe", "copy", "imapsieve"];
pipe :copy "rspamd-learn-ham.sh";

These two scripts need to be compiled – that is turning them into machine-readable code:

sievec /etc/dovecot/sieve/learn-spam.sieve
sievec /etc/dovecot/sieve/learn-ham.sieve

This creates two new files “learn-ham.svbin” and “learn-spam.svbin” that look like gibberish inside but are now in a format that Dovecot’s Sieve plugin can understand.

Let’s fix the permissions of these files, too, while we are at it:

chmod u=rw,go= /etc/dovecot/sieve/learn-{spam,ham}.sieve
chown vmail.vmail /etc/dovecot/sieve/learn-{spam,ham}.sieve

And the last step is to create the simple shell scripts that do the actual spam/ham training. The first file is /etc/dovecot/sieve/rspamd-learn-spam.sh which contains:

#!/bin/sh
exec /usr/bin/rspamc learn_spam

That looks simple, doesn’t it? Nothing more is actually needed. The spam email is piped to this script and rspamd learns it as a spam email and adjusts its spam detection database accordingly.

The second script teaches ham and is called /etc/dovecot/sieve/rspamd-learn-ham.sh. Make it contain:

#!/bin/sh
exec /usr/bin/rspamc learn_ham

These two shell scripts must be executable so go fix that:

chmod u=rwx,go= /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh
chown vmail.vmail /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh

I hope you haven’t lost your mind yet. It’s really just a chain of things to happen. Let’s reiterate how this process works:

  1. a user moves a spam email into their “Junk” folder
  2. Dovecot realizes that this triggers the Sieve rule “imapsieve_mailbox1” so it calls the Sieve script /etc/dovecot/sieve/learn-spam.sieve (in fact the *.svbin version of the script)
  3. Sieve will take the email and send (“pipe”) it to the executable rspamd-learn-spam.sh shell script
  4. the script in turn runs the email through the “/usr/bin/rspamc learn_spam” command

This works equally for the other way or learning ham emails of course.

I am sure you are eager to try it out. Yes, it’s about time. However to see that it actually works I suggest you edit the /etc/dovecot/conf.d/10-logging.conf file and set “mail_debug=yes”. That will add a lot more detail to the /var/log/mail.log file but on a busy server may also lead to headaches. 🙂

Restart Dovecot…

service dovecot restart

…and watch the /var/log/mail.log file…

tail -f /var/log/mail.log

Now open your IMAP client (Thunderbird, Evolution, Roundcube, mutt or whatever you prefer) and drag an email to your Junk folder. The mail log should read something along the lines of…

imap(john@example.org): Debug: imapsieve: mailbox INBOX.Junk: MOVE event
imap(john@example.org): Debug: imapsieve: Matched static mailbox rule [1]
imap(john@example.org): Debug: sieve: file storage: Using Sieve script path: /etc/dovecot/sieve/learn-spam.sieve
imap(john@example.org): Debug: sieve: file script: Opened script `learn-spam’ from `/etc/dovecot/sieve/learn-spam.sieve’
imap(john@example.org): Debug: sieve: Opening script 1 of 1 from `/etc/dovecot/sieve/learn-spam.sieve’
imap(john@example.org): Debug: sieve: Loading script /etc/dovecot/sieve/learn-spam.sieve
imap(john@example.org): Debug: sieve: Script binary /etc/dovecot/sieve/learn-spam.svbin successfully loaded
imap(john@example.org): Debug: sieve: binary save: not saving binary /etc/dovecot/sieve/learn-spam.svbin, because it is already stored
imap(john@example.org): Debug: sieve: Executing script from `/etc/dovecot/sieve/learn-spam.svbin’
imap(john@example.org): Debug: sieve: action pipe: running program: rspamd-learn-spam.sh
imap(john@example.org): Debug: Mailbox INBOX.Junk: Opened mail UID=3978 because: mail stream
imap(john@example.org): Debug: waiting for program `/etc/dovecot/sieve/rspamd-learn-spam.sh’ to finish after 0 msecs
imap(john@example.org): sieve: pipe action: piped message to program `rspamd-learn-spam.sh’

Look for errors and warnings. If at the end you see that Dovecot called the “rspamd-learn-spam.sh” script then you should be fine.

And finally if you pull an email out of the “Junk” folder you should see mailbox rule [2] be called and the email being learned as ham:

imap(john@example.org): Debug: imapsieve: mailbox INBOX: MOVE event
imap(john@example.org): Debug: imapsieve: Matched static mailbox rule [2]
imap(john@example.org): Debug: sieve: file storage: Using Sieve script path: /etc/dovecot/sieve/learn-ham.sieve
imap(john@example.org): Debug: sieve: file script: Opened script `learn-ham’ from `/etc/dovecot/sieve/learn-ham.sieve’
imap(john@example.org): Debug: sieve: Opening script 1 of 1 from `/etc/dovecot/sieve/learn-ham.sieve’
imap(john@example.org): Debug: sieve: Loading script /etc/dovecot/sieve/learn-ham.sieve
imap(john@example.org): Debug: sieve: Script binary /etc/dovecot/sieve/learn-ham.svbin successfully loaded
imap(john@example.org): Debug: sieve: binary save: not saving binary /etc/dovecot/sieve/learn-ham.svbin, because it is already stored
imap(john@example.org): Debug: sieve: Executing script from `/etc/dovecot/sieve/learn-ham.svbin’
imap(john@example.org): Debug: sieve: action pipe: running program: rspamd-learn-ham.sh
imap(john@example.org): Debug: Mailbox INBOX: Opened mail UID=28412 because: mail stream
imap(john@example.org): Debug: waiting for program `/etc/dovecot/sieve/rspamd-learn-ham.sh’ to finish after 0 msecs
imap(john@example.org): sieve: pipe action: piped message to program `rspamd-learn-ham.sh’

That’s it. Nifty, isn’t it?

Autoexpunge

Andi Olsen pointed out that Dovecot has introduced a feature to automatically delete emails in a folder that reach a certain age. This is especially useful for the “Trash” and “Junk” folders. To enable this feature just edit the /etc/dovecot/conf.d/15-mailboxes.conf file and add the autoexpunge parameter where desired. Example:

mailbox Junk {
  special_use = \Junk
  auto = subscribe
  autoexpunge = 30d
}
mailbox Trash {
  special_use = \Trash
  auto = subscribe
  autoexpunge = 30d
}

Restart Dovecot after any configuration change.

Logging

rspamd keeps a verbose log of its actions in /var/log/rspamd/rspamd.log. If a user complains that a certain email got blocked or at least flagged as spam then take a look at this log. You can match the /var/log/mail.log with it by comparing the Postfix queue ID. Those are the 12-digit hexadecimal number like “95CE05A00547“. Those IDs can be found in the rspamd.log, too:

2018-01-14 06:39:45 #10424(normal) <40985d>; task; rspamd_task_write_log: id: <undef>, qid: <95CE05A00547>, ip: 12.13.51.194, from: <…>, (default: F (no action): [3.40/15.00] [MISSING_MID(2.50){},MISSING_DATE(1.00){},MIME_GOOD(-0.10){text/plain;},ARC_NA(0.00){},ASN(0.00){asn:8220, ipnet:212.123.192.0/18, country:GB;},FROM_EQ_ENVFROM(0.00){},FROM_NO_DN(0.00){},RCPT_COUNT_ONE(0.00){1;},RCVD_COUNT_ZERO(0.00){0;},RCVD_TLS_ALL(0.00){},TO_DN_NONE(0.00){},TO_DOM_EQ_FROM_DOM(0.00){},TO_MATCH_ENVRCPT_ALL(0.00){}]), len: 181, time: 16.000ms real, 6.385ms virtual, dns req: 0, digest: <69b289a82827c11f759837c033cd800a>, rcpts: <…>, mime_rcpt: <…>

The web interface

rspamd’s web interface

rspamd comes with a neat bonus feature: a web interface. It allows you to check emails for spam, get statistics and fine-tune scores. It is already installed and enabled by default and expects HTTP requests on port 11334 on the localhost interface. I suggest you add a simple proxy configuration to your already working HTTPS-enabled web mail configuration to get access.

First you need to enable Apache’s module for HTTP proxying:

a2enmod proxy_http

You can either create a new virtual host configuration or just edit the /etc/apache2/sites-available/webmail.example.org-https.conf file. Anywhere within the VirtualHost tags add:

 ProxyPass "/rspamd" "http://localhost:11334"
 ProxyPassReverse "/rspamd" "http://localhost:11334"

This piece of configuration will forward any requests to https://webmail.example.org/rspamd to localhost:11334 and thus give you access to the rspamd web interface.

The interface is password protected. Let’s generate a new access password:

pwgen 15 1

This gives you a password like “eiLi1lueTh9mia4”. You could put that password in an rspamd configuration file. But cleartext passwords in configuration files are not quite elegant. Let’s create a hash of the password:

rspamadm pw
Enter passphrase: …
$2$icoahes75e7g9wxapnrbmqnpuzjoq7z…

Feed it the password that pwgen created for you and you will get a long hashed password. This procedure by the way is also documented on the rspamd pages.

Create a new configuration file /etc/rspamd/local.d/worker-controller.inc and put your hashed password in there:

password = "$2$icoahes75e7g9wxapnrbmqnpuzjoq7z…"

That’s it for the configuration. Finally restart both rspamd and Apache to load your changed configuration:

service rspamd reload
service apache2 restart

If everything went as expected you should now be able to access the rspamd web interface at https://webmail.example.org/rspamd

Anything else?

If you consider using rspamd for a larger environment then please take your time reading the good amount of documentation they provide. rspamd scales very well but requires additional setup like using Redis for faster spam analysis across multiple mail gateways.

120 thoughts on “Filtering out spam with rspamd”

  1. I think the /etc/rspamd/override/milter_headers.conf should be /etc/rspamd/override.d/milter_headers.conf

    (b) using pre-built statistics doesn’t seem to do anything maybe it is missing some rspamc commands ?

  2. Hi Christoph,

    rspamd listens also on 0.0.0.0 by default. For security reasons, I like to turn all public listening ports off (normal root server providers might not offer a firewall).

    Hence, I created 2 files in /etc/rspamd/local.d:

    worker-normal.inc
    bind_socket = “127.0.0.1:11333”;

    worder-proxy.inc
    bind_socket = “127.0.0.1:11332”;

    Regards,
    Andy

    1. Minor typo: “worder-proxy.inc” should be “worker-proxy.inc”, otherwise it doesn’t work.

      If you have a root server you can set up iptables as a firewall, configured to block everything by default and just open the desired ports. That way a misconfigured service doesn’t accidentally expose you. But I agree that listening on localhost for services that don’t need to be accessible from the outside is good practice (e.g. in case your firewall is misconfigured).

      1. As of v1.7, rspamd now only listens on localhost by default. This additional config is no longer neccessary

  3. Anyone has a running configuration to see the rspamd Web GUI ?
    I am trying to set it up with a nginx server on another machine and I don’t get it to run 🙁

    1. Christoph Haas

      I’m having problems, too. But I think I have found something that’s wrong in the documentation. I’ll add it as soon as it works here.

      1. Thanks a lot 🙂 I don’t have exactly the same setup as you have, but you “inspired” me to get the config working now 😉

      1. Sorry, little coy & paste mistake. Here is the right version:

        Maybe it helps:

        location ^~ /rspamd/ {
        proxy_pass http://localhost:11334/;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

  4. hi,
    for those who want to extend rspamd to support dkim, this is the following procedures:

    mkdir /var/lib/rspamd/dkim/
    rspamadm dkim_keygen -b 1024 -s mail -k /var/lib/rspamd/dkim/mail.key > /var/lib/rspamd/dkim/mail.txt
    (**I use 1024 as gandi.net seems to support only 1024 bits, feel free to move up to 2048. mail is a selector again feel free to change it **)
    chown -R _rspamd:_rspamd /var/lib/rspamd/dkim
    (** remember to set owner to rspamd **)
    chmod 440 /var/lib/rspamd/dkim/*

    Once the dkim key is set up it do:

    nano -$ /var/lib/rspamd/dkim/mail.txt

    It should look like this:

    mail._domainkey IN TXT ( “v=DKIM1; k=rsa; ”
    “p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2/al5HqXUpe+HUazCr6t9lv2VOZLR369PPB4t+dgljZQvgUsIKoYzfS/w9NagS32xZYxi1dtlDWuRfTU/ahHO2MYzE0zHE4lMfwb6VkNCG+pM6bAkCwc5cFvyRygwxAPEiHAtmtU5b0i9LY25Z/ZWgyBxEWZ0Wf+hLjYHvnvMqewPsduUqKVjDOdUqeBb1VAu3WFErOAGVUYfKqFX”
    “+yfz36Alb7/OMAort8A5Vo5t5k0vxTHzkYYg5KB6tLS8jngrNucGjyNL5+k0ijPs3yT7WpTGL3U3SEa8cX8WvOO1fIpWQz4yyZJJ1Mm62+FskSc7BHjdiMHE64Id/UBDDVjxwIDAQAB”
    ) ;

    create a dkim signing.conf:

    /etc/rspamd/local.d/dkim_signing.conf

    and fill it with :

    path = “/var/lib/rspamd/dkim/$selector.key”;
    selector = “mail”;
    ### Enable DKIM signing for alias sender addresses
    allow_username_mismatch = true;

    As rspamd also support arc:

    cp -R /etc/rspamd/local.d/dkim_signing.conf /etc/rspamd/local.d/arc.conf

    I took this from : https://thomas-leister.de/en/mailserver-debian-stretch/

    1. To configure spf, dkim and dmarc I followed the steps of https://dmarcguide.globalcyberalliance.org

      To configure the dkim_signing module to sign different subdomains with different dkim keys, I modify some steps:

      rspamadm dkim_keygen -k /var/lib/rspamd/dkim/subdomain.example.org.dkim.key -b 2048 -s dkim -d subdomain.example.org

      DNS
      dkim._domainkey.subdomain.example.org. IN TXT “v=DKIM1; k=rsa;” “p=MIIBI…..HtByA” “504pO…..DAQAB”

      chown -R _rspamd._rspamd /var/lib/rspamd/dkim
      chmod 640 /var/lib/rspamd/dkim/subdomain.example.org.dkim.key

      create a dkim signing.conf:
      /etc/rspamd/local.d/dkim_signing.conf

      and fill it with :
      path = “/var/lib/rspamd/dkim/$domain.$selector.key”;
      selector = “dkim”;
      allow_username_mismatch = true;
      use_esld = false;

      and then restart rspamd:
      systemctl restart rspamd

      https://github.com/vstakhov/rspamd/issues/1808

      I accept suggestions, since I have some doubts about whether it is the optimal configuration.
      Regards,
      Marcelo

  5. If you experience problems with outbound mails from authenticated users (with Postfix 2.11.3 on Debian jessie I got the error “4.7.1 Try again later” when sending outbound mails) try to replace

    milter_mail_macros = “i {mail_addr} {client_addr} {client_name} {auth_authen}”

    with

    milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}

    inside your main.cf 🙂

    1. THANK YOU for posting this!

      Rspamd has been treating my outbound e-mail as in-bound (and marking it as spam because I’m sending e-mail from an e-mail client running on a broadband IP).

      Once I removed the quotes as in your line, Rspamd now realises that I am an authenticated user and ignores the spam checks which are only relevant for inbound e-mail.

    2. Christoph Haas

      I wonder how you got quotes into your configuration. That could only happen if you edited the main.cf directly instead of using the “postconf” shell command.

  6. First of all, great guide!
    Your last command in den rspamd section “apache restart” should be “apache2ctl restart”

        1. Unfortunately the comment system removes lines enclosed with “lower than” and “greater than” symbols.
          The “Require all granted” line should be contained in a section entitled : Location “/rspamd”

    1. Davide Marchi

      This one (Giorgos clue) works fine for me!
      just add more:
      RewriteEngine on

      Thanks for the tips! 😉

  7. I suppose it’s a problem of copy/paste from the Jessie version. You write :

    The “require” lines include functionality to move emails into certain folders (fileinto) and to create folders if they don’t exist yet (mailbox). Then if SpamAssassin marked a header as spam it is moved into the INBOX.Junk folder which just appears as “Junk” to the user underneath their inbox.

    I suppose I have to read rspamd instead of SpamAssassin…

  8. Great tutorial – took me only about 3h to set up a new server…

    Is there any way to give feedback to rspamd by moving mails in and out of the spam folder, i.e. make it learn spam/ham by user actions?

  9. Justin L. Franks

    To change the score metrics, you don’t add them in /etc/rspamd/override.d/metrics.conf as described in the guide, since metrics.conf has been deprecated as of rspamd v1.7.

    They should be put in /etc/rspamd/override.d/rspam.conf.local.override instead.

    1. Justin L. Franks

      Correction: The edited score metrics should be placed in /etc/rspamd/rspamd.conf.local.override

      1. Davide Marchi

        Hi Christoph and Friends,
        is not clear for me if the right “score metrics” file path is (as suggested on Workaround tutorial) “/etc/rspamd/override.d/metrics.conf ” or as suggested from Justin L. Franks “/etc/rspamd/rspamd.conf.local.override” (since metrics.conf has been deprecated as of rspamd v1.7.)

        The same question obviously applies also to the other rspamd paths.

        An authoritative opinion would be useful 😉

        Davide

        1. Davide Marchi

          I’ve search into rspamd config files for “metrics.conf”:

          grep -R ‘metrics.conf’ /etc/rspamd/
          /etc/rspamd/metrics.conf: .include(try=true; priority=1; duplicate=merge) “$LOCAL_CONFDIR/local.d/metrics.conf”
          /etc/rspamd/metrics.conf: .include(try=true; priority=10) “$LOCAL_CONFDIR/override.d/metrics.conf”
          /etc/rspamd/common.conf:.include “$CONFDIR/metrics.conf”

          so rspamd search “metrics.conf” on:

          /etc/rspamd/local.d/metrics.conf
          /etc/rspamd/override.d/metrics.conf
          /etc/rspamd/metrics.conf

          again searching “$CONFDIR” the results are:

          grep -R ‘$CONFDIR’ /etc/rspamd/
          /etc/rspamd/rspamd.conf:.include “$CONFDIR/common.conf”
          /etc/rspamd/rspamd.conf: .include “$CONFDIR/options.inc”
          /etc/rspamd/rspamd.conf:.include(try=true; duplicate=merge) “$CONFDIR/cgp.inc”
          /etc/rspamd/rspamd.conf: .include “$CONFDIR/logging.inc”
          /etc/rspamd/rspamd.conf: .include “$CONFDIR/worker-normal.inc”
          /etc/rspamd/rspamd.conf: .include “$CONFDIR/worker-controller.inc”
          /etc/rspamd/rspamd.conf: .include “$CONFDIR/worker-proxy.inc”
          /etc/rspamd/rspamd.conf: .include “$CONFDIR/worker-fuzzy.inc”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/headers_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/subject_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/mua_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/rbl_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/statistics_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/fuzzy_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/policies_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/whitelist_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/surbl_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/phishing_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/hfilter_group.conf”
          /etc/rspamd/groups.conf: .include “$CONFDIR/scores.d/mime_types_group.conf”
          /etc/rspamd/common.conf:.include “$CONFDIR/metrics.conf”
          /etc/rspamd/common.conf:.include “$CONFDIR/actions.conf”
          /etc/rspamd/common.conf:.include “$CONFDIR/groups.conf”
          /etc/rspamd/common.conf:.include “$CONFDIR/composites.conf”
          /etc/rspamd/common.conf:.include “$CONFDIR/statistic.conf”
          /etc/rspamd/common.conf:.include “$CONFDIR/modules.conf”
          /etc/rspamd/common.conf:.include “$CONFDIR/settings.conf”

          no one “/etc/rspamd/rspamd.conf.local.override” or “/etc/rspamd/override.d/rspam.conf.local.override” I can see.
          so “/etc/rspamd/override.d/metrics.conf ” (and the other files) as suggested by Christoph Haas is right for me and wrong what suggest Justin L. Franks.

  10. My idea is to migrate the antispam of my server towards Rspamd, at present I use spamassassin.

    According to the documentation, to connect exim I must add the following rule:

    spamd_address = x.x.x.x 11333 variant=rspamd

    Inside the exim configuration I have these rules

    deny malware = */defer_ok
    message = This message contains a virus ($malware_name).
    deny message = SPAM Scan ($spam_score_int)
    spam = nobody:true/defer_ok
    condition = ${if >{$spam_score_int}{500}{1}{0}}
    deny message = Content Policy HELO required before MAIL
    condition = ${if eq{$sender_helo_name}{}}
    logwrite = Content Policy HELO required before MAIL
    deny message = Content Policy Restriction: Messages without From header are not permitted.
    condition = ${if eq{$header_from:}{}}
    logwrite = Content Policy Restriction: Messages without From header are not permitted.
    deny message = Content Policy Restriction: Multiple from addresses are not accepted here.
    condition = ${if match{$header_from:}{@.+@.+@}}
    logwrite = Content Policy Restriction: Multiple from addresses are not accepted here.
    accept

    To explain my scenario better, the rspamd service would be installed on a remote server, it would not be working locally.

    My problem is that I can not understand how to configure Rspamd to connect with exim.

    Where should I indicate the connection parameters? in which file?

    worker-controller.inc
    worker-normal.inc
    worker-proxy.inc

    the documentation of the following link does not help much: https://rspamd.com/doc/integration.html

    Could anyone help me please.

  11. Andi Olsen

    In the very beginning of the stretch guide you mention:
    “Automatic ham/spam learning. Whenever a user moves a mail into or out of the Junk folder it will be learned automatically.”

    Is this accomplished by the “(a) No Bayes training” section?

      1. For anyone who tries to configure automatic ham/spam-learnung under Ubuntu: You need Pigeonhole version 0.4.14 for IMAPSieve. Ubuntu 16.4 comes with version 0.4.13

      2. Hi Christoph, thanks again for adding this 🙂 but unfortunately it doesn’t seem to hit the scripts 🙁
        “The mail log should read something along the lines of…” –> not available and I checked every setting 3 times if I missed a step. I also tried to give the svbin files the same permissions, but no luck 🙁
        I think there must be something that I missed in the /etc/dovecot/conf.d/90-sieve.conf file, but I did the 2 steps there.

        1. OK, don’t ask… I now also found the part to debug the log… 😉 but still the script doesn’t semm to be fired, instead I have this in the log: sieve: include: sieve_global is not set; it is currently not possible to include `:global’ scripts

        2. After adding the following line to /etc/dovecot/conf.d/90-sieve.conf:
          sieve_global_dir=/etc/dovecot/sieve/

          I see the following the log:
          dovecot: imap(ham@example.org): Debug: imapsieve: mailbox INBOX.Junk: MOVE event
          dovecot: imap(ham@example.org): Debug: sieve: Pigeonhole version 0.4.16 (fed8554) initializing
          dovecot: imap(ham@example.org): Debug: sieve: Sieve imapsieve plugin for Pigeonhole version 0.4.16 (fed8554) loaded
          dovecot: imap(ham@example.org): Debug: sieve: Sieve Extprograms plugin for Pigeonhole version 0.4.16 (fed8554) loaded
          dovecot: imap(ham@example.org): Debug: imapsieve: Static mailbox rule [1]: mailbox=`Junk’ from=`*’ causes=(COPY) => before=`file:/etc/dovecot/sieve/learn-spam.sieve’ after=(none)
          dovecot: imap(ham@example.org): Debug: imapsieve: Static mailbox rule [2]: mailbox=`*’ from=`Junk’ causes=(COPY) => before=`file:/etc/dovecot/sieve/learn-ham.sieve’ after=(none)
          dovecot: imap(ham@example.org): Logged out in=225 out=1309

          Still no script startet after moving a mail to or from the Junk folder 🙁

          1. Andi Olsen

            You have to decide to either use Junk or INBOX.Junk everywhere.
            If you mix them up, things will not work 😀

  12. Andi Olsen

    When running the following commands:
    sievec /etc/dovecot/sieve/learn-spam.sieve
    sievec /etc/dovecot/sieve/learn-ham.sieve

    I get the following errors:
    sievec /etc/dovecot/sieve/learn-spam.sieve
    learn-spam: line 1: error: require command: unknown Sieve capability `vnd.dovecot.pipe’.
    learn-spam: line 1: error: require command: unknown Sieve capability `imapsieve’.
    learn-spam: line 2: error: unknown command ‘pipe’ (only reported once at first occurrence).
    learn-spam: error: validation failed.
    sievec(root): Error: failed to compile sieve script ‘/etc/dovecot/sieve/learn-spam.sieve’

    sievec /etc/dovecot/sieve/learn-ham.sieve
    learn-ham: line 1: error: require command: unknown Sieve capability `vnd.dovecot.pipe’.
    learn-ham: line 1: error: require command: unknown Sieve capability `imapsieve’.
    learn-ham: line 2: error: unknown command ‘pipe’ (only reported once at first occurrence).
    learn-ham: error: validation failed.
    sievec(root): Error: failed to compile sieve script ‘/etc/dovecot/sieve/learn-ham.sieve’

    1. Andi Olsen

      Nevermind. Just had to restart the dovecot service after adding everything to /etc/dovecot/conf.d/90-sieve.conf
      I’ve gotten so used to you telling me everything that I have to do in this guide, that I stopped thinking by myself 😛

  13. Andi Olsen

    In your guide you wrote:
    “These two shell scripts must be executable so go fix that:

    chmod u=rw,go= /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh
    chown vmail.vmail /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh”

    That does not make the scripts executable 🙂

  14. Danjel Jungersen

    When I move files from Junk to Trash the mail is trained as ham.
    Can I exclude this operation from ham-training, so that I can delete spam without training them as ham?

    1. Andi Olsen

      I just tested this and can confirm it myself.
      This can actually become a huge issue, as some people do tend to cleanup their Junk folder once in a while.

      1. Andi Olsen

        I think that the best solution would be to delete messages permanently, when they’re deleted from Junk, instead of moving them to Trash.

  15. Andi Olsen

    I hope suggested features are welcome here as well! 🙂
    I would imagine that a lot of people would benefit from a automatic expunge of emails in Junk and/or Trash! 😀

    1. Andi Olsen

      And seems like it’s fairly easy to add.
      Go to /etc/dovecot/conf.d/15-mailboxes.conf and add autoexpunge to the desired folder:
      mailbox Junk {
      auto = subscribe
      special_use = \Junk
      autoexpunge=30d
      }

  16. Just for other people on Ubuntu 16.04:

    If you try:
    sievec /etc/dovecot/sieve/learn-ham (or spam).sieve
    and it throws:
    sievec(root): Fatal: Plugin ‘sieve_imapsieve’ not found from directory /usr/lib/dovecot/modules/sieve

    Then you have to update dovecot to the latest stable build from the dovecot community repository. The package that ships with the official ubuntu rep doesn’t have most of the plugins

  17. Hello,

    I’ve noticed that Outlook (2016, Office 365) does the move to junk folder slightly different than other clients.

    When moving with Outlook, following entry is logged:
    Debug: imapsieve: mailbox Junk: APPEND event

    However, when moving with another client, webmail in this case, following entry is logged:
    Debug: imapsieve: mailbox Junk: MOVE event

    The Move event executes the learn scripts, but the append event doesn’t. How should this be fixed?

    1. So I figured out, that I can add APPEND to the rules in 90-sieve.conf -file, being as follows:

      # From elsewhere to Junk folder
      imapsieve_mailbox1_name = Junk
      imapsieve_mailbox1_causes = COPY APPEND
      imapsieve_mailbox1_before = file:/etc/dovecot/sieve/learn-spam.sieve

      # From Junk folder to elsewhere
      imapsieve_mailbox2_name = *
      imapsieve_mailbox2_from = Junk
      imapsieve_mailbox2_causes = COPY APPEND
      imapsieve_mailbox2_before = file:/etc/dovecot/sieve/learn-ham.sieve

      However, for some reason this fires both rules, and the mail is learn as spam and ham at the same time. That does not seem like a wanted situation. Any ideas on that?

        1. No, currently I’m instructing my users not to move the files in Outlook, but to do it in webmail.

          1. This sucks… couldn’t figure out why it didn’t work, and just found out i wasted all those hours 🙁
            So it’s outlook fault.. and most of my users use that client. Really hope someone will figure out a way to fix this.

      1. Xavier Reveillon

        My understanding is that COPY and APPEND are two different operations :
        – copy is an operation of movement from somewhere to elsewhere
        – append is just an addition, a movement with only a target, without source.

        So when someone “appends” a mail to wherever, the second rule is fired because append has no notion of “from”, and the condition mailbox_name = * is checked.

        And when someone “appends” a mail to Junk, both rules are fired.

  18. Hi anyone with this problem when running sieve-plugins?

    Debug: imapsieve: mailbox Spam: MOVE event
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: Pigeonhole version 0.4.16 (fed8554) initializing
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: include: sieve_global is not set; it is currently not possible to include `:global’ scripts.
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: Sieve imapsieve plugin for Pigeonhole version 0.4.16 (fed8554) loaded
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: Sieve Extprograms plugin for Pigeonhole version 0.4.16 (fed8554) loaded
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: imapsieve: Static mailbox rule [1]: mailbox=`Spam’ from=`*’ causes=(COPY) => before=`file:/etc/dovecot/sieve/learn-spam.sieve’ after=(none)
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: imapsieve: Static mailbox rule [2]: mailbox=`*’ from=`Spam’ causes=(COPY) => before=`file:/etc/dovecot/sieve/learn-ham.sieve’ after=(none)
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: imapsieve: Matched static mailbox rule [1]
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: file storage: Storage path `/var/vmail/parquedelconocimiento.com/mromanini/sieve’ not found
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: file storage: Storage path `/var/vmail/parquedelconocimiento.com/mromanini/.dovecot.sieve’ not found
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: storage: No default script location configured
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: file storage: Using Sieve script path: /etc/dovecot/sieve/learn-spam.sieve
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: file script: Opened script `learn-spam’ from `/etc/dovecot/sieve/learn-spam.sieve’
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: Opening script 1 of 1 from `/etc/dovecot/sieve/learn-spam.sieve’
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: Loading script /etc/dovecot/sieve/learn-spam.sieve
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: Script binary /etc/dovecot/sieve/learn-spam.svbin successfully loaded
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: binary save: not saving binary /etc/dovecot/sieve/learn-spam.svbin, because it is already stored
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: Executing script from `/etc/dovecot/sieve/learn-spam.svbin’
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: sieve: action pipe: running program: rspamd-learn-spam.sh
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: Mailbox Spam: Opened mail UID=10 because: mail stream
    Jun 18 20:06:09 correo dovecot: imap(john@example.net): Debug: waiting for program `/etc/dovecot/sieve/rspamd-learn-spam.sh’ to finish after 0 msecs
    Jun 18 20:06:19 correo dovecot: imap(john@example.net): Debug: program `/etc/dovecot/sieve/rspamd-learn-spam.sh'(8810) execution timed out after 10000 milliseconds: sending TERM signal
    Jun 18 20:06:19 correo dovecot: imap(john@example.net): Error: program `/etc/dovecot/sieve/rspamd-learn-spam.sh’ was forcibly terminated with signal 15
    Jun 18 20:06:19 correo dovecot: imap(john@example.net): Error: sieve: pipe action: failed to pipe message to program `rspamd-learn-spam.sh’: refer to server log for more information. [2018-06-18 20:06:19]
    Apriciate any help!
    Thanks!!

  19. First of all great guide !! Thank you so much.

    2 points from my experience setting up on a vanilla debian stretch system:
    – the downloaded prelearned stats from rspamd broke my learning: bayes.{spam,ham}.sqlite files. With kind help from the rspamd folks on freenode the solution was just removing them
    – redis was recommended to me as stats backend over sqlite on #rspamd

    Again, brilliant guide !

  20. Hi guys, rspamd works very well, but I would like to not apply the antispam to the users of the local network. I have received some complaints that are causing me a problem.

    When commenting on the line non_smtpd_milters the emails that are generated from the same system are not checked (via roundcube), but how can I add a local network to avoid antispam?

    I’m googling it but I can not find the solution.

  21. hi,
    which mistake have i made when all but no.3 of the 7 test mails from https://www.emailsecuritycheck.net come through rspamd and no 3 is rejected with smtp code 4.7.1 instead of 5.7.1 – which leads to the remote server continuously trying to deliver the mail?
    also, i cannot see the learning effect: when i move the messages to junk, the according logs appear, but the next bunch of mails is still ending up in INBOX.

  22. hi,
    what mistake have i made when
    – there is no learning effect (the according logs show up, but mails still end up in inbox)
    – test mails from https://www.emailsecuritycheck.net come through, except
    – no.3, which is rejected with smtp code 4.7.1 instead of 5.7.1, which leads to the sending server continuously trying to deliver the mail
    ?
    thanks for all the help.

  23. Javier Ortega Conde (Malkavian)

    Must be a semicolon at the end of the password line in /etc/rspamd/local.d/worker-controller.inc

    With your example:
    password = “$2$icoahes75e7g9wxapnrbmqnpuzjoq7z…”;

  24. Since today my long running mail server sticks with mail filtering:
    Sep 25 12:25:41 v6 postfix/cleanup[2292]: warning: milter inet:127.0.0.1:11332: can’t read SMFIC_BODYEOB reply packet header: Success
    Sep 25 12:25:41 v6 postfix/cleanup[2292]: 398669DD34: milter-reject: END-OF-MESSAGE from smtp.xxx[xxx]: 4.7.1 Service unavailable – try again later; from= to= proto=ESMTP helo=

    Every mail is rejected as so.

    Without miltering the postfix mail receiving works as expected.

    Any hints anybody?

    1. Same problem here. After an upgrade yesterday
      2018-09-25 13:21:40 status installed rspamd:amd64 1.8.0-1~stretch
      mail is not working anymore.
      I had to deactivate rspamd on a production system commenting out the lines in main.cf.
      Any ideas? THX

    2. After removing the antivirus.conf from override.d/ it seems to be working again.
      Maybe it helps temporarily without virus detection.

    3. Eduardo Saavedra

      This error is in clamav
      edit /etc/clamav-unofficial-sigs/master.conf
      yararulesproject_enabled=”no”
      enable_yararules=”no”
      And delete files .yar in /var/lib/clamav

  25. I am finding that with this

    # From Junk folder to elsewhere
    imapsieve_mailbox2_name = *
    imapsieve_mailbox2_from = Junk
    imapsieve_mailbox2_causes = COPY
    imapsieve_mailbox2_before = file:/etc/dovecot/sieve/learn-ham.sieve

    Emails that are in the Junk folder (either via RSPAMD or ones I have copied to train RSPAMD) are being piped through the learnham script upon deletion via my various IMAP clients (iPhone, roundcube etc). I guess because they are being moved from the Junk folder to the Trash folder.

    1. I’ve made the same observation which is why I added the following lines:

      # Mails that are deleted from Junk folder are being learned as spam (again)
      imapsieve_mailbox2_name = Trash
      imapsieve_mailbox2_from = Junk
      imapsieve_mailbox2_causes = COPY
      imapsieve_mailbox2_before = file:/var/customers/mail/sieve/global/learn-spam.sieve

      This is a workaround until I’ve got time to do some further research on this.

    2. The problem with the Trash can be solved with some changes in the “learn-ham.sieve” file.

      I’ve added

      require “environment”;

      if environment “imap.mailbox” “Trash” {
      # Putting spam in Trash mailbox is not significant
      stop;
      }

      if environment “imap.mailbox” “Spam” {
      # Copying mail inside Spam mailbox is not significant
      stop;
      }

      to the script, right before the pipe command.

      So my final script looks like this

      require [“vnd.dovecot.pipe”, “copy”, “imapsieve”];
      require “environment”;

      if environment “imap.mailbox” “Trash” {
      # Putting spam in Trash mailbox is not significant
      stop;
      }

      if environment “imap.mailbox” “Spam” {
      # Copying mail inside Spam mailbox is not significant
      stop;
      }

      pipe :copy “rspamd-learn-ham.sh”;

      Here you can find some more infos
      https://doc.dovecot.org/configuration_manual/spam_reporting/

  26. you ansible repo is not using spam detection at all, nor is updated with rspamd

    ispmail-postfix.yml
    # – name: Enabling Spamassassin milter
    # command: postconf smtpd_milters=unix:/spamass/spamass.sock

  27. Is it possible that I made a configuration mistake? If I send an email with a mail client (TB) to the postfix server destined for another virtual domain existing on this same server in this same database that no rspamd filtering occurs?
    Maybe anyone has a hint for me?

  28. I decided to give rspamd a try. But with greylisting I’d prefer another approach. I have postgrey running before the spamfiltering occurs, so the load the machine will be lower, as the possible spam, that can be catches with greylisting doesn’t bother the machine at all. So I switch off greylisting in rspamd and let postgrey do the job beforehand.

  29. Marcelo Alberto Gomez

    How do I ensure that a user or anybody isn’t using the server to send spam or sending bulk emails, etc.
    I tried postfwd with no success (to rate-limit the number of emails an account can send per day/hour/whatever). Has anyone been able to run postfwd with this installation? Do you know any other alternative?

  30. Keith Williams

    I noticed recently that I could no longer use the web ui. It had worked before. I checked all configuration, Apache, rspamd etc. Could not find the cause. The Apache webmail config was OK as what I was getting when going to …/rspamd was a page with the menu headers in a list a couple of links for saving and broken images. It was as if the js files and css were not working. I could see from the headers etc that rspamd was all OK. I checked all the permissions on .js and .css, all were fine.
    In the end I set up a tunnel. I defined the tunnel from localhost.8080 on my client machine to http://localhost:11334 on the server. Saved this config as rspamd. Details will vary on this dependant on your particular SSH client. This works a treat. I click on the icon for the tunnel, wait a second or two for it to connect, then usee the browser to point to http://localhost:8080 et voila, the UI is there. Because the SSH connection is made using a strong key it is secure, as the server receives the request for the UI page from a trusted source (localhost) no password is required

  31. rspamd seems to have a problem with very large messages (~50MB+).
    While everything else including messages with smaller attachments seems to run fine, the rspamd milter rejects those messages with a “temporary failure” (which is not exactly useful) and writes a message to the rspamd-log about the request entity being too large:

    “[…]task; rspamd_worker_error_handler: abnormally closing connection from: 127.0.0.1, error: Request entity too large: 63069870”

    Unfortunately it does not specify an exact limit, it just says what ever I am sending is too big, which makes it hard to communicate the limit to users.

    Is that something that can be configured?
    Unfortunately I have not been able to find any documentation on it, aside from a similar, but unrelated bug report (the bug report is about a crash. my process doesn’t crash, it just rejects big messages)…

    Has anyone ever seen this and maybe knows how to fix it?

  32. Thanks for your tutorial.

    Unfortunately When running rspamc learn_spam on my spam folder, I got this error for each message:

    HTTP error: 500, Unknown statistics error, found on stage learn; classifier: (null)

    and my total learns numbers is stalled to 0. I’m running the package from rspamd repo, and permissions are OK in the /var/lib/rspamd folder

    Do you know how can I fix that?

    Thanks for your help.

  33. Ben Chadwick

    Thanks for the great guide. Everything has worked flawlessly up to this point.
    Rspamd refuses milter connections from postfix.
    “/var/log/mail.log” says “warning: connect to Milter service inet:127.0.0.1:11332: Connection refused”
    I can “telnet 127.0.0.1:11333” and “telnet 127.0.0.1:11334” ok.
    “telnet 127.0.0.1:11332” says, “telnet: Unable to connect to remote host: Connection refused”
    Am I missing something simple. Everything I read says this is default.
    Any help would be appreciated.

    1. This probably won’t help you since my reply is coming months after your post, but maybe someone else scrolling through will find it helpful. Connecting to those ports means that rspamd has to be listening on them. In your /etc/rspamd/rspamd.conf file, do you have a worker setup for rspamd_proxy? It should include a line for: bind_socket = “127.0.0.1:11332”; Or run a netstat -an | grep 1133, and see if you have bindings listening to all of the rspamd ports. The IP will have to be 127.0.0.1 if you’re connecting into it via that address. Or there may be a configuration issue with just that worker object that’s preventing it from running. If so, you’ll see that as the case with the netstat results (and see no listing for 11332).

  34. Hello,

    When I tested my config with command “rspamadm configtest”, I got warning like this:

    $root@vps:/# rspamadm configtest
    – CPU doesn’t have SSSE3 instructions set required for hyperscan, disable it
    syntax OK

    And when I check if all processes are running, I got only several:
    $root@vps:/# pgrep -a rspam
    27729 rspamd: main process
    27730 rspamd: rspamd_proxy process (localhost:11332)
    27731 rspamd: controller process (localhost:11334)
    27732 rspamd: normal process (localhost:11333)

    The missing one is “normal process” and “hs_helper process”.

    Should I warry about my rspamd configuration? Or it is okey?

  35. So, DKIM Signing. Am I right?

    Anyway, so that’s the only piece of this whole thing that’s not working for me.
    I’m using a dkim selector map file, and a single path. It looks like the path checks out, the map file format checks out, and what I have configured in DNS checks out. But the problem is just that the signing isn’t being applied to outbound messages. In the log file, I see:
    “dkim_signing; lua_dkim_tools.lua:155: ignoring unauthenticated mail”

    I haven’t been able to find anything to clue me into what could be going on, there. I (believe I) have things setup to require proper authentication. Specifically, the SMTP connection requires the email address as the username (since I’m servicing multiple domains on the single mail server). If that name is wrong or missing, or the password isn’t correct (STARTTLS/Normal password), then mail-no-sendy, which is what I want.

    Mail sends out just fine, but it’s just not getting the DKIM signing treatment on its way out and that one line in the error log is all I have to go off of, but can’t figure out where to go to understand how/why rspamd is thinking the mail is unauthenticated.

    Any thoughts?
    Thanks!

  36. From last update it seems rspamd move to redis instead of sqlite, how can fix that?
    root:~# rspamadm configdump classifier.bayes.backend
    *** Section classifier.bayes.backend ***
    “redis”
    *** End of section classifier.bayes.backend ***

      1. Thanks !
        I will watch for next distro (buster) 🙂
        My mistake is was because i setup apt source list with original version of rspamd.
        When i make upgrade, rspamd broke.
        I remove rspamd, i remove apt source list.
        I installed from backport debian distro where is a old version of rspamd and work with setting from here.

  37. I have really appreciated each tutorial (Lenny, Jessie, Wheezy and now Stretch)
    Each has gone smoothly and worked flawlessly until Stretch, but likely that’s because I was slow on implementing it and some of the packages, particularly rspamd have moved on.

    I’ve repeated each step of the excellent tutorial and each step and test is OK up until “filtering out spam with rspamd” and the test “rspamc stat”
    From then on, things don’t work:

    I get:
    root@debian-vm:~# rspamc stat
    Results for command: stat (0.159 seconds)
    Messages scanned: 13
    Messages with action reject: 9, 69.23%
    Messages with action soft reject: 0, 0.00%
    Messages with action rewrite subject: 0, 0.00%
    Messages with action add header: 0, 0.00%
    Messages with action greylist: 0, 0.00%
    Messages with action no action: 4, 30.76%
    Messages treated as spam: 9, 69.23%
    Messages treated as ham: 4, 30.76%
    Messages learned: 0
    Connections count: 0
    Control connections count: 352
    Pools allocated: 375
    Pools freed: 352
    Bytes allocated: 21.11MiB
    Memory chunks allocated: 77
    Shared chunks allocated: 17
    Chunks freed: 0
    Oversized chunks: 122
    Fuzzy hashes in storage “rspamd.com”: 801200074
    Fuzzy hashes stored: 801200074
    Total learns: 0

    But not what I should see, namely:
    Statfile: BAYES_SPAM type: sqlite3; length: 41.78M; free blocks: 0; total blocks: 596k; free: 0.00%; learned: 1880; users: 1; languages: 3
    Statfile: BAYES_HAM type: sqlite3; length: 51.12M; free blocks: 0; total blocks: 684k; free: 0.00%; learned: 1578; users: 1; languages: 3
    Total learns: 3458

    The files seem in the correct location and settings:
    root@debian-vm:/var/lib/rspamd# ls -al *sqlite
    -rw-r–r– 1 _rspamd _rspamd 51125248 Sep 10 2015 bayes.ham.sqlite
    -rw-r–r– 1 _rspamd _rspamd 41777152 Sep 10 2015 bayes.spam.sqlite

    Also the next tutorial steps (learn_spam and learn_ham) commands fail:
    #rspamc learn_spam /var/vmail/xxx.ca/yyy/Maildir/.Junk/cur
    does see the appropriate mail files but then gives error message for each:
    Results for file: /var/vmail/xxx.ca/yyy/Maildir/.Junk/cur/1572201870.M943214P91949.serveitvm9,S=21739,W=22059:2, (0.024 seconds)
    HTTP error: 500, Unknown statistics error, found when storing data on backend; classifier: (null)

    Here are the versions

    Debian 9.11.0
    rspamd: 2.1-1~stretch
    postfix: 3.1.12-0+deb9u1

    Is there any hope, or do I need to wait for Buster???

    1. Hi Darrell,

      Looks like you’re not using sqlite as the backend for storing bayes information. Check “/etc/rspamd/statistic.conf”. There’s probably a line in there that reads:
      backend = “redis”;

      Hence it’s not reading statistics from the sqlite databases. You may want to consider using redis as backend as it’s recommended by rspamd anyway.

  38. Hi !
    I have a lot of problems since rspamd 2: Including a tempo of 120s when sending mails (smtp) ???
    I would like to come back to an earlier version of rspamd: 1.9 (Debian)
    Is it possible ?
    Where can I find this version and how to install it?
    Thank you in advance.
    And thank you very much for this tutorial 😉

    1. In fact, from version 2 of rspamd, it is imperative to use redis instead of sqlite to avoid problems !

  39. 1nformat0r

    The section LEARNING EXISTING SPAM at point (B) is not valid any more has no effect. Currently the latest rspamd version does not provide pre-built stats and those sqlite files are old and useless. SQLite is deprecated and instead redis should be used.

    1. Sebastian Mares

      Are you sure your information applies to the rspamd version used in this tutorial which is 1.8.1?

    2. Christoph Haas

      Generally not a bad advice for larger installations. However as Sebastian stated it’s a recommendation for newer rspamd versions indeed. It is not deprecated in the version at hand.

  40. Thought I’d just add this in case you’re using the redis store instead of sqlite. You can import sqlite into redis like this.

    To see help text run: rspamadm help statconvert
    Example invocation: rspamadm statconvert -d /var/lib/rspamd/bayes.spam.sqlite -h 127.0.0.1 -s BAYES_SPAM ; rspamadm statconvert -d /var/lib/rspamd/bayes.ham.sqlite -h 127.0.0.1 -s BAYES_HAM

  41. Great thanks .. just an update if you use Outlook as Client Change the Sieve rules to

    # From elsewhere to Junk folder (APPAND = OULOOK)
    imapsieve_mailbox1_name = Junk
    imapsieve_mailbox1_causes = COPY APPEND
    imapsieve_mailbox1_before = file:/etc/dovecot/sieve/learn-spam.sieve

    # From Junk folder to elsewhere
    imapsieve_mailbox2_name = *
    imapsieve_mailbox2_from = Junk
    imapsieve_mailbox2_causes = COPY
    imapsieve_mailbox2_before = file:/etc/dovecot/sieve/learn-ham.sieve

    # From (Junk folder) to INBOX (Outlook)
    imapsieve_mailbox3_name = Inbox
    imapsieve_mailbox3_causes = APPEND
    imapsieve_mailbox3_before = file:/etc/dovecot/sieve/learn-ham.sieve

  42. Hi, thanks you for this great tutoriel !
    Everything seems to work fine exept the sieve rules, I read 3 times this page et did nothing wrong and got theses error messages after dropping mail to Junk or Junk to INBOX

    Nov 17 16:36:33 nsx dovecot: imap(user@sysmailx.com): program `/etc/dovecot/sieve/rspamd-learn-spam.sh’ terminated with non-zero exit code 1
    Nov 17 16:36:33 nsx dovecot: imap(user@sysmailx.com): Error: sieve: pipe action: failed to execute to program `rspamd-learn-spam.sh’: refer to server log for more information. [2020-11-17 16:36:33]
    Nov 17 16:36:33 nsx dovecot: imap(user@sysmailx.com): Error: sieve: Execution of script /etc/dovecot/sieve/learn-spam.sieve failed

    Can somebody help me ???

    Thanks in advance

    1. Christoph Haas

      What happens when you run this:

      echo test | /etc/dovecot/sieve/rspamd-learn-spam.sh

      Also are you sure your system is running Debian Stretch and not Buster?

      1. echo test | /etc/dovecot/sieve/rspamd-learn-spam.sh

        Results for file: stdin (0.000 seconds)
        error = ” contains less tokens than required for bayes classifier: 3 < 11";
        filename = "stdin";
        scan_time = 0.0;

        I m using stretch 9.13 with upgraded system, stil the same error…

        1. *Updated sorry

          Here is my /var/log/rspamd/rspamd.log when I move mail to JUNK et JUNK to INBOX:

          2020-11-18 08:44:14 #20801(controller) ; csession; rspamd_controller_check_password: allow unauthorized connection from a trusted IP 127.0.0.1
          2020-11-18 08:44:14 #20801(controller) ; csession; rspamd_message_parse: loaded message; id: ; queue-id: ; size: 2828; checksum:
          2020-11-18 08:44:14 #20801(controller) ; csession; rspamd_mime_part_detect_language: detected part language: en
          2020-11-18 08:44:14 #20801(controller) ; csession; rspamd_mime_part_detect_language: detected part language: en
          2020-11-18 08:44:14 #20801(controller) ; csession; rspamd_stat_classifiers_process: skip statistics as SPAM class is missing
          2020-11-18 08:44:14 #20801(controller) ; csession; rspamd_task_process: learn error: Unknown statistics error, found when storing data on backend; classifier: (null)
          2020-11-18 08:44:14 #20801(controller) ; csession; rspamd_controller_learn_fin_task: cannot learn : Unknown statistics error, found when storing data on backend; classifier: (null)

          If it can help…

        2. Christoph Haas

          Alright. Thanks. The reason could also be wrong permissions/ownership of the files. Here it looks like this:

          -rwxr—– 1 vmail vmail 84 Nov 7 23:41 rspamd-learn-ham.sh
          -rwxr—– 1 vmail vmail 86 Nov 7 23:41 rspamd-learn-spam.sh

          1. ls -l return me

            total 24K
            4.0K -rw——- 1 vmail vmail 85 Nov 18 08:20 learn-ham.sieve
            4.0K -rw-r–r– 1 vmail vmail 238 Nov 18 08:20 learn-ham.svbin
            4.0K -rw——- 1 vmail vmail 86 Nov 18 08:20 learn-spam.sieve
            4.0K -rw-r–r– 1 vmail vmail 242 Nov 18 08:20 learn-spam.svbin
            4.0K -rwxr—– 1 vmail vmail 41 Nov 18 08:21 rspamd-learn-ham.sh
            4.0K -rwxr—– 1 vmail vmail 42 Nov 18 08:20 rspamd-learn-spam.sh

            The mail server works so far very good except the sieve part… I found nothing on internet, just tried with differents configs, errors are stil the same…

  43. Ok solved after tons of searching hours i’ve found what was wrong…

    With the new version of rspamd apparently you need to install redis-server then create /etc/rspamd/local.d/redis.conf with this content

    # /etc/rspamd/local.d/redis.conf
    read_servers = “127.0.0.1”;
    write_servers = “127.0.0.1”;

    Then convert the bayes files with this command.

    rspamadm statconvert /etc/rspamd/local.d/redis.conf –spam-db bayes.spam.sqlite –ham-db bayes.ham.sqlite –symbol-spam BAYES_SPAM –symbol-ham BAYES_HAM –redis-host 127.0.0.1:6379

    It should work now.

    Also if you want to see the dovecot debug log message when you drag your mails, you have to uncomment or add mail_debug = yes to /etc/dovecot/conf.d/10-logging.conf.

    Restart dovecot and you should see the log now:

    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: Loading modules from directory: /usr/lib/dovecot/modules
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: Module loaded: /usr/lib/dovecot/modules/lib95_imap_sieve_plugin.so
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: Effective uid=5000, gid=5000, home=/var/vmail/sysmailx.com/user
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: Namespace inbox: type=private, prefix=, sep=, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir:/var/vmail/sysmailx.com/user/Maildir
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: maildir++: root=/var/vmail/sysmailx.com/user/Maildir, index=, indexpvt=, control=, inbox=/var/vmail/sysmailx.com/user/Maildir, alt=
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: imapsieve: mailbox Junk: MOVE event
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: Pigeonhole version 0.4.16 (fed8554) initializing
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: include: sieve_global is not set; it is currently not possible to include `:global’ scripts.
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: Sieve imapsieve plugin for Pigeonhole version 0.4.16 (fed8554) loaded
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: Sieve Extprograms plugin for Pigeonhole version 0.4.16 (fed8554) loaded
    Nov 18 12:54:39 nsx dovecot: imap(fuser@sysmailx.com): Debug: imapsieve: Static mailbox rule [1]: mailbox=`Junk’ from=`*’ causes=(COPY) => before=`file:/etc/dovecot/sieve/learn-spam.sieve’ after=(none)
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: imapsieve: Static mailbox rule [2]: mailbox=`*’ from=`Junk’ causes=(COPY) => before=`file:/etc/dovecot/sieve/learn-ham.sieve’ after=(none)
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: imapsieve: Matched static mailbox rule [1]
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: file storage: Storage path `/var/vmail/sysmailx.com/user/sieve’ not found
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: file storage: Storage path `/var/vmail/sysmailx.com/user/.dovecot.sieve’ not found
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: storage: No default script location configured
    Nov 18 12:54:39 nsx dovecot: imap(fuser@sysmailx.com): Debug: sieve: file storage: Using Sieve script path: /etc/dovecot/sieve/learn-spam.sieve
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: file script: Opened script `learn-spam’ from `/etc/dovecot/sieve/learn-spam.sieve’
    Nov 18 12:54:39 nsx dovecot: imap(fuser@sysmailx.com): Debug: sieve: Opening script 1 of 1 from `/etc/dovecot/sieve/learn-spam.sieve’
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: Loading script /etc/dovecot/sieve/learn-spam.sieve
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: Script binary /etc/dovecot/sieve/learn-spam.svbin successfully loaded
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: binary save: not saving binary /etc/dovecot/sieve/learn-spam.svbin, because it is already stored
    Nov 18 12:54:39 nsx dovecot: imap(fuser@sysmailx.com): Debug: sieve: Executing script from `/etc/dovecot/sieve/learn-spam.svbin’
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: sieve: action pipe: running program: rspamd-learn-spam.sh
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: Mailbox Junk: Opened mail UID=21 because: mail stream
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Debug: waiting for program `/etc/dovecot/sieve/rspamd-learn-spam.sh’ to finish after 0 msecs
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): sieve: pipe action: piped message to program `rspamd-learn-spam.sh’
    Nov 18 12:54:39 nsx dovecot: imap(user@sysmailx.com): Logged out in=209 out=1289

    Hope that help and thanks again for this ISPmail server!

    1. fj you are my hero. I came in to work today and my coworker had forced rspamd to update and broke spam filtering. this made it work again!

  44. Hi all,

    I have a problem running the web interface.
    After the proxy configuration, the web interface start to load but only the text html.
    It does not load the CSS, images etc., the browser console return many messages like this one:

    [Error] Failed to load resource: the server responded with a status of 404 (Not Found) (bootstrap.min.css, line 0) https://webmail.xxxxxxxx.com/css/bootstrap.min.css

    It seem the rspamd gui path is missing.

    What I miss?

    Thanks

    1. I have solved the problem removing this tutorial rows:

      ProxyPass “/rspamd” “http://localhost:11334”
      ProxyPassReverse “/rspamd” “http://localhost:11334”

      and using the follow location inside my apache virtual host:

      Require all granted

      RewriteEngine On
      RewriteRule ^/rspamd$ /rspamd/ [R,L]
      RewriteRule ^/rspamd/(.*) http://localhost:11334/$1 [P,L]

      Now the https://webamil.example.com/rspamd web interface work properly but I have a login problem.
      I’m unable to login using the password created during the installation.
      I check it many times and it’s correct.
      I also tried to create a new one but every time when I insert the password I receive this message from rspamd:

      Undefined
      Request failed

      My browser console report this message:

      GET https://webmail.luxolab.com/rspamd/auth 403 (Unauthorized) jquery-3.5.1.min.js:2

      Could be a file permission problem?

      Thanks

  45. mail setup

    I think this is an interesting article it was really useful! here is more in this blog about How to Stop getting junk mail?, it is more familiar to me! keep doing awesome. instructions on Data Recovery Software Services and Support kindly follow our site.

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top