Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I was studying and searching 2 days about how to configure my exim/spamassassin/clamd configuration.

I have the next situation:

I have an email a@domain.com redirected to a@gmail.com. Unfortunately, every time a@domain.com receives a spam email, forwards it to a@gmail.com. In this situation, gmail deny it because identify it as spam, bounce it back, server try to forward the bounce and so on. I'm at the risk to get the IP blacklisted by google because of "sending spam".

The problem is....spamassassin correctly identify the spam and move it to Junk folder. I know that there is a way to filter the emails and forward them from Roundcube, but I have a control panel which make use of .forward file and I need to be able to do it out of Roundcube.

This is my exim4 config file

##########################################################################
SPAMASSASSIN = yes
SPAM_SCORE = 50
CLAMD =  yes
##########################################################################

domainlist local_domains = dsearch;/etc/exim4/domains/
domainlist relay_to_domains = dsearch;/etc/exim4/domains/
hostlist   relay_from_hosts = 127.0.0.1
hostlist   whitelist = net-iplsearch;/etc/exim4/white-blocks.conf
hostlist   spammers = net-iplsearch;/etc/exim4/spam-blocks.conf
no_local_from_check
untrusted_set_sender = *
acl_smtp_connect = acl_check_spammers
acl_smtp_mail = acl_check_mail
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
acl_smtp_mime = acl_check_mime

.ifdef SPAMASSASSIN
spamd_address = 127.0.0.1 783
.endif

.ifdef CLAMD
av_scanner = clamd: /var/run/clamav/clamd.ctl
.endif

tls_advertise_hosts = *
tls_certificate = /usr/local/ssl/certificate.crt
tls_privatekey = /usr/local/ssl/certificate.key

daemon_smtp_ports = 25 : 465 : 587 : 2525
tls_on_connect_ports = 465
never_users = root
host_lookup = *
rfc1413_hosts = *
rfc1413_query_timeout = 5s
ignore_bounce_errors_after = 2d
timeout_frozen_after = 7d

DKIM_DOMAIN = ${lc:${domain:$h_from:}}
DKIM_FILE = /etc/exim4/domains/${lc:${domain:$h_from:}}/dkim.pem
DKIM_PRIVATE_KEY = ${if exists{DKIM_FILE}{DKIM_FILE}{0}}


##########################################################################
begin acl
##########################################################################
acl_check_spammers:
  accept hosts = +whitelist
  drop    message       = Your host in blacklist on this server.
          log_message   = Host in blacklist
          hosts         = +spammers
  deny    message       = rejected because $sender_host_address is in a black list at $dnslist_domain\\n$dnslist_text
          dnslists      = ${readfile {/etc/exim4/dnsbl.conf}{:}}
  accept

acl_check_mail:
  deny
          condition     = ${if eq{$sender_helo_name}{}}
          message       = HELO required before MAIL
#  drop
#          condition     = ${if isip{$sender_helo_name}}
#          message       = Access denied - Invalid HELO name (See RFC2821 4.1.3)
  drop    message       = Helo name contains a ip address (HELO was $sender_helo_name) and not is valid
          condition     = ${if match{$sender_helo_name}{\N((\d{1,3}[.-]\d{1,3}[.-]\d{1,3}[.-]\d{1,3})|([0-9a-f]{8})|([0-9A-F]{8}))\N}{yes}{no}}
          condition     = ${if match {${lookup dnsdb{>: defer_never,ptr=$sender_host_address}}\}{$sender_helo_name}{no}{yes}}
          delay         = 45s
#  drop
#          condition     = ${if match{$sender_helo_name}{\N^\[\N}{no}{yes}}
#          condition     = ${if match{$sender_helo_name}{\N\.\N}{no}{yes}}
#          message       = Access denied - Invalid HELO name (See RFC2821 4.1.1.1)
  drop
          condition     = ${if isip{$sender_helo_name}}
          message       = Access denied - Invalid HELO name (See RFC2821 4.1.3)
#  drop
#          condition     = ${if match{$sender_helo_name}{\N\.$\N}}
#          message       = Access denied - Invalid HELO name (See RFC2821 4.1.1.1)
#  drop    message       = "REJECTED - Bad HELO - Host impersonating [$sender_helo_name]"
#          condition     = ${if match{$sender_helo_name}{$primary_hostname}}
  drop    condition     = ${if eq{[$interface_address]}{$sender_helo_name}}
          message       = $interface_address is _my_ address
  accept


