Search code examples
spamspamassassin

Spamassassin - score by time of day sent


Is there a way to assign a score for mail sent between certain hours. I find a lot of spam is sent in the middle of the night so would like to give anything between say 2am and 5am a score of 2 or 3.


Solution

  • You can use SpamAssassin to penalize mail received within certain hours, but it's messy.

    Before we start, verify that SA's primary defenses are properly set up:

    If that's insufficient, then you can address the sort of issue you're keying on. Try:

    If all that doesn't help enough, then (and only then) you can consider what you proposed. Read on.


    Don't forget about time zones. You can't use the Date header for this reason. This type of rule is not safe for deployments that have conversations that span too many time zones, and you must ensure the MX record servers are all consistent and on the same time zone. Be aware that daylight savings (aka “summer time”) can be annoying here.

    Identify a relay that your receiving infrastructure adds but is added before SpamAssassin runs (so SA can see it). This will manifest as a Received header near the top of your email. Again, make sure it's actually visible to SpamAssassin; the Received header added by your IMAP server will not be visible.

    It is possible that you have SpamAssassin configured to run before any internal relay is stamped into the message. If this is the case, do not proceed further as you cannot reliably determine the local time.

    Okay, all caveats aside, here's an example Received header:

    Received: from external-host.example.com
            (external-host.example.com [198.51.100.25])
            by mx.mydomain with ESMTPS id ABC123DEF456;
            Fri, 13 Mar 2020 12:34:56 -0400 (EDT)
    

    This must be a header one of your systems adds or else it could have a different time zone, clock skew, or even a forged timestamp.

    Match that in a rule that clearly denotes you as the author (by convention, start it with your initials):

    header   CL_RCVD_WEE_HOURS Received =~ /\sby\smx\.mydomain\swith\s[^:]{9,64}+:(?<=[0 ][2-4]:)[0-9:]{5}\s-0[45]00\s/
    describe CL_RCVD_WEE_HOURS Received by our mx.mydomain relay between 2a and 5a EST/EDT
    score    CL_RCVD_WEE_HOURS 0.500
    

    A walk through that regex (see also an interactive explanation at Regex101):

    • First, you need to verify that it's your relay, matched by name: by mx.mydomain with
    • Then, skip ahead 9-64 non-colon characters (quickly, with no backtracking, thus the + sign). You'll need to verify your server doesn't have any colons here
    • The real meat is in a look-behind (since we actually skipped over the hour for speed purposes), which seeks the leading zero (or else a space) and then the 2, 3, or 4 (not 5 since we don't want to match a time like 05:59:59)
    • Finally, there's a sanity check to ensure we're looking at the right time zone. I assumed you're in the US on the east coast, which is -0400 or -0500 depending on whether daylight savings is in effect

    So you'll need to change the server name, review whether the colon trick works with your relay, and possibly adjust the time zone regex.

    I also gave this a lower score than you desired. Start low and slowly raise it as needed. 3.000 is a really high value.