Setting Up Amavis and ClamAV on Ubuntu Mail Server

This is part 11 in the Ubuntu mail server from scratch tutorial series. In this article, I will show you how to use Amavis and ClamAV to scan viruses in email messages.

Amavis (A Mail Virus Scanner) is a high-performance interface between a message transfer agent (MTA) such as Postfix and content filters. A content filter is a program that scans the headers and body of an email message, and usually takes some action based on what it finds. The most common examples are ClamAV virus scanner and SpamAssassin.

Set Up Amavis and ClamAV on Ubuntu Mail Server

Amavis speaks standard SMTP protocol and can also use the Sendmail milter interface. It’s commonly used for

  • virus-scanning by integrating with ClamAV (Clam AntiVirus)
  • spam-checking by integrating with SpamAssassin
  • DKIM signing and verification. (Actually, I prefer to use OpenDKIM for DKIM signing and verification.)

Prerequisites

You should have completed at least part 1 (Postfix SMTP server) and part 2 (Dovecot IMAP server) of the Ubuntu mail server from scratch tutorial series. Note that if you used iRedMail or Modoboa to set up your mail server, then Amavis and ClamAV are already installed and configured, so you don’t need to follow this tutorial.

Warning: Amavis and ClamAV require a fair amount of RAM. Make sure you have at least 1.3 GB free RAM on your server before installing Amavis and ClamAV. The whole mail server stack (Postfix, Dovecot, Amavis, ClamAV, SpamAssassin, OpenDKIM, MySQL/MariaDB, PostfixAdmin, and Roundcube Webmail) needs at least 3 GB RAM to run smoothly. If your RAM runs out, you are going to have troubles like mail server going offline or unresponsive.

Step 1: Install Amavis on Ubuntu

Amvis is available from the default Ubuntu repository, so run the following command to install it.

sudo apt install amavisd-new -y

Once installed, it automatically starts. You can check its status with:

systemctl status amavis

Output:

 amavis.service - LSB: Starts amavisd-new mailfilter
     Loaded: loaded (/etc/init.d/amavis; generated)
     Active: active (running) since Fri 2020-08-07 15:43:40 HKT; 1min 1s ago
       Docs: man:systemd-sysv-generator(8)
      Tasks: 3 (limit: 9451)
     Memory: 75.4M
     CGroup: /system.slice/amavis.service
             ├─1794260 /usr/sbin/amavisd-new (master)
             ├─1794263 /usr/sbin/amavisd-new (virgin child)
             └─1794264 /usr/sbin/amavisd-new (virgin child)

If it’s not running, you can start it with:

sudo systemctl start amavis

Enable auto-start at boot time.

sudo systemctl enable amavis

By default, it listen on 127.0.0.1:10024, as can be seen with:

sudo netstat -lnpt | grep amavis

amavis listening port

And it runs as the amavis user. To check the version number, run

amavisd-new -V

Sample output:

amavisd-new-2.11.0 (20160426)

To check the logs of Amavis, you can run

sudo journalctl -eu amavis

Viruses are commonly spread as attachments to email messages. Install the following packages for Amavis to extract and scan archive files in email messages such as .7z, .cab, .doc, .exe, .iso, .jar, and .rar files.

sudo apt install arj bzip2 cabextract cpio rpm2cpio file gzip lhasa nomarch pax rar unrar p7zip-full unzip zip lrzip lzip liblz4-tool lzop unrar-free

If you use Ubuntu 18.04, then also install the ripole package.

sudo apt install ripole

Note that if your server doesn’t use a fully-qualified domain name (FQDN) as the hostname, Amavis might fail to start. And the OS hostname might change, so it’s recommended to set a valid hostname directly in the Amavis configuration file.

sudo nano /etc/amavis/conf.d/05-node_id

Find the following line.

#$myhostname = "mail.example.com";