acl_check_rcpt:
  accept  hosts         = :

  deny    message       = Restricted characters in address
          domains       = +local_domains
          local_parts   = ^[.] : ^.*[@%!/|]

  deny    message       = Restricted characters in address
          domains       = !+local_domains
          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./

  require verify        = sender

  accept  hosts         = +relay_from_hosts
          control       = submission

  accept  authenticated = *
          control       = submission/domain=

  require message       = relay not permitted
          domains       = +local_domains : +relay_to_domains

  deny    message       = smtp auth requried
         sender_domains = +local_domains
         !authenticated = *

  require verify        = recipient

.ifdef CLAMD
  warn    set acl_m0    = no
  warn    condition     = ${if exists {/etc/exim4/domains/$domain/antivirus}{yes}{no}}
          set acl_m0    = yes
.endif
.ifdef SPAMASSASSIN
  warn    set acl_m1    = no
  warn    condition     = ${if exists {/etc/exim4/domains/$domain/antispam}{yes}{no}}
          set acl_m1    = yes
.endif
  accept


acl_check_data:
.ifdef CLAMD
         deny message   = Message contains a virus ($malware_name) and has been rejected
         malware        = *
         condition      = ${if eq{$acl_m0}{yes}{yes}{no}}
.endif

.ifdef SPAMASSASSIN
  warn
         !authenticated = *
         hosts          = !+relay_from_hosts
         condition      = ${if < {$message_size}{100K}}
         condition      = ${if eq{$acl_m1}{yes}{yes}{no}}
         spam           = spamd:true/defer_ok
         add_header     = X-Spam-Score: $spam_score_int
         add_header     = X-Spam-Bar: $spam_bar
         add_header     = X-Spam-Report: $spam_report
         set acl_m2     = $spam_score_int
  warn
         condition      = ${if !eq{$acl_m2}{} {yes}{no}}
         condition      = ${if >{$acl_m2}{SPAM_SCORE} {yes}{no}}
         add_header     = X-Spam-Status: Yes
         message        = SpamAssassin detected spam (from $sender_address to $recipients).
.endif
  accept


acl_check_mime:
  deny   message       = Blacklisted file extension detected
         condition     = ${if match {${lc:$mime_filename}}{\N(\.ade|\.adp|\.bat|\.chm|\.cmd|\.com|\.cpl|\.exe|\.hta|\.ins|\.isp|\.jse|\.lib|\.lnk|\.mde|\.msc|\.msp|\.mst|\.pif|\.scr|\.sct|\.shb|\.sys|\.vb|\.vbe|\.vbs|\.vxd|\.wsc|\.wsf|\.wsh)$\N}{1}{0}}
  accept

##########################################################################
begin authenticators
##########################################################################
dovecot_plain:
  driver = dovecot
  public_name = PLAIN
  server_socket = /var/run/dovecot/auth-client
  server_set_id = $auth1

dovecot_login:
  driver = dovecot
  public_name = LOGIN
  server_socket = /var/run/dovecot/auth-client
  server_set_id = $auth1

##########################################################################
begin routers
##########################################################################

dnslookup:
  driver = dnslookup
  domains = !+local_domains
  transport = remote_smtp
  no_more

userforward:
  errors_to =
  driver = redirect
  check_local_user
  file = $home/.forward
  allow_filter
  no_verify
  no_expn
  check_ancestor
  file_transport = address_file
  pipe_transport = address_pipe
  reply_transport = address_reply

procmail:
  driver = accept
  check_local_user
  require_files = ${local_part}:+${home}/.procmailrc:/usr/bin/procmail
  transport = procmail
  no_verify

autoreplay:
  driver = accept
  require_files = /etc/exim4/domains/$domain/autoreply.${local_part}.msg
  condition = ${if exists{/etc/exim4/domains/$domain/autoreply.${local_part}.msg}}{yes}{no}}
  retry_use_local_part
  transport = userautoreply
  unseen

