Prevent spam problem with Zimbra server

From Notes_Wiki

Home > CentOS > CentOS 6.x > Zimbra server configuration > Prevent spam problem with Zimbra server

For incoming spam related refer more up-to-date CentOS 7.x Configure or optimize new Zimbra installation article

Often Zimbra server is used as relay to send bulk SPAM messages. This can be done if at least one of the accounts on server is compromised. An attacker can use compromised account to login into SMTP server over SSL/TLS and then send SPAM messages. These spam messages can be sent from any email address to any other email address. Thus, detecting which accounts have been compromised is tricky.

Analyze log file to detect compromised account

One very quick way of detecting the attack source and also compromised login is to analyze /var/log/zimbra.log file. Use steps suggested at Get count of IP addresses in a log file arranged in descending order of frequency to get IPs which are contacting Zimbra server to often. Some of these IPs could belong to attacker and others would belong to popular email servers such as Gmail, Yahoo, etc. which the compromised server might be contacting to send SPAM. For first 10-20 top IPs use following command to see name of user logged in:

grep '<public-ip>' zimbra.log | grep 'sasl_user' | head -15

If there is no output then perhaps the IP belongs to Google, Yahoo, etc. popular destinations. This can be verified by using<public-IP> facility to determine owner of particular IP.

If the output contains name of user authenticated and there is no good reason for one single user to send that many emails then perhaps the listed account is compromised. Such compromised accounts can be disabled or their password can be reset to prevent further abuse. This should be done for all top IPs as more than one account might have been compromised.

Note that attackers send multiple phising emails to all users on the same domain hoping that some of them would also reply with their password. This causes multiple accounts to get compromised in short time.

Enable sender policy to ensure that login user name matches from address in email

Enabling sender policy to ensure that login user name matches from address in email in Zimbra 8.0 series

To enable sender policy to for preventing abuse in Zimbra 8.0 use following steps:

  1. Edit file '/opt/zimbra/conf/' and append line
    POSTCONF smtpd_sender_login_maps FILE
    This line must be appended immediately after line 'POSTCONF smtpd_sender_restrictions FILE zmconfigd/'
    Please ensure that there is tab at beginning of new appended line
  2. Edit file '/opt/zimbra/conf/zmconfigd/' and insert following line at top of the file
  3. Edit/create file '/opt/zimbra/conf/' with following contents:
    hash:/opt/zimbra/conf/exceptions-db ldap:/opt/zimbra/conf/
  4. Create file '/opt/zimbra/conf/exceptions-db' with email ID and username pairs where given user can send emails with listed email address admin admin
  5. Create db file by using:
    cd /opt/zimbra/conf
    /opt/zimbra/postfix/sbin/postmap exceptions-db
    Thist must be done everytime '/opt/zimbra/conf/exceptions-db' file is modified for changes to take effect. Just running postmap is enough and there is no need to reload/restart Zimbra for new settings to take effect
  6. Get values of 'server_host' and 'bind_pw' using:
    grep server_host /opt/zimbra/conf/
    grep bind_pw /opt/zimbra/conf/
  7. Edit/create file '/opt/zimbra/conf/' with following contents:
    server_host = ldap://
    server_port = 389
    search_base =
    query_filter = (&(|(uid=%s)(zimbraMailDeliveryAddress=%s)(zimbraMailAlias=%s)(zimbraMailCatchAllAddress=%s))(zimbraMailStatus=enabled))
    result_attribute = uid,zimbraMailDeliveryAddress,zimbraMailForwardingAddress,zimbraPrefMailForwardingAddress,zimbraMailCatchAllForwardingAddress
    version = 3
    start_tls = yes
    tls_ca_cert_dir = /opt/zimbra/conf/ca
    bind = yes
    bind_dn = uid=zmpostfix,cn=appaccts,cn=zimbra
    bind_pw = XXXXXXXXXX
    timeout = 30
    Here replace server_host and bind_pw with values found in previous step. Note that if you are using external LDAP for authentication then values in server_host, server_port, search_base, bind_dn, bind_pw, etc. should reflect external LDAP server values and not values found in previous step.
  8. Set correct permissions on all new files using:
    cd /opt/zimbra/conf
    chown zimbra: postfix_sender_* exceptions-db*
  9. Run following command as Zimbra user for new settings to take effect
    zmmtactl restart

These steps have been learned from

Enabling sender policy to ensure that login user name matches from address in email in Zimbra 8.5 series


Troubleshooting sender policy configured

If sender policy configured is not working properly monitor '/var/log/zimbra.log' using tail command to see possible reasons why settings are not working.

Verifying sender policy configuration

It is important to verify sender policy configuration. Following tests are recommended

Resolving sender not allowed issues after implementing sender email and authenticated user name match

It is possible that server might not allow user 'saurabh' authenticated with username 'saurabh' to send emails from domain This can be tried to be resolved partially by authenticating with full email address '' and not just with user-name. However propagating this change to all already configured email clients / mobiles might be an issue. To work around this problem a list of all company email IDs and the corresponding usernames can be added to /opt/zimbra/conf/exceptions-db file. This would allow user 'saurabh' to send emails from based on exceptions. To achieve this use following steps:

  1. List all Zimbra users using 'zmprov -l gaa' command. A more exhaustive list which also includes all aliases can be obtained using:
    /opt/zimbra/openldap/bin/ldapsearch -LLL -x -D"`/opt/zimbra/bin/zmlocalconfig -s zimbra_ldap_userdn | \
    awk '{print $3}'`" -w"`/opt/zimbra/bin/zmlocalconfig -s zimbra_ldap_password | \
    awk '{print $3}'`" -H `/opt/zimbra/bin/zmlocalconfig ldap_url | \
    awk '{print $3}'` $* | \
    grep ^mail | \
    awk '{print $2}' | \
    sort > zimbra_recipients.list
  2. Install erlang on server using 'yum -y install erlang'
  3. Create convert.erl file with following erlang program:
    main() ->
    {ok, Data1} = file:read_file("zimra_recipients.list"),
    Email_list1=string:tokens(Data2, "\n"),
    Output_lines1=lists:map(fun(Email1) ->
    Username=hd(string:tokens(Email1, "@")),
    lists:flatten(io_lib:format("~s ~s ~s", [Email1, Username, Email1]))
    Output_data=string:join(Output_lines1, "\n"),
    file:write_file("exceptions-db", Output_data),
  4. Compile and run this program using:
    erlc convert.erl
    erl -noshell -s convert main -s init stop
  5. Replace or append the exceptions-db file created by running this program with previous exceptions-db file
  6. Run postmap again for new exceptions to take effect

More zmprov commands can be learned from Technique of exporting all email IDs including aliases learned from

smtpd_sender_login_maps are explained at

Home > CentOS > CentOS 6.x > Zimbra server configuration > Prevent spam problem with Zimbra server