bugSpamAssassin Milter Plugin - Bugs: bug #58234, spamassassin-milter : header...


bug #58234: spamassassin-milter : header appends at end instead of beginning of header : howto prepend instead?

Submitter:  Hint Please <hintplease>
Submitted:  Fri 24 Apr 2020 08:18:49 AM UTC
Category:  None Severity:  2 - Minor
Item Group:  None Status:  Ready For Test
Privacy:  Public Assigned to:  gdt
Open/Closed:  Open
* Mandatory Fields

Add a New Comment Rich Markup

Sun 07 Jun 2020 08:36:55 PM UTC, comment #3: 


I encountered that today as well and played around with the source a bit. spamass-milter uses libmilter's smfi_addheader function to insert headers. Replacing it with smfi_insheader seems to put the headers at the top-most position. Here's the patch:

--- spamass-milter-0.4.0/spamass-milter.cpp 2014-09-11 02:38:00.000000000 +0200
+++ spamass-milter-0.4.0-mod/spamass-milter.cpp 2020-06-07 22:22:50.495030802 +0200
@@ -420,7 +420,7 @@
  } else if (newstring.size() > 0)
  debug(D_UORI, "u_or_i: inserting");
- smfi_addheader(ctx, const_cast<char*>(header), cstr);
+ smfi_insheader(ctx, 1, const_cast<char*>(header), cstr);
  } else
@@ -526,7 +526,7 @@
                 // time. Note, this may generate multiple X-Spam-Orig-To
                 // headers, but that's okay.
                 while( !assassin->recipients.empty()) {
-                  if ( smfi_addheader( ctx, const_cast<char >("X-Spam-Orig-To"), (char )assassin->recipients.front().c_str()) != MI_SUCCESS ) {
+                  if ( smfi_insheader( ctx, 1, const_cast<char >("X-Spam-Orig-To"), (char )assassin->recipients.front().c_str()) != MI_SUCCESS ) {
                         throw string( "Failed to save recipient" );

It is not well tested, use at your own risk ;)

Best regards,

Christoph Kindl <ckristo>
Wed 13 May 2020 12:26:28 PM UTC, comment #2: 

More details:

It seems to happen in DKIM messages which use */simple (relaxed/simple or simple/simple)

I can take a sample message and save it to a file. Then I can edit it and re-scan with dkim checks.

If I move the X-Spam* headers anywhere above the DKIM headers, the message passes both header and body checks.

If I leave the X-Spam* headers at the end of the headers, the DKIM headers pass, but the body fails.

I have found a work-around, which is poor for resources use, but allows for spamassassin to contribute to the pre-queue evaluation as a milter, but not break DKIM checks on body:

Tell spamass-milter to not add any headers (-M)

Use postfix content_filter with spamassassin for post-queue examination and markup of messages, and let it add headers (Which are prepended and don't appear to break DKIM body checks.)

Maybe this will help someone else finding the same problem with spamass-milter in postfix and only some DKIM signed messages.

Hint Please <hintplease>
Wed 13 May 2020 02:29:08 AM UTC, comment #1: 

Taking all of the SpamAssassin header items added to the bottom of the header, and prepending them just before the DKIM related headers actually allows the DKIM validation checks to pass.

calling spamc directly on a file which is a message results in the spamassassin headers beng prepended at the top of the headers.

Letting spamassassin-milter call spamc results in the same headers being appended at the end of all of the headers.

Hint Please <hintplease>
Fri 24 Apr 2020 08:18:49 AM UTC, original submission:  


We have and use several milters. Each that processes the message prepends their header lines at the top of previous headers except for spamassassin milter. It appears to add them to the bottom of the headers.

Is there a configuration option which will cause it to prepend the spamassassin added header items to the top of headers instead of the bottom of headers?

When I run a sample message through "spamc" directly, at the command line, spamc prepends the spamassassin header items to the top of the headers.

When I run spamassassin milter through postfix as a milter, the SpamAssassin results are appended at the end of the headers.

Other milters from postfix prepend to header top:

  • DKIM Validation and/or signing
  • DMARC Validation (from external, not internal)
  • AV/Malware Scanner

Only SpamAssassin Milter adds the spamassassin results to the end.

Why does it matter? Mostly, it does not. However, some spammers violate RFC on header/body separation, and it appears as though when this happens, DKIM signing they use include hints to separate header from body which include the bottom header name and value.

When postfix called milter for SpamAssassin is called and these SpamAssassin header items are appended at the bottom of the header items, it breaks the DKIM validation.

If I take the resulting editor and remove only those SpamAssasin headers, the resulting file passes all of the DKIM checks.

If I take those SpamAssassin items from the end of the headers, and cut them, then move them to the top, and save, the resulting file passes the dkim checks (header and body.)

So, again, why should that matter? Spammers are going to spam. Spammers will break RFC if convenient or helpful to spamming.

When this happens on the filter box, and those messages are passed to an internal mail server, the internal server DKIM check for those messages will now fail, and result in a bounce.

So, then what? Allowing bounces for when DKIM validation fails after validation + acceptance risks back-scatter, and getting on BackScatter blacklists.

Disable bounces when DKIM validation fails risks not notifying non-spammers when their DKIM signing process is broken, but nothing would be bounced if it can be rejected at the filter.

Is there a flag or configuration option for SpamAssassin Milter to result in the same headers being prepended just like when spamc is called from the command line and other milters add headers to messages?

OS: Hardened BSD 12, latest versions of packages and platform updated as of today.
Spamassassin Milter version, 0.4.0 package 0.4.0_4
SpamAssassin: 3.4.4
Perl: perl5 (revision 5 version 30 subversion 2)

Hint Please <hintplease>


(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:

No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by gdt (Updated the item)
  • -email is unavailable- added by ckristo (Posted a comment)
  • -email is unavailable- added by hintplease (Submitted the item)

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.


    Follow 3 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-08-02 gdt Severity3 - Normal 2 - Minor
        StatusNone Ready For Test
    2020-08-01 gdt Assigned toNone gdt

    Back to the top

    Powered by Savane 3.13-b921.
    Corresponding source code