aliases:
  errors_to =
  driver = redirect
  headers_add = X-redirected: yes
  data = ${extract{1}{:}{${lookup{$local_part@$domain}lsearch{/etc/exim4/domains/$domain/aliases}}}}
  require_files = /etc/exim4/domains/$domain/aliases
  redirect_router = dnslookup
  pipe_transport = address_pipe
  unseen

localuser_fwd_only:
  driver = accept
  transport = devnull
  condition = ${if exists{/etc/exim/domains/$domain/fwd_only}{${lookup{$local_part}lsearch{/etc/exim/domains/$domain/fwd_only}{true}{false}}}}

localuser_spam:
  driver = accept
  transport = local_spam_delivery
  condition = ${if eq {${if match{$h_X-Spam-Status:}{\N^Yes\N}{yes}{no}}} {${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}{yes}{no_such_user}}}}

localuser:
  driver = accept
  transport = local_delivery
  condition = ${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}{true}{false}}

catchall:
  driver = redirect
  headers_add = X-redirected: yes
  require_files = /etc/exim4/domains/$domain/aliases
  data = ${extract{1}{:}{${lookup{*@$domain}lsearch{/etc/exim4/domains/$domain/aliases}}}}
  file_transport = local_delivery
  redirect_router = dnslookup

terminate_alias:
  driver = accept
  transport = devnull
  condition = ${lookup{$local_part@$domain}lsearch{/etc/exim4/domains/$domain/aliases}{true}{false}}


##########################################################################
begin transports
##########################################################################
remote_smtp:
  driver = smtp
  #helo_data = $sender_address_domain
  dkim_domain = DKIM_DOMAIN
  dkim_selector = mail
  dkim_private_key = DKIM_PRIVATE_KEY
  dkim_canon = relaxed
  dkim_strict = 0


procmail:
  driver = pipe
  command = "/usr/bin/procmail -d $local_part"
  return_path_add
  delivery_date_add
  envelope_to_add
  user = $local_part
  initgroups
  return_output

local_delivery:
  driver = appendfile
  maildir_format
  maildir_use_size_file
  user = ${extract{2}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}}}}
  group = mail
  create_directory
  directory_mode = 770
  mode = 660
  use_lockfile = no
  delivery_date_add
  envelope_to_add
  return_path_add
  directory = "${extract{5}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}}}}/mail/$domain/$local_part"
  quota = ${extract{6}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}}}}M
  quota_warn_threshold = 75%

local_spam_delivery:
  driver = appendfile
  maildir_format
  maildir_use_size_file
  user = ${extract{2}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}}}}
  group = mail
  create_directory
  directory_mode = 770
  mode = 660
  use_lockfile = no
  delivery_date_add
  envelope_to_add
  return_path_add
  directory = "${extract{5}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}}}}/mail/$domain/$local_part/.Junk"
  quota = ${extract{6}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}}}}M
  quota_directory = "${extract{5}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}}}}/mail/$domain/$local_part"
  quota_warn_threshold = 75%

address_pipe:
  driver = pipe
  return_output

address_file:
  driver = appendfile
  delivery_date_add
  envelope_to_add
  return_path_add

address_reply:
  driver = autoreply

userautoreply:
  driver = autoreply
  file = /etc/exim4/domains/$domain/autoreply.${local_part}.msg
  from = "${local_part}@${domain}"
  subject = "${if def:h_Subject: {Autoreply: ${quote:${escape:$h_Subject:}}} {Autoreply Message}}"
  to = "${sender_address}"

devnull:
  driver = appendfile
  file = /dev/null

##########################################################################
begin retry
*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h
##########################################################################
begin rewrite

This is my spamassassin configuration

# This is the right place to customize your installation of SpamAssassin.
#
# See 'perldoc Mail::SpamAssassin::Conf' for details of what can be
# tweaked.
#
# Only a small subset of options are listed below
#
###########################################################################

#   Add *****SPAM***** to the Subject header of spam e-mails
#
# rewrite_header Subject *****SPAM*****


#   Save spam messages as a message/rfc822 MIME attachment instead of
#   modifying the original message (0: off, 2: use text/plain instead)
#
 report_safe 0
 clear_report_template
 report_contact abuse@domain.com 
 report host: _HOSTNAME_ | contact: _CONTACTADDRESS_ | scores: _TESTSSCORES(,)_ | autolearn=_AUTOLEARN_, score=_AUTOLEARNSCORE_

