Skip to content

Disable spam/virus check for outbound messages #3170

@marcinkunert

Description

@marcinkunert

This is actually a follow-up for #1713. I've finally found some time to tinker on it. I would share my solution and ask a few questions about possible improvements.

I've enabled avamis and spamassasin in the env, so starting up both incoming and outgoing messages are checked for spam.

ENABLE_AMAVIS=1
ENABLE_SPAMASSASSIN=1

So basically every message goes through postfix. I don't quite understand why after receiving the message by dovecot it gets transferred to postfix, and not directly to the inbox. I guess it's about reusing some useful parts like queues, spamchecks etc.

The solution I've found is to route the traffic either to amavis or a dummy filter to send out the message.

What is important here is the content_filter in /etc/postfix/main.cf

content_filter = smtp-amavis:[127.0.0.1]:10024

So the traffic always goes to smtp-amavis for it to handle the check and send the message. We can override this by using a FILTER like this:

smtpd_sender_restrictions =
  check_sender_access FILTER smtp-amavis:[127.0.0.1]:10026

This would also use smtp-amavis, but on another port, which we could use to our advantage and disable some checks there, like this (config/amavis.cf):

$inet_socket_port = [10024, 10026];

#interface_policy{'10026'} = 'ORIGINATING';

$policy_bank{'ORIGINATING'} = {
    originating => 1, # declare that mail was submitted by our smtp client

    # don't perform spam/virus/header check.
    bypass_spam_checks_maps => [1],
    bypass_virus_checks_maps => [1],
    bypass_header_checks_maps => [1],

    # allow sending any file names and types
    bypass_banned_checks_maps => [1],

    final_spam_destiny   => D_PASS, # insure spam passes
    final_banned_destiny => D_PASS, # insure banned files pass
};

But this took ~400 ms per message, and I was not entirely happy with it.

Ok, back to the topic. We need a conditional here. This can be used to switch between originating and foreign:

smtpd_sender_restrictions = 
  check_sender_access regexp:/etc/postfix/tag_as_originating.re
  permit_mynetworks
  permit_sasl_authenticated
  permit_tls_clientcerts
  reject_unknown_sender_domain
  reject_unknown_client_hostname
  check_sender_access regexp:/etc/postfix/tag_as_foreign.re

And the filters looks like this.

echo '/^/  FILTER filter:dummy ' > /etc/postfix/tag_as_originating.re
echo '/^/  FILTER smtp-amavis:[127.0.0.1]:10024' > /etc/postfix/tag_as_foreign.re

The missing part is the filter. It should be created in master.cf

filter    unix  -       n       n       -       10      pipe
    flags=Rq user=filter null_sender=
    argv=/opt/filter.sh -f ${sender} -- ${recipient}

It basically executes the /opt/filter.sh script:

#!/bin/sh

# Simple shell-based filter. It is meant to be invoked as follows:
#       /path/to/script -f sender recipients...

# Localize these. The -G option does nothing before Postfix 2.3.
INSPECT_DIR=/var/spool/filter
SENDMAIL="/usr/sbin/sendmail -G -i" # NEVER NEVER NEVER use "-t" here.

# Exit codes from <sysexits.h>
EX_TEMPFAIL=75
EX_UNAVAILABLE=69

# Clean up when done or when aborting.
trap "rm -f in.$$" 0 1 2 3 15

# Start processing.
cd $INSPECT_DIR || {
    echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }

cat >in.$$ || {
    echo Cannot save mail to file; exit $EX_TEMPFAIL; }

$SENDMAIL "$@" <in.$$

exit $?

Finally, to the questions:

  • the filter seems like a strange workaround, couldn't an existing service declared in /etc/postfix/master.cf used instead? I've tried using smtpd:10025, but it would fail from time to time with "corrupted format" message (or something like that)
  • the filter sends it using sendmail, does postfix also use it? I'm not quite sure about the relationship between these two? I assume sendmail is a part of postfix`
  • in the ideal case I would love to remove the entire filter part, I wonder if the content_filter = smtp-amavis:[127.0.0.1]:10024 can be cancelled out completely - I have to check that
  • I can't understand how the smtpd_sender_restrictions works. I guess it looks for the first true value, so after finding permit_mynetworks to be true it doesn't process the params further
  • do you see any points of what may fail here?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions