Filter spam emails from being forwarded by exim4
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}{[email protected]}}
condition = ${if >{$acl_m2}{SPAM_SCORE}}
transport = devnull
go2gmail:
driver = redirect
condition = ${if eq{$local_part@$domain}{[email protected]}}
data = [email protected]
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.
Related videos on Youtube
Dipankar Maikap
Updated on September 18, 2022Comments
-
Dipankar Maikap almost 2 years
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 [email protected] redirected to [email protected]. Unfortunately, every time [email protected] receives a spam email, forwards it to [email protected]. 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 [email protected] 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
-
Dipankar Maikap about 10 yearsWow, I haven't expected an answer after so much time. Finally! Thank you so much. However, I don't understand the [email protected] and the [email protected]. It doesn't looks like some variables, wouldn't emails be forwarded to [email protected] ? Thank you.
-
Kondybas about 10 yearsThat's not a variables, that's a plain strings containing real email addresses you want to filter/redirect. If your local address is
[email protected]
you have to put that string instead of[email protected]
. The same with[email protected]
- that is just placeholder for the real email you want to redirect clean messages to. -
Kondybas about 10 yearsProposed 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.