#   Set which networks or hosts are considered 'trusted' by your mail
#   server (i.e. not spammers)
#
# trusted_networks 212.17.35.


#   Set file-locking method (flock is not safe over NFS, but is faster)
#
# lock_method flock


#   Set the threshold at which a message is considered spam (default: 5.0)
#
 required_score 5.0


#   Use Bayesian classifier (default: 1)
#
 use_bayes 1


#   Bayesian classifier auto-learning (default: 1)
#
 bayes_auto_learn 1


#   Set headers which may provide inappropriate cues to the Bayesian
#   classifier
#
 bayes_ignore_header X-Bogosity
 bayes_ignore_header X-Spam-Flag
 bayes_ignore_header X-Spam-Status
 bayes_ignore_header X-Spam-Report

#   Some shortcircuiting, if the plugin is enabled
# 
ifplugin Mail::SpamAssassin::Plugin::Shortcircuit
#
#   default: strongly-whitelisted mails are *really* whitelisted now, if the
#   shortcircuiting plugin is active, causing early exit to save CPU load.
#   Uncomment to turn this on
#
# shortcircuit USER_IN_WHITELIST       on
# shortcircuit USER_IN_DEF_WHITELIST   on
# shortcircuit USER_IN_ALL_SPAM_TO     on
# shortcircuit SUBJECT_IN_WHITELIST    on

#   the opposite; blacklisted mails can also save CPU
#
# shortcircuit USER_IN_BLACKLIST       on
# shortcircuit USER_IN_BLACKLIST_TO    on
# shortcircuit SUBJECT_IN_BLACKLIST    on

#   if you have taken the time to correctly specify your "trusted_networks",
#   this is another good way to save CPU
#
# shortcircuit ALL_TRUSTED             on

#   and a well-trained bayes DB can save running rules, too
#
# shortcircuit BAYES_99                spam
# shortcircuit BAYES_00                ham

endif # Mail::SpamAssassin::Plugin::Shortcircuit
share|improve this question

1 Answer 1

You have an acl_check_data acl where you invoke spamassassin. When SA detects spam exim sets the variable acl_m2=$spam_score_int. Now you can check that variable later in the routers and behave accordingly. F.e. do the next:

begin routers
nospam:
        driver          = accept
        condition       = ${if eq{$local_part@$domain}{a@domain.com}}
        condition       = ${if >{$acl_m2}{SPAM_SCORE}}
        transport       = devnull

go2gmail:
        driver          = redirect
        condition       = ${if eq{$local_part@$domain}{a@domain.com}}
        data            = a@gmail.com   
        pipe_transport  = address_pipe
        unseen
. . . . .
dnslookup:
        . . . . .

It is strictly significant that this two routers are placed before the dnslookup and all the magic has been done before message could be sended to the outer space. First router checks the variable and recipient's address and if they both are "bad" - simply drop the message to the blackhole. If not - the next router will redirect message to the gmail instead of original destination. And then the rest of routers will do their work. Also I've add the unseen verb to the second router. That's mean that the original message also will be processed and delivered to the original destination - i.e. to the local maildir where it will be accessible via roundcube.

share|improve this answer
    
Wow, I haven't expected an answer after so much time. Finally! Thank you so much. However, I don't understand the a@domain.com and the a@gmail.com. It doesn't looks like some variables, wouldn't emails be forwarded to a@gmail.com ? Thank you. –  demlasjr May 23 at 7:59
    
That's not a variables, that's a plain strings containing real email addresses you want to filter/redirect. If your local address is manager@some.cool.co.uk you have to put that string instead of a@domain.com. The same with a@gmail.com - that is just placeholder for the real email you want to redirect clean messages to. –  Kondybas May 23 at 8:59
    
The problem is that I have various domains and tens of emails accounts on that server, it wouldn't work, because doing that, the emails will be sent to a selected address instead of the designated received –  demlasjr May 23 at 15:15
    
Proposed solution works ONLY with explicitly defined email address while all others are stay intacted and processed as usual. And even messages to the selected address will be splitted into two copies - one will go to the gmail while the other will be delivered in usual way. Nevertheless, decision is your. –  Kondybas May 23 at 16:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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