Remove the comment character (#) and change mail.example.com to your real hostname.

$myhostname = "mail.linuxbabe.com";

Save and close the file. Restart Amavis for the changes to take effect.

sudo systemctl restart amavis

Step 2: Integrate Postfix SMTP Server With Amavis

Amavisd-new works as an SMTP proxy. Email is fed to it through SMTP, processed, and fed back to the MTA through a new SMTP connection.

Edit the Postfix main configuration file.

sudo nano /etc/postfix/main.cf

Add the following line at the end of the file. This tells Postfix to turn on content filtering by sending every incoming email message to Amavis, which listens on 127.0.0.1:10024.

content_filter = smtp-amavis:[127.0.0.1]:10024

Also, add the following line.

smtpd_proxy_options = speed_adjust

This will delay Postfix connection to content filter until the entire email message has been received, which can prevent content filters from wasting time and resources for slow SMTP clients.

Save and close the file. Then edit the master.cf file.

sudo nano /etc/postfix/master.cf

Add the following lines at the end of the file. This instructs Postfix to use a special SMTP client component called smtp-amavis to deliver email messages to Amavis. Please allow at least one whitespace character (tab or spacebar) before each -o.  In postfix configurations, a preceding whitespace character means that this line is continuation of the previous line.

smtp-amavis   unix   -   -   n   -   2   smtp
    -o syslog_name=postfix/amavis
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20
    -o smtp_tls_security_level=none

Then add the following lines at the end of the file. This tells Postfix to run an additional smtpd daemon listening on 127.0.0.1:10025 to receive email messages back from Amavis.

127.0.0.1:10025   inet   n    -     n     -     -    smtpd
    -o syslog_name=postfix/10025
    -o content_filter=
    -o mynetworks_style=host
    -o mynetworks=127.0.0.0/8
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o strict_rfc821_envelopes=yes
    -o smtp_tls_security_level=none
    -o smtpd_tls_security_level=none
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_end_of_data_restrictions=
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings

Save and close the file. Restart Postfix for the changes to take effect.

sudo systemctl restart postfix

Step 3: Integrate Amavis with ClamAV

Now that Postfix can pass incoming emails to Amavis, we need to install the ClamAV virus scanner and integrate it with Amavis, so incoming emails can be scanned by ClamAV.

Install ClamAV on Ubuntu.

sudo apt install clamav clamav-daemon

There will be two systemd services installed by ClamAV:

  • clamav-daemon.service: the Clam AntiVirus userspace daemon
  • clamav-freshclam.service: the ClamAV virus database updater

First, check the status of clamav-freshclam.service.

systemctl status clamav-freshclam

clamav-freshclam-ubuntu-20.04

As you can see, it’s active (running) and uses 217.6M RAM on my mail server. Then check the journal/log.

sudo journalctl -eu clamav-freshclam

Output:

ClamAV virus database updater

Hint: If the above command doesn’t quit immediately, press the Q key to make it quit.

We can see that freshclam downloaded 3 virus databases. CVD stands for ClamAV Virus Database.

  • daily.cvd
  • main.cvd
  • bytecode.cvd

However, clamd was not notified because freshclam can’t connect to clamd through /var/run/clamav/clamd.ctl. Check the status of clamav-daemon.service.

systemctl status clamav-daemon

Output:

clamav-daemon ubuntu 20.04

As you can see, it failed to start because a condition wasn’t met. In the /lib/systemd/system/clamav-daemon.service file, there are two conditions:

ConditionPathExistsGlob=/var/lib/clamav/main.{c[vl]d,inc}
ConditionPathExistsGlob=/var/lib/clamav/daily.{c[vl]d,inc}

The clamav-daemon.service failed to start because main.cvd and daily.cvd were not downloaded yet when it starts. So we just need to restart this service.

sudo systemctl restart clamav-daemon

Now it should be running. By the way, it uses 731.4M RAM on my mail server. If your mail server doesn’t have enough RAM left, the service will fail.

systemctl status clamav-daemon.service

clamav-daemon.service ubuntu 20.04

The clamav-freshclam.service will check ClamAV virus database updates once per hour.

Now we need to turn on virus-checking in Amavis.

sudo nano /etc/amavis/conf.d/15-content_filter_mode

Uncomment the following lines to enable virus-checking.

#@bypass_virus_checks_maps = (
#      \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

ubuntu amavis turn on virus checking

Save and close the file. There are lots of antivirus scanners in the /etc/amavis/conf.d/15-av_scanners file. ClamAV is the default. Amavis will call ClamAV via the /var/run/clamav/clamd.ctl Unix socket. We need to add user clamav to the amavis group.

sudo adduser clamav amavis

Then restart Amavis and ClamAV daemon for the changes to take effect.

sudo systemctl restart amavis clamav-daemon

Check the logs.

sudo journalctl -eu amavis

You can see that Amavis is now using ClamAV to scan viruses.

Aug 08 17:26:19 mail.linuxbabe.com amavis[1233432]: Using primary internal av scanner code for ClamAV-clamd
Aug 08 17:26:19 mail.linuxbabe.com amavis[1233432]: Found secondary av scanner ClamAV-clamscan at /usr/bin/clamscan

Now if you send an email from other mail servers like Gmail to your own mail server and check the email headers, you can find a line like below, which indicates this email has been scanned by Amavis.

X-Virus-Scanned: Debian amavisd-new at linuxbabe.com

You should also check the mail log (/var/log/mail.log) to find if there are any errors.

Step 4: Use A Dedicated Port for Email Submissions

ClamAV can scan both incoming and outgoing emails now. Amavis listens on port 10024 for both incoming and outgoing email messages. However, it’s a good practice to use a different port such as 10026 for email submissions from authenticated users. Edit the Amavis configuration file.

sudo nano /etc/amavis/conf.d/50-user

Custom settings should be added between the use strict; and 1; line. By default, Amavis only listens on port 10024. Add the following line to make it also listen on port 10026.

$inet_socket_port = [10024,10026];

Then add the following line, which sets the “ORIGINATING” policy for port 10026.

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

Next, add the following lines, which define the “ORIGINATING” policy.

$policy_bank{'ORIGINATING'} = {  # mail supposedly originating from our users
  originating => 1,  # declare that mail was submitted by our smtp client
  allow_disclaimers => 1,  # enables disclaimer insertion if available

  # notify administrator of locally originating malware
  virus_admin_maps => ["virusalert\@$mydomain"],
  spam_admin_maps  => ["virusalert\@$mydomain"],
  warnbadhsender   => 1,

  # force MTA conversion to 7-bit (e.g. before DKIM signing)
  smtpd_discard_ehlo_keywords => ['8BITMIME'],
  bypass_banned_checks_maps => [1],  # allow sending any file names and types
  terminate_dsn_on_notify_success => 0,  # don't remove NOTIFY=SUCCESS option
  $undecipherable_subject_tag = '***Encrypted Message***',
};

Save and close the file. Restart Amavis.

sudo systemctl restart amavis

Check its status to see if the restart is successful.

systemctl status amavis

Next, edit the Postfix master configuration file.

sudo nano /etc/postfix/master.cf

Add the following line to the submission service, so emails from authenticated SMTP clients will be passed to Amavis listening on port 10026. This line will override (-o) the content_filter parameter in /etc/postfix/main.cf file that we added in step 2.

 -o content_filter=smtp-amavis:[127.0.0.1]:10026

Like this:

ubuntu postfix submissions amavis port 10026

If you have enabled the smtps service for Microsoft Outlook users, then you also need to add this line to the smtps service.

Save and close the file. Restart Postfix for the changes to take effect.

sudo systemctl restart postfix

Check its status to see if the restart is successful.

systemctl status postfix

Step 5: Receive Virus Alert

You need to create an email address [email protected] to receive virus alerts from ClamAV. Note that you should create a real email address instead of creating an alias. ClamAV will bypass Postfix and submit alert emails directly to Dovecot, which isn’t configured to query aliases in the PostfixAdmin database.

Spam Filtering in Amavis

Note: If you have followed my SpamAssassin tutorial, you don’t need to enable spam-checking in Amavis. If you enable it, each email will be checked twice by SpamAssassin.

To enable spam-checking in Amavis, install SpamAssassin and related packages.

sudo apt install spamassassin libnet-dns-perl libmail-spf-perl pyzor razor

Edit an Amavis configuration file.

sudo nano /etc/amavis/conf.d/15-content_filter_mode

Uncomment the following lines to enable spam-checking.

#@bypass_spam_checks_maps = (
#   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

Save and close the file. Then restart Amavis.

sudo systemctl restart amavis

DKIM in Amavis

Two common pieces of software that can do DKIM signing and verification on Linux are OpenDKIM and Amavis. I prefer to use OpenDKIM because it works better with OpenDMARC. So I won’t explain how to DKIM sign your email in Amavis.

By default, Amavis can verify the DKIM signature of incoming email messages. If you have OpenDKIM running on your mail server, then you can disable DKIM verification in Amavis.

sudo nano /etc/amavis/conf.d/21-ubuntu_defaults

Find the following line and change 1 to 0, so Amavis won’t verify DKIM signatures.

$enable_dkim_verification = 1;

Save and close the file. Then restart Amavis.

sudo systemctl restart amavis

When receiving incoming emails, Postfix will call OpenDKIM via the sendmail milter interface to verify DKIM signatures, then pass the email to Amavis for virus-checking. When sending outgoing emails, Postfix will call OpenDKIM to sign the emails, then pass them to Amavis for virus-checking.

Improving Amavis Performance

By default, Amavis runs 2 processes. If you see the following lines in the mail log (/var/log/mail.log), it means Amavis can’t process emails fast enough.

postfix/qmgr[1619188]: warning: mail for [127.0.0.1]:10024 is using up 4001 of 4008 active queue entries
postfix/qmgr[1619188]: warning: you may need to reduce smtp-amavis connect and helo timeouts
postfix/qmgr[1619188]: warning: so that Postfix quickly skips unavailable hosts
postfix/qmgr[1619188]: warning: you may need to increase the main.cf minimal_backoff_time and maximal_backoff_time
postfix/qmgr[1619188]: warning: so that Postfix wastes less time on undeliverable mail
mail postfix/qmgr[1619188]: warning: you may need to increase the master.cf smtp-amavis process limit
mail postfix/qmgr[1619188]: warning: please avoid flushing the whole queue when you have
mail postfix/qmgr[1619188]: warning: lots of deferred mail, that is bad for performance

To improve performance, edit Amavis configuration file.

sudo nano /etc/amavis/conf.d/50-user

Add the following line in the file between the use strict; and 1; line. This will make Amavis run 4 processes. If you have 10 CPU cores, you can change 4 to 10. Note that running more than 10 Amavis processes has little effect on performance.

$max_servers = 4;

Save and close the file. Then edit the Postifx master configuration file.

sudo nano /etc/postfix/master.cf

Find the smtp-amavis service definition, and change the process limit from 2 to 4.

smtp-amavis   unix   -   -   n   -   4   smtp
    -o syslog_name=postfix/amavis
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20
    -o smtp_tls_security_level=none

Save and close the file. Then restart Amavis and Postfix for the changes to take effect.

sudo systemctl restart amavis postfix

Now run the following command. You should see that there are 4 Amavis processes now.

sudo amavisd-nanny

sudo amavisd-nanny

Press Ctrl+C to stop amavisd-nanny.

Skip Virus-Checking for Your Newsletters

If you use your mail server to send newsletters, and you enable Amavis and ClamAV, then lots of CPU and RAM resources will be used for virus-checking when you send newsletters to your subscribers. It could make your mail server unresponsive. You can skip virus-checking for your newsletters by using the method below.

Edit the Postfix master configuration file.

sudo nano /etc/postfix/master.cf

Add the following lines at the beginning of this file. This will enable smtpd on port 2525 of the localhost and it can accept client connections initiated from the same server. If there’s another process listening on port 2525, you can change 127.0.0.1:2525 to something else, like 127.0.0.1:2552. Note that the content_filter parameter is set to none, which means emails won’t be scanned by ClamAV.

127.0.0.1:2525      inet  n       -       -       -       1       smtpd
  -o syslog_name=postfix/2525
  -o postscreen_greet_action=ignore
  -o content_filter=

Then add the following lines at the end of this file. Replace 12.34.56.78 with the mail server’s public IP address. This will create another Postfix submission daemon listening on port 10587. This is for client connections from another server.

12.34.56.78:10587     inet     n    -    y    -    -    smtpd
  -o syslog_name=postfix/10587
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=no
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o content_filter=

Save and close the file. Then Restart postfix.

sudo systemctl restart postfix

If your newsletter application runs on the mail server, then specify 127.0.0.1:2525 as the SMTP host, without SMTP authentication. If your newsletter application runs on a different server, then specify 12.34.56.78:10587 as the SMTP host, with SMTP authentication.

Troubleshooting

If your Postfix SMTP server can’t send outgoing emails, and you find the following error message in the mail log (/var/log/mail.log),

relay=none, delay=239, delays=239/0.04/0/0, dsn=4.3.0, status=deferred (server unavailable or unable to receive mail)

it could be that amavis is not running, so you need to check its status:

sudo systemctl status amavis

You can restart it with:

sudo systemctl restart amavis

Another cause for this error is that you are enforcing TLS connection for Postfix when sending outgoing emails with the following setting in the /etc/postfix/main.cf file.

smtp_tls_security_level = enforce

Since Postfix can’t establish TLS connection to Amavis, so the email is deferred. You should use the following setting.

smtp_tls_security_level = may

Then restart Postfix.

Using ClamAV to Scan Virus for the Linux File System

While the main topic of this article is virus scanning for emails, since ClamAV is installed on the server, why not use it to scan viruses for other files?

First, edit the ClamAV configuration file.

sudo nano /etc/clamav/clamd.conf

Find the following line:

MaxDirectoryRecursion 15

The default maximum depth directories scanned by ClamAV is 15, you probably want to change it to a bigger number to avoid the “directory recursion limit reached” warning.

MaxDirectoryRecursion 30

Then find the following two lines.

MaxScanSize 100M
MaxFileSize 25M

The default max scan size is 100M and the max file size is 25M. It’s likely that your server has files of more than 100M. The default config will produce the following errors when the file size exceeds the limit.

LibClamAV Warning: PNG: Unexpected early end-of-file.
LibClamAV Warning: cli_scanxz: decompress file size exceeds limits - only scanning 27262976 bytes

You can increase the scan size like:

MaxScanSize 2048M
MaxFileSize 2048M

Linux has many special files in /proc/, /sys/, /run/, /dev/, /snap/ and /var/lib/lxcfs/cgroup/ directory that should not be scanned, so you need to exclude them in ClamAV by adding the following lines at the end of this file.

ExcludePath ^/proc
ExcludePath ^/sys
ExcludePath ^/run
ExcludePath ^/dev
ExcludePath ^/snap
ExcludePath ^/var/lib/lxcfs/cgroup

Save and close the file. Then restart clamav-daemon.service for the changes to take effect.

sudo systemctl restart clamav-daemon

Wait a few seconds for clamav-daemon.service to finish restarting. Next, you can start scanning with:

sudo clamdscan --fdpass /

This will scan the entire Linux file system, excluding the directories we mentioned earlier. To make ClamAV scan the file sytem automatically, edit the root user’s crontab file.

sudo crontab -e

Add the following line to this file. ClamAV will scan the entire file system at 5:10AM every day.

10 5 * * * /usr/bin/clamdscan --fdpass /

Save and close the file.

Hint #1: There’s another utility called clamscan that can also be used for virus scanning. However, clamscan doesn’t use the virus definition database that’s already loaded in memory. It will load a separate copy of virus definition database into memory again, wasting server resources.clamscan is also slower than clamdscan, so I don’t recommend it.

Hint #2: If there are a huge number of files on your server, clamdscan will use lots of CPU resources.

Wrapping Up

I hope this tutorial helped you set up Amavis and ClamAV on Ubuntu mail server. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial
[Total: 25 Average: 5]

61 Responses to “Setting Up Amavis and ClamAV on Ubuntu Mail Server

  • IMRON AMD
    3 years ago

    Thank you Xiao? Works for me, 5 Star for you!

  • Hello Xiao,

    After performing “Step 3: Integrate Amavis with ClamAV”, the mail server stopped receiving emails. How do i look at?


    Kindest Regards

    • Xiao Guoan (Admin)
      3 years ago

      Make sure your server has enough RAM to run ClamAV.

      • Hello Xiao and Thank You so much.

        However that is not the problem.

        When i finish “Step 2: Integrate Postfix SMTP Server With Amavis” and before “step 3” the server no longer send or receive emails. At this time ClamAV is not yet installed.


        Kindest Regards

    • Xiao Guoan (Admin)
      3 years ago

      Always check the mail log file (/var/log/mail.log) and Dovecot log (sudo journalctl -eu dovecot) to troubleshoot mail server problems.

      • Hello Xiao, Thank you.

        I’ve added “smtp_tls_security_level=none” to “smtp-amavis unix – – n – 4 smtp” in master.cf and then the servers started send and receive emails.

  • I am stumped with my setup. I am able to send out to external email addresses, but not local addresses. And no email is being received. My postconf -n is below: I have not seen the possible simple step I am missing here…telnet localhost 25, times out..Any help appreciated..

    Postconf
    alias_database = hash:/etc/aliases
    alias_maps = hash:/etc/aliases
    append_dot_mydomain = no
    biff = no
    compatibility_level = 2
    inet_interfaces = all
    inet_protocols = ipv4
    mailbox_size_limit = 0
    mailbox_transport = lmtp:unix:private/dovecot-lmtp
    message_size_limit = 52428800
    milter_default_action = accept
    milter_protocol = 6
    mydestination = xxxxxxxshipxx.org, $myhostname, localhost.$mydomain, localhost
    mydomain = xxxxxxxxxshipxx.org
    myhostname = mail.xxxxxxxxxshipxx.org
    mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
    myorigin = xxxxxxxshipxx.org
    non_smtpd_milters = $smtpd_milters
    policyd-spf_time_limit = 3600
    readme_directory = no
    recipient_delimiter = +
    relayhost =
    smtp_tls_loglevel = 1
    smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
    smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
    smtp_tls_security_level = may
    smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
    smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
    smtpd_milters = local:opendkim/opendkim.sock
    smtpd_proxy_options = speed_adjust
    smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, check_policy_service unix:private/policyd-spf
    smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination
    smtpd_tls_cert_file = /etc/letsencrypt/live/mail.xxxxxxxxshipxx.org/fullchain.pem
    smtpd_tls_key_file = /etc/letsencrypt/live/mail.xxxxxxxxshipxx.org/privkey.pem
    smtpd_tls_loglevel = 1
    smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
    smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
    smtpd_tls_security_level = may
    smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
    smtputf8_enable = no

    Master
    #
    # Postfix master process configuration file. For details on the format
    # of the file, see the master(5) manual page (command: “man 5 master” or
    # on-line: http://www.postfix.org/master.5.html).
    #
    # Do not forget to execute “postfix reload” after editing this file.
    #
    # ==========================================================================
    # service type private unpriv chroot wakeup maxproc command + args
    # (yes) (yes) (no) (never) (100)
    # ==========================================================================
    smtp inet n – n – – smtpd
    #smtp inet n – y – 1 postscreen
    #smtpd pass – – y – – smtpd
    #dnsblog unix – – y – 0 dnsblog
    #tlsproxy unix – – y – 0 tlsproxy

    submission inet n – y – – smtpd
    -o syslog_name=postfix/submission
    -o smtpd_tls_security_level=encrypt
    -o smtpd_tls_wrappermode=no
    -o smtpd_sasl_auth_enable=yes
    # -o smtpd_tls_auth_only=yes
    # -o smtpd_reject_unlisted_recipient=no
    # -o smtpd_client_restrictions=$mua_client_restrictions
    # -o smtpd_helo_restrictions=$mua_helo_restrictions
    # -o smtpd_sender_restrictions=$mua_sender_restrictions
    -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
    -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
    -o smtpd_sasl_type=dovecot
    -o smtpd_sasl_path=private/auth
    # -o content_filter=smtp-amavis:[127.0.0.1]:10026
    # -o milter_macro_daemon_name=ORIGINATING
    #
    smtps inet n – y – – smtpd
    -o syslog_name=postfix/smtps
    -o smtpd_tls_wrappermode=yes
    -o smtpd_sasl_auth_enable=yes
    # -o smtpd_reject_unlisted_recipient=no
    # -o smtpd_client_restrictions=$mua_client_restrictions
    # -o smtpd_helo_restrictions=$mua_helo_restrictions
    # -o smtpd_sender_restrictions=$mua_sender_restrictions
    -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
    -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
    -o smtpd_sasl_type=dovecot
    -o smtpd_sasl_path=private/auth
    # -o content_filter=smtp-amavis:[127.0.0.1]:10026
    # -o milter_macro_daemon_name=ORIGINATING
    #
    #628 inet n – y – – qmqpd
    pickup unix n – y 60 1 pickup
    cleanup unix n – y – 0 cleanup
    qmgr unix n – n 300 1 qmgr
    #qmgr unix n – n 300 1 oqmgr
    tlsmgr unix – – y 1000? 1 tlsmgr
    rewrite unix – – y – – trivial-rewrite
    bounce unix – – y – 0 bounce
    defer unix – – y – 0 bounce
    trace unix – – y – 0 bounce
    verify unix – – y – 1 verify
    flush unix n – y 1000? 0 flush
    proxymap unix – – n – – proxymap
    proxywrite unix – – n – 1 proxymap
    smtp unix – – y – – smtp
    relay unix – – y – – smtp
    -o syslog_name=postfix/$service_name
    # -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
    showq unix n – y – – showq
    error unix – – y – – error
    retry unix – – y – – error
    discard unix – – y – – discard
    local unix – n n – – local
    virtual unix – n n – – virtual
    lmtp unix – – y – – lmtp
    anvil unix – – y – 1 anvil
    scache unix – – y – 1 scache
    postlog unix-dgram n – n – 1 postlogd
    #
    # ====================================================================
    # Interfaces to non-Postfix software. Be sure to examine the manual
    # pages of the non-Postfix software to find out what options it wants.
    #
    # Many of the following services use the Postfix pipe(8) delivery
    # agent. See the pipe(8) man page for information about ${recipient}
    # and other message envelope options.
    # ====================================================================
    #
    # maildrop. See the Postfix MAILDROP_README file for details.
    # Also specify in main.cf: maildrop_destination_recipient_limit=1
    #
    maildrop unix – n n – – pipe
    flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
    #
    # ====================================================================
    #
    # Recent Cyrus versions can use the existing “lmtp” master.cf entry.
    #
    # Specify in cyrus.conf:
    # lmtp cmd=”lmtpd -a” listen=”localhost:lmtp” proto=tcp4
    #
    # Specify in main.cf one or more of the following:
    # mailbox_transport = lmtp:inet:localhost
    # virtual_transport = lmtp:inet:localhost
    #
    # ====================================================================
    #
    # Cyrus 2.1.5 (Amos Gouaux)
    # Also specify in main.cf: cyrus_destination_recipient_limit=1
    #
    #cyrus unix – n n – – pipe
    # user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
    #
    # ====================================================================
    # Old example of delivery via Cyrus.
    #
    #old-cyrus unix – n n – – pipe
    # flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
    #
    # ====================================================================
    #
    # See the Postfix UUCP_README file for configuration details.
    #
    uucp unix – n n – – pipe
    flags=Fqhu user=uucp argv=uux -r -n -z -a$sender – $nexthop!rmail ($recipient)
    #
    # Other external delivery methods.
    #
    ifmail unix – n n – – pipe
    flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
    bsmtp unix – n n – – pipe
    flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
    scalemail-backend unix – n n – 2 pipe
    flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
    mailman unix – n n – – pipe
    flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
    ${nexthop} ${user}

    policyd-spf unix – n n – 0 spawn
    user=policyd-spf argv=/usr/bin/policyd-spf

    smtp-amavis unix – – n – 4 smtp
    -o syslog_name=postfix/amavis
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20
    -o smtp_tls_security_level=none

    127.0.0.1:10025 inet n – n – – smtpd
    -o syslog_name=postfix/10025
    -o content_filter=
    -o mynetworks_style=host
    -o mynetworks=127.0.0.0/8
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o strict_rfc821_envelopes=yes
    -o smtp_tls_security_level=none
    -o smtpd_tls_security_level=none
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_end_of_data_restrictions=
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings

  • Hi, I’ve been using this setup for a while and it has worked fine. However, the clamav-daemon stopped working for some reason and I can’t figure out why. When I check the status I get – “clamav-daemon.service: Failed with result ‘signal’.”.

  • David E.
    3 years ago

    Ran into some curious perl errors with

    /etc/amavis/conf.d/05-node_id

    and

    /etc/amavis/conf.d/15-content_filter_mode

    . In order for perl to not throw an error regarding the constant nature, I had to use a fat carrot, >, in order to get the commands to work.

    $myhostname => "mail.linuxbabe.com";

    and

    @bypass_virus_checks_maps => (
                 \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
  • Hi, i have follow this setup and it works! I have a little problem; on maillog log i receive Passed CLEAN {RelayedOpenRelay}. i use ubuntu 20.04.

    Thanks for support

    • Xiao Guoan (Admin)
      3 years ago

      This is not an error. Your Postfix SMTP server does not become an open relay.

      Postfix passes incoming emails to Amavis, which scans the email for a potential virus, then it returns the email back to Postfix, all done via the SMTP protocol. So in terms of the SMTP protocol, Amavis is an open relay for the Postfix SMTP server. It’s not an open relay for outside SMTP servers.

  • Hi,
    Thank you for the guide, I followed it to the t and everything works well.
    I’m using it on ubuntu 20.04 to send mail out to roughly 10k members at a time through back-end script. All mails are unique and personalized for each member, how to stop Amavis from scanning outgoing mails in this case ?

  • Robi Erwin Setiawan
    3 years ago

    Should we update Clamav to the newest version? or Just installed and update only the virus database?

    • Xiao Guoan (Admin)
      3 years ago

      It will be fine to update only the virus database.

  • Sergio Jara
    3 years ago

    Hello, I am getting *UNCHECKED* on my emails and after looking further into it it seems that my emails are not getting scanned due to some failure I can’t figure out.

    How do I fix this UNCHECKED issue?

    • Xiao Guoan (Admin)
      3 years ago

      Increase your server RAM, so clamav-daemon won’t be killed due to out-of-memory.

      • Sergio Jara
        3 years ago

        I have 8GB of RAM available. I believe it’s bigger than that. Last time I checked I couldn’t find clamd process which I think is needed for this to work.

        Is there a log we can look at for more clarity?

      • Sergio Jara
        3 years ago

        Running “systemctl status amavis” shows that amavis is active and running but has errors saying it can’t connect to the clamd.ctl

    • Xiao Guoan (Admin)
      3 years ago

      Check the status of clamav-daemon.

      systemctl status clamav-daemon

      If it’s not running, start it.

      sudo systemctl enable clamav-daemon --now

      If it doesn’t start, check the log to debug.

      sudo journalctl -eu clamav-daemon
      • Sergio Jara
        3 years ago

        Checking the status of clamav-daemon shows that the service is inactive. Restarting it does nothing.

        • Sergio Jara
          3 years ago

          Running:

          sudo journalctl -eu amavis

          outputs:

          Jul 27 23:33:32 email amavis[6472]: (06472-01) (!)connect to /var/run/clamav/clamd.ctl failed, attempt #1: Can't connect
          Jul 27 23:33:33 email amavis[6472]: (06472-01) (!)connect to /var/run/clamav/clamd.ctl failed, attempt #1: Can't connect
          Jul 27 23:33:33 email amavis[6472]: (06472-01) (!)ClamAV-clamd: All attempts (1) failed connecting to /var/run/clamav/cl
          Jul 27 23:33:39 email amavis[6472]: (06472-01) (!)connect to /var/run/clamav/clamd.ctl failed, attempt #1: Can't connect
          Jul 27 23:33:39 email amavis[6472]: (06472-01) (!)ClamAV-clamd av-scanner FAILED: run_av error: Too many retries to talk
          Jul 27 23:33:39 email amavis[6472]: (06472-01) (!)WARN: all primary virus scanners failed, considering backups
          Jul 27 23:33:57 email amavis[6472]: (06472-01) Passed CLEAN {RelayedOpenRelay}, ORIGINATING [127.0.0.1]:38842 
    • Xiao Guoan (Admin)
      3 years ago

      It’s

       sudo journalctl -eu clamav-daemon

      not

      sudo journalctl -eu amavis
      • Sergio Jara
        3 years ago

        For that command there doesn’t seem to be any errors but a few days ago it logged the following:

        Jul 23 11:54:58 email clamd[7991]: Fri Jul 23 11:54:58 2021 -> SelfCheck: Database status OK.
        Jul 23 12:44:42 email systemd[1]: Stopping Clam AntiVirus userspace daemon...
        Jul 23 12:44:44 email clamd[7991]: Fri Jul 23 12:44:44 2021 -> --- Stopped at Fri Jul 23 12:44:44 2021
        Jul 23 12:44:44 email clamd[7991]: Fri Jul 23 12:44:44 2021 -> Socket file removed.
        Jul 23 12:44:44 email systemd[1]: Stopped Clam AntiVirus userspace daemon.
    • Xiao Guoan (Admin)
      3 years ago

      Start clamav-daemon.

      sudo systemctl enable clamav-daemon --now

      Check its status.

      systemctl status clamav-daemon

      If it doesn’t start, check the log to debug.

      sudo journalctl -eu clamav-daemon

      Note that it’s clamav-daemon, not amavis.

      • Sergio Jara
        3 years ago

        These are my results.

        email@email:~$ sudo systemctl enable clamav-daemon --now
        [sudo] password for email:
        Synchronizing state of clamav-daemon.service with SysV service script with /lib/systemd/systemd-sysv-install.
        Executing: /lib/systemd/systemd-sysv-install enable clamav-daemon
        email@email:~$ systemctl status clamav-daemon
        ● clamav-daemon.service - Clam AntiVirus userspace daemon
           Loaded: loaded (/lib/systemd/system/clamav-daemon.service; enabled; vendor preset: enabled)
          Drop-In: /etc/systemd/system/clamav-daemon.service.d
                   └─extend.conf
           Active: inactive (dead)
        Condition: start condition failed at Wed 2021-07-28 18:40:21 EDT; 11s ago
                   └─ ConditionPathExistsGlob=/usr/local/share/clamav/daily.{c[vl]d,inc} was not met
             Docs: man:clamd(8)
                   man:clamd.conf(5)
                   https://www.clamav.net/documents/
        email@email:~$ sudo journalctl -eu clamav-daemon
        ...
        Jul 23 09:54:58 email clamd[7991]: Fri Jul 23 09:54:58 2021 -> SelfCheck: Database status OK.
        Jul 23 10:54:58 email clamd[7991]: Fri Jul 23 10:54:58 2021 -> SelfCheck: Database status OK.
        Jul 23 11:54:58 email clamd[7991]: Fri Jul 23 11:54:58 2021 -> SelfCheck: Database status OK.
        Jul 23 12:44:42 email systemd[1]: Stopping Clam AntiVirus userspace daemon...
        Jul 23 12:44:44 email clamd[7991]: Fri Jul 23 12:44:44 2021 -> --- Stopped at Fri Jul 23 12:44:44 2021
        Jul 23 12:44:44 email clamd[7991]: Fri Jul 23 12:44:44 2021 -> Socket file removed.
        Jul 23 12:44:44 email systemd[1]: Stopped Clam AntiVirus userspace daemon.
        email@email:~$
    • Xiao Guoan (Admin)
      3 years ago

      Restart clamav-freshclam

      sudo systemctl restart clamav-freshclam

      Wait a few minutes, then restart clamav-daemon

      sudo systemctl restart clamav-daemon
    • Xiao Guoan (Admin)
      3 years ago

      Always check the status and log after trying to restart the service.

      systemctl status clamav-daemon
      
      sudo journalctl -eu clamav-daemon
      
      systemctl status clamav-freshclam
      
      sudo journalctl -eu clamav-freshclam
      
      
  • Sergio Jara
    3 years ago

    Have everything working. Amavis resorts to the second virus scanner, backup, to run the scan but it still works. I can’t seem to fix the sock problem I’m getting when it tries to use clamd.

  • Hi,
    >However, it’s a good practice to use a different port such as 10026 for email submissions from authenticated users.

    why is it good practice? 🙂

    • Xiao Guoan (Admin)
      2 years ago

      Because authenticated users are your own users and you can set different rules for them.

  • Hi, just to mention a little typo in step 4

    After the line ‘sudo nano /etc/postfix/master.cf’, the end of the following paragraph refers to main.cf

  • My bad

  • Not a good idea to skip spam filtering for your own mails (newsletters or not), if they are recognized as spam they won`t reach anyone anyways and your server is going on blacklists (public or inhouse) and/or reputation is down the drain.
    Also if your account is “hacked”, credentials stolen, trojan etc. your server would send out millions of spam messages.

  • Bjorn Stronginthearm
    2 years ago

    To add: it took me today quite some time to notice, that in this configuration Spamassissin will ignore everything you do in /etc/spamassassin and you can only use the $sa_* options in /etc/amavis/conf.d/. That’s really counter-intuitive.

  • Another big thanks for your excellent how-to’s.
    In another comment, I suggested linking from the DMARC setup how-to to the DMARC how-to to this article.
    From this article, I would suggest following from here onto the Roundcubemail how-to at
    https://www.linuxbabe.com/ubuntu/install-roundcube-webmail-ubuntu-20-04-apache-nginx

    Last time I followed your how-to series for mail servers was about a year ago, and your instructions were great. This time, you’ve improved them even further (you updated the Postfixadmin installation with important steps fixing a problem people were encountering with permissions for access to the Letsencrypt certificates). After a server hardware and messing up my RAID1 recovery, I had to do a total reinstallation.

    Maybe you could do an article on how to properly set up a RAID1 (2 disks) and ESSENTIALLY how to recover and restore RAID1 after a disk loss?

    In any case, thanks for your great work. 🙂

    • Sorry for my typos above : “server hardware failure and messing up my RAID1 recovery” and “DMARC setup how-to to this Amavis/Clamav/Spamassassin how-to”

  • Duffman
    2 years ago

    A+ Instructions!!!!

    Thank you LinuxBabe!!!

    The best Linux Instructions on the internet!!!

  • Hi,
    I followed 1st step to install amavisd-new but its service stops immediately after restarted. I searched from the internet to get a solution by adding a line $inet_socket_bind = ‘127.0.0.1’; to a file at /etc/amavis/conf.d/99-warden. Then everything works fine. What is that? Besides adding a new file 99-warden, which existing configuration file can be set for the same result? I’m using Ubuntu 22.04 LTS.
    Thanks

  • LinuxBabe, you ROCK!

    I just built my first full-featured email server! I started with parts 1-3 of the guide, then went over configuring an SMTP (and HTTP/S) proxy via HAProxy, then added the email server to the VPS VPN network via WireGuard, and continued with the rest of the 14-part guide. I’m amazed at how well you put it together, explaining every piece along the way!

    My one hiccup now is getting ClamAV to work with Amavis-new. I do not see the X-Virus-Scan header nor anything in any logs indicating any attachments scanned. systemctl status amavis returns the following:

    # systemctl status amavis
    ● amavis.service - Interface between MTA and virus scanner/content filters
         Loaded: loaded (/lib/systemd/system/amavis.service; enabled; vendor preset: enabled)
         Active: active (running) since Tue 2022-09-27 17:47:58 EDT; 2h 31min ago
           Docs: http://www.ijs.si/software/amavisd/#doc
       Main PID: 9103 (/usr/sbin/amavi)
          Tasks: 3 (limit: 77136)
         Memory: 220.4M
            CPU: 5.454s
         CGroup: /system.slice/amavis.service
                 ├─9103 /usr/sbin/amavisd-new (master)
                 ├─9123 /usr/sbin/amavisd-new (ch1-avail)
                 └─9124 /usr/sbin/amavisd-new (ch1-avail)
    
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: perl=5.034000, user=124, EUID: 124 (124);  group=, EGID: 131 131 (131 131)
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: Net::Server: Group Not Defined.  Defaulting to EGID 131 131
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: Net::Server: User Not Defined.  Defaulting to EUID 124
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No ext program for   .zoo, tried: zoo
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No ext program for   .doc, tried: ripole
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No decoder for       .F
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No decoder for       .doc
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No decoder for       .zoo

    And journalctl -eu amavis outputs:

    Sep 27 17:47:57 mail.mydomain.com systemd[1]: amavis.service: Deactivated successfully.
    Sep 27 17:47:57 mail.mydomain.com systemd[1]: Stopped Interface between MTA and virus scanner/content filters.
    Sep 27 17:47:57 mail.mydomain.com systemd[1]: amavis.service: Consumed 5.202s CPU time.
    Sep 27 17:47:57 mail.mydomain.com systemd[1]: Starting Interface between MTA and virus scanner/content filters...
    Sep 27 17:47:58 mail.mydomain.com systemd[1]: Started Interface between MTA and virus scanner/content filters.
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: starting. /usr/sbin/amavisd-new at mail.mpwardenterprises.com amavisd-new-2.12.2 (20211013), Unicode aware, LANG="en_US.UTF-8"
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: perl=5.034000, user=124, EUID: 124 (124);  group=, EGID: 131 131 (131 131)
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: Net::Server: Group Not Defined.  Defaulting to EGID '131 131'
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: Net::Server: User Not Defined.  Defaulting to EUID '124'
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No ext program for   .zoo, tried: zoo
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No ext program for   .doc, tried: ripole
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No decoder for       .F
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No decoder for       .doc
    Sep 27 17:48:00 mail.mydomain.com amavis[9103]: No decoder for       .zoo

    This isn’t close to the output expected at the end of Step 3 above. Any idea on where to go from here?

  • Kindly disregard my last post. I went back over things and found my error. I wound up uncommenting the spam scan rather than the virus scan in /etc/amavis/conf.d/15-content_filter_mode.

    However, I am now experiencing an issue with an incoming email failing DMARC/DKIM, which gets rejected.

    I am trying to enable Mailvelope for PGP encryption in Roundcube. When I have the sync email sent, my server rejects/bounces it.

    Here is the output of /var/log/mail.log:

    Sep 28 09:11:39 mail postfix/2525/postscreen[22546]: PASS NEW [54.240.4.13]:40309
    Sep 28 09:11:41 mail postfix/smtpd[22552]: connect from a4-13.smtp-out.eu-west-1.amazonses.com[54.240.4.13]
    Sep 28 09:11:41 mail postfix/smtpd[22552]: Anonymous TLS connection established from a4-13.smtp-out.eu-west-1.amazonses.com[54.240.4.13]: TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)
    Sep 28 09:11:42 mail policyd-spf[22555]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=54.240.4.13; helo=a4-13.smtp-out.eu-west-1.amazonses.com; envelope-from=0102018384396659-90ff021c-7a5f-463d-bc15-7febab265b1d-000000@eu-west-1.amazonses.com; receiver= 
    Sep 28 09:11:42 mail postgrey[18592]: action=pass, reason=client whitelist, client_name=a4-13.smtp-out.eu-west-1.amazonses.com, client_address=54.240.4.13/32, sender=0102018384396659-90ff021c-7a5f-463d-bc15-7febab265b1d-000000@eu-west-1.amazonses.com, [email protected]
    Sep 28 09:11:42 mail postgrey[18592]: cleaning up old logs...
    Sep 28 09:11:44 mail postfix/smtpd[22552]: 9654E5E0FA7: client=a4-13.smtp-out.eu-west-1.amazonses.com[54.240.4.13]
    Sep 28 09:11:44 mail postfix/cleanup[22556]: 9654E5E0FA7: message-id=
    Sep 28 09:11:44 mail opendkim[18827]: 9654E5E0FA7: a4-13.smtp-out.eu-west-1.amazonses.com [54.240.4.13] not internal
    Sep 28 09:11:44 mail opendkim[18827]: 9654E5E0FA7: not authenticated
    Sep 28 09:11:45 mail opendkim[18827]: 9654E5E0FA7: message has signatures from mailvelope.com, amazonses.com
    Sep 28 09:11:45 mail opendkim[18827]: 9654E5E0FA7: DKIM verification successful
    Sep 28 09:11:45 mail opendkim[18827]: 9654E5E0FA7: s=gsccgzjp2fmfu5acbnu3m5o32pzrjcqc d=mailvelope.com a=rsa-sha256 SSL 
    Sep 28 09:11:45 mail opendmarc[18825]: implicit authentication service: mail.mydomain.com
    Sep 28 09:11:45 mail opendmarc[18825]: 9654E5E0FA7: mailvelope.com pass
    Sep 28 09:11:45 mail spamd[20799]: spamd: connection from ::1 [::1]:58696 to port 783, fd 5
    Sep 28 09:11:45 mail spamd[20799]: spamd: using default config for [email protected]: /var/vmail/mydomain.com/user/spamassassin/user_prefs
    Sep 28 09:11:45 mail spamd[20799]: spamd: processing message  for [email protected]:2000
    Sep 28 09:11:51 mail spamd[20799]: spamd: clean message (0.1/5.0) for [email protected]:2000 in 6.0 seconds, 4258 bytes.
    Sep 28 09:11:51 mail spamd[20799]: spamd: result: . 0 - DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_NONE,SPF_PASS scantime=6.0,size=4258,[email protected],uid=2000,required_score=5.0,rhost=::1,raddr=::1,rport=58696,mid=,autolearn=ham autolearn_force=no
    Sep 28 09:11:51 mail postfix/qmgr[18816]: 9654E5E0FA7: from=, size=3566, nrcpt=1 (queue active)
    Sep 28 09:11:51 mail spamd[20781]: prefork: child states: II
    Sep 28 09:11:51 mail postfix/10025/smtpd[22561]: connect from mail.mydomain.com[127.0.0.1]
    Sep 28 09:11:51 mail postfix/10025/smtpd[22561]: 768E55E0FAA: client=mail.mydomain.com[127.0.0.1]
    Sep 28 09:11:51 mail postfix/cleanup[22556]: 768E55E0FAA: message-id=
    Sep 28 09:11:51 mail opendkim[18827]: 768E55E0FAA: no signing table match for '[email protected]'
    Sep 28 09:11:51 mail opendkim[18827]: 768E55E0FAA: message has signatures from mailvelope.com, amazonses.com
    Sep 28 09:11:51 mail opendkim[18827]: 768E55E0FAA: s=gsccgzjp2fmfu5acbnu3m5o32pzrjcqc d=mailvelope.com a=rsa-sha256 SSL error:02000068:rsa routines::bad signature
    Sep 28 09:11:51 mail opendkim[18827]: 768E55E0FAA: bad signature data
    Sep 28 09:11:51 mail opendmarc[18825]: implicit authentication service: mail.mydomain.com
    Sep 28 09:11:51 mail opendmarc[18825]: 768E55E0FAA: mailvelope.com fail
    Sep 28 09:11:51 mail postfix/cleanup[22556]: 768E55E0FAA: milter-reject: END-OF-MESSAGE from mail.mydomain.com[127.0.0.1]: 5.7.1 rejected by DMARC policy for mailvelope.com; from= to= proto=ESMTP helo=
    Sep 28 09:11:51 mail amavis[20798]: (20798-01) Negative SMTP response to data-dot (): 550 5.7.1 rejected by DMARC policy for mailvelope.com, dt: 22.8 ms
    Sep 28 09:11:51 mail postfix/10025/smtpd[22561]: disconnect from mail.mydomain.com[127.0.0.1] ehlo=1 mail=1 rcpt=1 data=0/1 commands=3/4
    Sep 28 09:11:51 mail amavis[20798]: (20798-01) (!)HFTRi5srJavY FWD from  -> , BODY=7BIT 550 5.7.1 from MTA(smtp:[127.0.0.1]:10025): 550 5.7.1 rejected by DMARC policy for mailvelope.com
    Sep 28 09:11:51 mail amavis[20798]: (20798-01) Blocked MTA-BLOCKED {RejectedInbound}, [54.240.4.13]:40309 [54.240.4.13]  -> , Queue-ID: 9654E5E0FA7, Message-ID: , mail_id: HFTRi5srJavY, Hits: -, size: 4053, dkim_sd=gsccgzjp2fmfu5acbnu3m5o32pzrjcqc:mailvelope.com,ihchhvubuqgjsxyuhssfvqohv7z3u4hn:amazonses.com, 260 ms
    Sep 28 09:11:51 mail postfix/amavis/smtp[22558]: 9654E5E0FA7: to=, relay=127.0.0.1[127.0.0.1]:10024, delay=9.2, delays=8.9/0.01/0.01/0.26, dsn=5.7.1, status=bounced (host 127.0.0.1[127.0.0.1] said: 550 5.7.1 id=20798-01 - Rejected by next-hop MTA on relaying, from MTA(smtp:[127.0.0.1]:10025): 550 5.7.1 rejected by DMARC policy for mailvelope.com (in reply to end of DATA command))
    Sep 28 09:11:51 mail postfix/cleanup[22556]: 86EB15E0FAB: message-id=
    Sep 28 09:11:51 mail postfix/bounce[22562]: 9654E5E0FA7: sender non-delivery notification: 86EB15E0FAB
    Sep 28 09:11:51 mail postfix/qmgr[18816]: 86EB15E0FAB: from=, size=6844, nrcpt=1 (queue active)
    Sep 28 09:11:51 mail postfix/qmgr[18816]: 9654E5E0FA7: removed
    Sep 28 09:11:53 mail postfix/smtp[22563]: Untrusted TLS connection established to feedback-smtp.eu-west-1.amazonses.com[18.200.42.95]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
    Sep 28 09:11:53 mail postfix/smtp[22563]: 86EB15E0FAB: to=, relay=feedback-smtp.eu-west-1.amazonses.com[18.200.42.95]:25, delay=2.4, delays=0.02/0.02/1.6/0.73, dsn=2.0.0, status=sent (250 Ok woD2cM1sFl13EtaNvXPV-1)
    Sep 28 09:11:53 mail postfix/qmgr[18816]: 86EB15E0FAB: removed
    Sep 28 09:12:13 mail postfix/smtpd[22552]: disconnect from a4-13.smtp-out.eu-west-1.amazonses.com[54.240.4.13] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
    

    At first, postgrey greylisted/rejected it, but adding mailvelope.com and amazonses.com to /etc/postgrey/whitelist_clients seems to have resolved that part. I added the above domains, preceded by a ., and their IPs to /etc/opendkim/trusted.hosts, to no avail. Any guidance on getting this email through the filters would be greatly appreciated!

    And also another issue I noticed in Roundcube is in Settings > Identities > Click on any identity, and a red banner loads to the right saying: SERVER ERROR! Error No. [600]

    I know the secondary issue is unrelated, but I can’t find anything on the topic and thought you might’ve run into it at some point. Cheers! Your work is AMAZING!

    • Kevin Turner
      4 months ago

      > I wound up uncommenting the spam scan rather than the virus scan in /etc/amavis/conf.d/15-content_filter_mode.

      DITTO!! :O

      I am glad I saw this comment.

  • :::UPDATE:::

    IT WORKS!!!

    After hours of racking my brain and trying various solutions for whitelisting, I got it to work!

    The PGP and Identity issue (Server Error 600) was related to not having a home directory defined in the Enigma plugin conf file. As soon as I created a directory, gave it permissions, and defined it, everything started to work as intended!

    Again, many thanks for such an amazing guide! I learned SO much about email deliverability in the process! And now I know exactly how my system functions, so future maintenance will be a breeze! I’ll be sending a few coffees your way, for sure! Many many kudos to you!

  • at step 3 there is no ClamAV in the amavis operation log.
    Both daemons are up and running on the server.
    I did everything according to the instructions.
    operation log files have no errors.

    • Steffen Mutter
      1 year ago

      To check if it’s working you may take a peek in an email, you send to you. If you see something like:

      X-Virus-Scanned: Debian amavisd-new at whatever.yourdomainlooks.like

      everything works fine.
      If you are interested in logs you should add some logging to your clamav configuration, it does not log to a file by default.

  • Jürgen
    1 year ago

    Thank you for your tutorial! Everything works fine in my configuration but let me ask two questions.

    1. You have written: “You need to create an email address [email protected] to receive virus alerts from ClamAV.”
    I have done this and do not receive any E-Mail from or to this account. I suppose I have to konfigure ClamAV to use this account. Can you please tell me how and where?

    2. I found in the source of incoming but also outging E-Mails the line “X-Virus-Scanned: Debian amavisd-new at [my server]” as expected. Can I also have a 2nd line saying something like clean, infected passed or similar information? If yes, how to achive this?

    However let my record my thanks for your outstanding tutorial. Kind regards Jürgen

  • Steffen Mutter
    1 year ago
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings

    in master.cf is the tag no_address_mappings not a good idea, if you use something like canonical or virtual_alias_maps in your main.cf
    You will run in bounce mails instantly:

    cat /var/log/mail.log | grep bounce | grep postmaster

    which returned something like that:
    <preDec 18 07:25:15 styx2 postfix/lmtp[23389]: 80EB4202983: to=, relay=127.0.0.1[127.0.0.1]:24, delay=0.09, delays=0.01/0/0.01/0.06, dsn=5.1.1, status=bounced (host 127.0.0.1[127.0.0.1] said: 550 5.1.1 User doesn’t exist: [email protected] (in reply to RCPT TO command))>

    It took me a couple of hours to find out what was going on there.

  • Hello,

    Many thanks for this great howto. I noted that the suggested `$policy_bank` makes amavis log this warning:

    Feb  8 16:50:03 mail amavis[1221]: (!)loading policy bank "ORIGINATING": unknown field "***Encrypted Message***"
    

    I have removed the leading ‘$’ from

    $undecipherable_subject_tag => '***Encrypted Message***',
    

    in the policy_bank definition, and the error is gone; I have also tested that the Subject is correctly set to “***Encrypted Message***” for encrypted originating messages.

    • How did you do that? If you remove the “$”, the amavis will not start anymore.

      Mar 12 14:12:14 mail amavisd-new[59013]: Error in config file "/etc/amavis/conf.d/50-user": Can't modify constant item in scalar assignment at /etc/amavis/conf.d/50-user line 28, near "'**>
      Mar 12 14:12:14 mail amavisd-new[59013]: Bareword "undecipherable_subject_tag" not allowed while "strict subs" in use at /etc/amavis/conf.d/50-user line 15.
      Mar 12 14:12:14 mail systemd[1]: amavis.service: Main process exited, code=exited, status=255/EXCEPTION
      Mar 12 14:12:14 mail systemd[1]: amavis.service: Failed with result 'exit-code'.
      Mar 12 14:12:15 mail systemd[1]: amavis.service: Scheduled restart job, restart counter is at 5.
      Mar 12 14:12:15 mail systemd[1]: Stopped Interface between MTA and virus scanner/content filters.
      Mar 12 14:12:15 mail systemd[1]: amavis.service: Start request repeated too quickly.
      Mar 12 14:12:15 mail systemd[1]: amavis.service: Failed with result 'exit-code'.
      Mar 12 14:12:15 mail systemd[1]: Failed to start Interface between MTA and virus scanner/content filters.
      Mar 12 14:14:31 mail systemd[1]: Starting Interface between MTA and virus scanner/content filters...
      Mar 12 14:14:31 mail systemd[1]: Started Interface between MTA and virus scanner/content filters.
      
  • i’m getting this error, how can I fix the main.cf

  • Gede Wijaya
    11 months ago

    I want to use antispam function only (I have setup successfully OpenDKIM, based on the tutorial from this site). But I still got twice DKIM sign entry eventhough I have set “$enable_dkim_verification = 0”. Ubuntu 22.04.2

  • René Frej Nielsen
    11 months ago

    After configuring this I get double DKIM signing. It seems like when the email is first run through the milters and is DKIM signed, then it’s forwarded to Amavis that adds it’s AV header and then it’s forwarded to Postfix again, where it’s DKIM signed once more and even checked by OpenDMARC. It’s like it sees it as external email?

    I have tried a workaround that disables milters after Amavis, but Gmail reports “body hash mismatch or not verifiable” and I suspect that it’s because the AV scan header is added after DKIM signing.

    Gmail is happy about the DKIM even with double signing, but it’s not very elegant and it also seems wrong that it’s run through OpenDMARC when it’s internal.

    I’m have followed the guides to setup a mailserver from scratch on Ubuntu 22.04. Any help would be appreciated!

    • René Frej Nielsen
      11 months ago

      I’m a newbie at this, but I have tried a couple of things, and it’s working, but I can’t tell if there are any negative side effects. It’s also not perfect. What I did was the following:

      In master.cf under “submission inet n – y – – smtpd” I added this line:
      ” -o smtpd_milters=”

      I did the same under the “smtps inet n – y – – smtpd” section. This skips milters for mails that come from email clients, but since the line ” -o content_filter=smtp-amavis:[127.0.0.1]:10026″ sends the email to Amavis, which then returns the email to Postfix, then they emails are then run through the milters, so that DKIM is applied. The result is only one DKIM header which is what I wanted.

      A downside was that Spamassasin is skipped for incoming emails for some reason, even though it’s part of the milters configuration. I fixed that by adding this to the “smtp inet n – y – – smtpd” section.

      ” -o smtpd_milters=local:spamass/spamass.sock”

      Everything works, but I think it’s a hack. Outgoing mails are still run through OpenDMARC which I think is wrong. Maybe I could add more ” -o smtpd_milters=” overrides to specific sections?

      I would still prefer to have someone with more knowledge create a more perfect solution, instead of my hacks. In the meantime I will look at the Modoba guide.

  • ksotiris
    10 months ago

    Thank you for this useful guide. I have problem with amavisd-new and clamav .

    Not working with THE SAME ERROR log on every incoming email:

    mail amavis[32631]: (32631-01) (!)run_av (ClamAV-clamd) FAILED – unexpected , output=”/var/lib/amavis/tmp/amavis-20230417T222358-32631-IXqH2_nL/parts: Excluded\n”
    mail amavis[32631]: (32631-01) (!)ClamAV-clamd av-scanner FAILED: CODE(0x56318fa2dad8) unexpected , output=”/var/lib/amavis/tmp/amavis-20230417T222358-32631-IXqH2_nL/parts: Excluded\n” at (eval 101) line 951.
    mail amavis[32631]: (32631-01) (!)WARN: all primary virus scanners failed, considering backups

    I use
    $> cat /etc/debian_version
    10.13

    $> amavisd-new -V
    amavisd-new-2.11.0 (20160426)

    $> clamd -V
    ClamAV 0.103.8/26878/Mon Apr 17 10:23:32 2023

    it ‘s the same error always. I did all checks as described bellow:
    1. I re-check all installation steps of your guide.
    2. I added amavis user to clamav group
    $> id amavis
    uid=127(amavis) gid=133(amavis) groups=133(amavis),134(clamav)
    and added clamav to amavis gorup

    $> id clamav
    uid=128(clamav) gid=134(clamav) groups=134(clamav),133(amavis)

    3. I check /etc/clamav/clamd.conf
    LocalSocket /var/run/clamav/clamd.ctl
    FixStaleSocket true
    LocalSocketGroup clamav
    LocalSocketMode 777
    # TemporaryDirectory is not set to its default /tmp here to make overriding
    # the default with environment variables TMPDIR/TMP/TEMP possible
    User clamav

    4. /etc/amavis/conf.d/15-av_scanners
    [‘ClamAV-clamd’,
    \&ask_daemon, [“CONTSCAN {}\n”, “/var/run/clamav/clamd.ctl”],
    qr/\bOK$/m, qr/\bFOUND$/m,
    qr/^.*?: (?!Infected Archive)(.*) FOUND$/m ],

    and googling a lot but nothing …

    can you help me ?
    Thanks in advance.

  • Wayne Spivak
    10 months ago

    I’m using PHPList and don’t want a 15K address list to be virus checked.

    I changed the master.cf on Postfix as stipulated above.

    I changed this section of PHPList config.php to:

    define('PHPMAILERHOST', '127.0.0.1');
    define('PHPMAILERPORT',2525);
    define('PHPMAILER_SECURE',true);
    

    I even tried PHPMAILER_SECURE, false without success.

    Any ideas?

  • Wayne Spivak
    10 months ago

    Adding the maillog shows

    When true is used:

    pr 25 06:31:50 mcq postfix/2525/smtpd[13272]: connect from localhost[127.0.0.1]
    Apr 25 06:31:50 mcq postfix/2525/smtpd[13272]: Anonymous TLS connection established from localhost[127.0.0.1]: TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
    Apr 25 06:31:50 mcq postfix/2525/smtpd[13272]: lost connection after STARTTLS from localhost[127.0.0.1]
    Apr 25 06:31:50 mcq postfix/2525/smtpd[13272]: disconnect from localhost[127.0.0.1] ehlo=1 starttls=1 commands=2
    Apr 25 06:31:50 mcq opendmarc[11855]: ignoring connection from localhost
    

    when false is used

    Apr 25 06:33:15 mcq postfix/2525/smtpd[13272]: connect from localhost[127.0.0.1]
    Apr 25 06:33:15 mcq postfix/2525/smtpd[13272]: disconnect from localhost[127.0.0.1] ehlo=1 quit=1 commands=2
    Apr 25 06:33:15 mcq opendmarc[11855]: ignoring connection from localhost
    
  • How would you go with “Step 4: Use A Dedicated Port for Email Submissions” if submission is already managed by dovecot?

    I have that submission section commented in postfix configuration.

  • Rob Watson
    3 mins ago

    I can’t seem to get both policyd-spy-python and postgrey to both log to mail.log. I have also tried the spf perl version. I have proper settings in rsyslog to forward to mail.log for both programs yet once I get one to finally log, the other won’t. I do see it in journald logs however. I been trying to solve this for days on end. I use monitorix to graph and want to see all the graphs working. Currently only spf is logging.

    Debiab 12 bookworm
    Postfix 3.7.10
    Postgrey 1.37

    I have tried different positions for spf entry to no avail.
    #### main.cf ####
    smtpd_recipient_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    check_policy_service unix:private/policyd-spf,
    check_policy_service inet:127.0.0.1:10023,
    reject_invalid_hostname,
    reject_unknown_recipient_domain,
    reject_non_fqdn_hostname,
    reject_non_fqdn_sender,
    reject_non_fqdn_recipient,
    reject_unknown_sender_domain,
    reject_rhsbl_helo dbl.spamhaus.org,
    reject_rhsbl_reverse_client dbl.spamhaus.org,
    reject_rhsbl_sender dbl.spamhaus.org,
    permit_dnswl_client list.dnswl.org=127.0.[0..255].[1..3],
    reject_rbl_client sbl.spamhaus.org,
    reject_rbl_client zen.spamhaus.org,
    reject_rbl_client cbl.abuseat.org,
    policyd-spf_time_limit = 3600

    #POSTGREY_OPTS=”–inet=10023″
    POSTGREY_OPTS=”–inet=127.0.0.1:10023 –syslog-facility=mail –delay=60 –verbose –x-greylist-header=delayed %t seconds by postgrey-%v at %h; %d”
    # the –greylist-text commandline argument can not be easily passed through
    # POSTGREY_OPTS when it contains spaces. So, insert your text here:
    POSTGREY_TEXT=”Greylisted, Temporary rejection, please try again later. This is a greylisting measure to protect against spam. Your email will be accepted after a short delay. Thank you for your understanding”

    • Rob Watson
      4 seconds ago

      the last comma was removed reject_rbl_client cbl.abuseat.org,

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here