I made a Postfix + SpamAssassin setup following the instructions most websites recommend for this kind os setup. Basically I edited my master.cf to add:

smtp      inet  n       -       -       -       -       smtpd -o content_filter=spamassassin

spamassassin unix -     n       n       -       -       pipe
        user=debian-spamd argv=/usr/bin/spamc -f -e  
        /usr/sbin/sendmail -oi -f ${sender} ${recipient}

SpamAssassin actually works fine and my email gets filtered, however I noticed the following. In the past, before SpamAssassin when an email was sent to my sever the headers would show something like:

Return-path: <sender@sender-server.dev>
Envelope-to: <destination@my-server.dev>
Delivery-date: Wed, 02 Dec 2015 12:37:13 +0100
Received: from mail.sender-server.dev ...
    by mail.my-server.dev

After SpamAssassin they show:

Return-path: <sender@sender-server.dev>
Envelope-to: <destination@my-server.dev>
Delivery-date: Wed, 02 Dec 2015 12:37:13 +0100
Received: from mail.my-server.dev ...
    by mail.my-server.dev

Looks like at enabling SpamAssassin the Received: from is changed from the original server from where the email really came to my own server... Why does this happen? Can't this be fixed in a way my email is filtered by the correct headers are displayed? Thank you.


This was my final solution after research and help from @tarleb

My mail delivery was happening over sendmail program, which was adding some additional headers to my email. I could use a mitter (mail filter) to filter incoming email and drop the sendmail usage, however I decided to change to Dovecot LDA for the delivery.

My original filter was, at the beginning of Postfix's master.cf:

smtp      inet  n       -       -       -       -       smtpd -o content_filter=spamassassin

And at the end of the file:

spamassassin unix -     n       n       -       -       pipe
        user=debian-spamd argv=/usr/bin/spamc -f -e  
        /usr/sbin/sendmail -oi -f ${sender} ${recipient}

I changed the end of the file to use the Dovecot local delivery by:

spamassassin unix -     n   n   -   -   pipe
    flags=DROhu user=vmail:vmail argv=/usr/bin/spamc -f -e 
    /usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop} 

Now edit Postfix's main.cf and add (optional, check (3) bellow):

spamassassin_destination_recipient_limit = 1

Now your email will be delivered via Dovecot LDA without header changes. For the curious ones, here are some details on my config:

  1. This config can be used with plus-addressing / sub-addressing / recipient delimiters (emails addressed to user+nospam@example.com will be delivered into user@example.com inbox) - That's why I added -d ${user}@${nexthop} this will remove the + and everything until the domain. To enable this feature, also be sure to add recipient_delimiter = + into main.cf;
  2. My flags flags=DROhu, they don't add anything abnormal but they can be understood here: http://www.postfix.org/pipe.8.html;
  3. spamassassin_destination_recipient_limit = 1 is required to make sure that every recipient gets individually processed by spamassassin. This is required due to the D flag above (Includes X-Original-To header). If you've the D flag and you don't set spamassassin_destination_recipient_limit = 1 email with multiple destinations won't be delivered! If you don't care about this header you can remove the flag and this isn't needed.

Edit: Bonus Content - Move your SPAM to the Junk folder!

You can also configure Dovecot to move email detected as SPAM to the Junk IMAP folder. This will make your life easier for sure. Just follow this:

  1. Edit /etc/dovecot/conf.d/15-mailboxes.conf and uncomment / add the Junk folder with (should be on the namespace inbox section near mailbox Trash):

    mailbox Junk {
       special_use = \Junk
  2. Install dovecot-sieve with apt-get install dovecot-sieve;

  3. Edit /etc/dovecot/conf.d/90-sieve.conf and comment the line: #sieve = ~/.dovecot.sieve

  4. Edit /etc/dovecot/conf.d/90-plugin.conf as:

    plugin {
        sieve = /etc/dovecot/sieve/default.sieve
  5. Edit /etc/dovecot/conf.d/15-lda.conf and /etc/dovecot/conf.d/20-lmtp.conf to match:

    protocol lda/lmtp { # do not copy/paste this line!
      mail_plugins = $mail_plugins sieve

    WARNING: You might have another settings under the protocol selections, keep them. The line protocol lda/lmtp changes in the files, keep the original.

  6. Create folder /etc/dovecot/sieve/

  7. Create file /etc/dovecot/sieve/default.sieve with this content:

    require "fileinto";
    if header :contains "X-Spam-Flag" "YES" {
        fileinto "Junk";
  8. Change folder permissions to your virtual email user and group like: chown vmail:vmail /etc/dovecot/sieve/ -R. If you miss this dovecot will complain!

  9. Restart everything: service postfix restart; service dovecot restart; service spamassassin restart

  10. Try to send an email to some email on the server (from an external server), first a normal email and then another one with this subject: XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X. The second email should to into the Junk folder and the first to your inbox.

If this doesn't work at your first try, look at the logs: tail -f /var/log/mail.log and send the email while tail is running. A good working setup should report stored mail into mailbox 'INBOX' or stored mail into mailbox 'Junk'.

| improve this answer | |

That is the direct result of how mails should handled by SMTP servers: each server handling the mail will add a new Received header when processing the mail (as required by RFC 2821).

This is what you are seeing. The SpamAssassin service acts as a filter, getting the mail from postfix and sending the result back to postfix. Postfix is hence receiving the mail twice. Its inserting a Received header every time. That's why you see your own server listed there. The header probably contains something along the lines of (Postfix, from userid 120), where the user id belongs to your debian-spamd user.

Inspecting the rest of the mail header should show that there are more Received headers below. It's just that the old headers are hidden further down now, but they are still present. No information is lost.

| improve this answer | |
  • This was my first thought however I'm used to deal with cPanel servers and on those, even why SpamAssassin enabled and working there is no other Received header, only the X-Spam-* headers are added... Why and how? – TCB13 Dec 7 '15 at 17:50
  • 1
    @TCB13 There are multiple ways to involve SpamAssassin. An alternative to the so-called after-queue filtering (which is what you describe in the question) are milters. Milters (mail filters) are run via a different protocol and are involved as part of the main receiving SMTP process. They won't insert a separate header, as they are not called via SMTP. Milters are more complicated, but still neat because they allow you to reject mail with very high spam scores before they are added to the queue. Check out Amavisd-new if you want to try it. – tarleb Dec 7 '15 at 19:30
  • thanks for the heads up. I actually did read something about filters before. I'll look into it. ;) – TCB13 Dec 8 '15 at 0:17
  • 1
    @TCB13 Just realized my answer was partly wrong, fixed it. (SpamAssassin isn't acting as an SMTP server, the additional header is inserted by postfix when it's involved via /usr/sbin/sendmail.) – tarleb Dec 8 '15 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.