Install Mail Server Exim4 on Ubuntu Server 16.04

(0 comments)

Overview

Exim is MTA - SMTP Mail server

is opensource package.

Install

we will install exim with MySQL support (mail boxes, multidomain, etc.)

Today we will install Exim v4 on Ubuntu server 16.04

before we need update upgrade all necessary packages:

$sudo apt-get update -y && apt-get upgrade -y && apt-get dist-upgrade -y

Install dovecot as imap/pop3 services:

$apt-get install dovecot-common dovecot-imapd dovecot-pop3d

Create system user  with uid = 1150, username = vmail, in group = mail:

$sudo useradd -r -u 1150 -g mail -d /var/vmail -s /sbin/nologin -c 'Virtual Mailbox' vmail

create dir for store mails and get permissions vmail user:

$sudo mkdir var/mail
$sudo chwon vmail:mail /var/mail
$sudo chmod 0770 /var/mail

Now create Database for exim:

$sudo apt-get install mysql-server

in during installation MySQL server, provide password for root (root in this case mysql server's user) not root user Operating system Ubuntu server

$mysqladmin -u root -p create exim_db
$Enter password: (Enter password)
$mysql -u root -p
mysql>GRANT ALL PRIVILEGES ON exim_db.* TO exim_user@localhost IDENTIFIED BY 'password';
mysql>Ctrl+D

we created database and user for it.

in this case user is - exim_user 

password - "password" (you can change it and remember, we will use in exim's config file later)

Create self-signed certificate

$sudo openssl req -new -x509 -days 3650 -nodes -out /etc/ssl/certs/mail.pem -keyout /etc/ssl/certs/mail.pem

Configuration Dovecot

$cat /etc/dovecot/dovecot.conf

#change domain name!!!
auth_default_realm = domain.com
auth_verbose = yes
$for temp files
base_dir = /var/run/dovecot/
disable_plaintext_auth = no
first_valid_gid = 8
first_valid_uid = 118
login_greeting = Dovecot ready
log_path = /var/log/dovecot.log
login_log_format_elements = user=<%u> method=%m rip=%r lip=%l %c
mail_access_groups = mail
mail_debug = yes
mail_location = maildir:/var/mail/%d/%n
passdb {
args = /etc/dovecot/dovecot-sql.conf
driver = sql
}
protocols = pop3 imap
service auth {
unix_listener auth-master {
mode = 0600
user = Debian-exim
}
user = root
}
service imap-login {
chroot = login
inet_listener imap {
address = *
port = 143
}
process_limit = 3
process_min_avail = 3
service_count = 1
user = dovecot
vsz_limit = 64 M
}
service pop3-login {
chroot = login
inet_listener pop3 {
address = *
port = 110
}
process_limit = 3
process_min_avail = 3
service_count = 1
user = dovecot
vsz_limit = 64 M
}
ssl = yes
ssl_cert = </etc/ssl/certs/mail.pem
ssl_key = </etc/ssl/certs/mail.pem
userdb {
args = /etc/dovecot/dovecot-sql.conf
driver = sql
}
verbose_proctitle = yes

#protocol imap {
# imap_client_workarounds = delay-newmail tb-extra-mailbox-sep
#}

protocol pop3 {
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
pop3_uidl_format = %08Xu%08Xv
}
protocol lda {
auth_socket_path = /var/run/dovecot/auth-master
postmaster_address = [email protected]
}

## Dovecot configuration file

# If you're in a hurry, see http://wiki2.dovecot.org/QuickConfiguration

# "doveconf -n" command gives a clean output of the changed settings. Use it
# instead of copy&pasting files when posting to the Dovecot mailing list.

# '#' character and everything after it is treated as comments. Extra spaces
# and tabs are ignored. If you want to use either of these explicitly, put the
# value inside quotes, eg.: key = "# char and trailing whitespace "

# Default values are shown for each setting, it's not required to uncomment
# those. These are exceptions to this though: No sections (e.g. namespace {})
# or plugin settings are added by default, they're listed only as examples.
# Paths are also just examples with the real defaults being based on configure
# options. The paths listed here are for configure --prefix=/usr
# --sysconfdir=/etc --localstatedir=/var

# Enable installed protocols
!include_try /usr/share/dovecot/protocols.d/*.protocol

# A comma separated list of IPs or hosts where to listen in for connections.
# "*" listens in all IPv4 interfaces, "::" listens in all IPv6 interfaces.
# If you want to specify non-default ports or anything more complex,
# edit conf.d/master.conf.
#listen = *, ::

# Base directory where to store runtime data.
#base_dir = /var/run/dovecot/

# Name of this instance. Used to prefix all Dovecot processes in ps output.
#instance_name = dovecot

# Greeting message for clients.
#login_greeting = Dovecot ready.

# Space separated list of trusted network ranges. Connections from these
# IPs are allowed to override their IP addresses and ports (for logging and
# for authentication checks). disable_plaintext_auth is also ignored for
# these networks. Typically you'd specify your IMAP proxy servers here.
#login_trusted_networks =

# Sepace separated list of login access check sockets (e.g. tcpwrap)
#login_access_sockets =

# Show more verbose process titles (in ps). Currently shows user name and
# IP address. Useful for seeing who are actually using the IMAP processes
# (eg. shared mailboxes or if same uid is used for multiple accounts).
#verbose_proctitle = no

# Should all processes be killed when Dovecot master process shuts down.
# Setting this to "no" means that Dovecot can be upgraded without
# forcing existing client connections to close (although that could also be
# a problem if the upgrade is e.g. because of a security fix).
#shutdown_clients = yes

# If non-zero, run mail commands via this many connections to doveadm server,
# instead of running them directly in the same process.
#doveadm_worker_count = 0
# UNIX socket or host:port used for connecting to doveadm server
#doveadm_socket_path = doveadm-server

# Space separated list of environment variables that are preserved on Dovecot
# startup and passed down to all of its child processes. You can also give
# key=value pairs to always set specific settings.
#import_environment = TZ

##
## Dictionary server settings
##

# Dictionary can be used to store key=value lists. This is used by several
# plugins. The dictionary can be accessed either directly or though a
# dictionary server. The following dict block maps dictionary names to URIs
# when the server is used. These can then be referenced using URIs in format
# "proxy::<name>".

dict {
#quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
#expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext
}

# Most of the actual configuration gets included below. The filenames are
# first sorted by their ASCII value and parsed in that order. The 00-prefixes
# in filenames are intended to make it easier to understand the ordering.
!include conf.d/*.conf

# A config file can also tried to be included without giving an error if
# it's not found:
!include_try local.conf

$ sudo cat dovecot-sql.conf  (access has only root )

# This file is opened as root, so it should be owned by root and mode 0600.
#
# http://wiki2.dovecot.org/AuthDatabase/SQL
#
# For the sql passdb module, you'll need a database with a table that
# contains fields for at least the username and password. If you want to
# use the user@domain syntax, you might want to have a separate domain
# field as well.
#
# If your users all have the same uig/gid, and have predictable home
# directories, you can use the static userdb module to generate the home
# dir based on the username and domain. In this case, you won't need fields
# for home, uid, or gid in the database.
#
# If you prefer to use the sql userdb module, you'll want to add fields
# for home, uid, and gid. Here is an example table:
#
# CREATE TABLE users (
#     username VARCHAR(128) NOT NULL,
#     domain VARCHAR(128) NOT NULL,
#     password VARCHAR(64) NOT NULL,
#     home VARCHAR(255) NOT NULL,
#     uid INTEGER NOT NULL,
#     gid INTEGER NOT NULL,
#     active CHAR(1) DEFAULT 'Y' NOT NULL
# );

# Database driver: mysql, pgsql, sqlite
driver = mysql

#here you should put ip address server and credentials for MySQL server connect=host=10.10.10.10 dbname=exim_db user=exim_user password=password default_pass_scheme=PLAIN password_query=select password from accounts where login='%n' and domain='%d' user_query=select uid, gid from accounts where login='%n' and domain='%d' # Database connection string. This is driver-specific setting. # # HA / round-robin load-balancing is supported by giving multiple host # settings, like: host=sql1.host.org host=sql2.host.org # # pgsql: # For available options, see the PostgreSQL documention for the # PQconnectdb function of libpq. # Use maxconns=n (default 5) to change how many connections Dovecot can # create to pgsql. # # mysql: # Basic options emulate PostgreSQL option names: # host, port, user, password, dbname # # But also adds some new settings: # client_flags - See MySQL manual # ssl_ca, ssl_ca_path - Set either one or both to enable SSL # ssl_cert, ssl_key - For sending client-side certificates to server # ssl_cipher - Set minimum allowed cipher security (default: HIGH) # option_file - Read options from the given file instead of # the default my.cnf location # option_group - Read options from the given group (default: client) # # You can connect to UNIX sockets by using host: host=/var/run/mysql.sock # Note that currently you can't use spaces in parameters. # # sqlite: # The path to the database file. # # Examples: # connect = host=192.168.1.1 dbname=users # connect = host=sql.example.com dbname=virtual user=virtual password=blarg # connect = /etc/dovecot/authdb.sqlite # #connect = # Default password scheme. # # List of supported schemes is in # http://wiki2.dovecot.org/Authentication/PasswordSchemes # #default_pass_scheme = MD5 # passdb query to retrieve the password. It can return fields: # password - The user's password. This field must be returned. # user - user@domain from the database. Needed with case-insensitive lookups. # username and domain - An alternative way to represent the "user" field. # # The "user" field is often necessary with case-insensitive lookups to avoid # e.g. "name" and "nAme" logins creating two different mail directories. If # your user and domain names are in separate fields, you can return "username" # and "domain" fields instead of "user". # # The query can also return other fields which have a special meaning, see # http://wiki2.dovecot.org/PasswordDatabase/ExtraFields # # Commonly used available substitutions (see http://wiki2.dovecot.org/Variables # for full list): # %u = entire user@domain # %n = user part of user@domain # %d = domain part of user@domain # # Note that these can be used only as input to SQL query. If the query outputs # any of these substitutions, they're not touched. Otherwise it would be # difficult to have eg. usernames containing '%' characters. # # Example: # password_query = SELECT userid AS user, pw AS password \ # FROM users WHERE userid = '%u' AND active = 'Y' # #password_query = \ # SELECT username, domain, password \ # FROM users WHERE username = '%n' AND domain = '%d' # userdb query to retrieve the user information. It can return fields: # uid - System UID (overrides mail_uid setting) # gid - System GID (overrides mail_gid setting) # home - Home directory # mail - Mail location (overrides mail_location setting) # # None of these are strictly required. If you use a single UID and GID, and # home or mail directory fits to a template string, you could use userdb static # instead. For a list of all fields that can be returned, see # http://wiki2.dovecot.org/UserDatabase/ExtraFields # # Examples: # user_query = SELECT home, uid, gid FROM users WHERE userid = '%u' # user_query = SELECT dir AS home, user AS uid, group AS gid FROM users where userid = '%u' # user_query = SELECT home, 501 AS uid, 501 AS gid FROM users WHERE userid = '%u' # #user_query = \ # SELECT home, uid, gid \ # FROM users WHERE username = '%n' AND domain = '%d' # If you wish to avoid two SQL lookups (passdb + userdb), you can use # userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll # also have to return userdb fields in password_query prefixed with "userdb_" # string. For example: #password_query = \ # SELECT userid AS user, password, \ # home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \ # FROM users WHERE userid = '%u' # Query to get a list of all usernames. #iterate_query = SELECT username AS user FROM users

$sudo systemctl restart dovecot.service

Configuration EXIM

Lets restore schema of database exim_db:

# cat exim_db.sql 
-- MySQL dump 10.13  Distrib 5.7.17, for Linux (x86_64)
--
-- Host: localhost    Database: exim_db
-- ------------------------------------------------------
-- Server version	5.7.17-0ubuntu0.16.04.1

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `accounts`
--

DROP TABLE IF EXISTS `accounts`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `accounts` (
  `login` varchar(128) COLLATE utf8_bin NOT NULL DEFAULT '',
  `password` varchar(128) COLLATE utf8_bin NOT NULL DEFAULT '',
  `uid` int(11) NOT NULL DEFAULT '118',
  `gid` int(11) NOT NULL DEFAULT '8',
  `domain` varchar(128) COLLATE utf8_bin NOT NULL DEFAULT 'nixtalk.com',
  `quota` varchar(16) COLLATE utf8_bin NOT NULL DEFAULT '250M',
  `status` int(11) NOT NULL DEFAULT '1',
  PRIMARY KEY (`login`,`domain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `accounts`
--

LOCK TABLES `accounts` WRITE;
/*!40000 ALTER TABLE `accounts` DISABLE KEYS */;
INSERT INTO `accounts` VALUES ('admin','password',118,8,'domain.com','250M',1);
/*!40000 ALTER TABLE `accounts` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `aliases`
--

DROP TABLE IF EXISTS `aliases`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `aliases` (
  `address` varchar(128) COLLATE utf8_bin DEFAULT NULL,
  `goto` varchar(128) COLLATE utf8_bin DEFAULT NULL,
  `domain` varchar(128) COLLATE utf8_bin DEFAULT 'nixtalk.com'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `aliases`
--

LOCK TABLES `aliases` WRITE;
/*!40000 ALTER TABLE `aliases` DISABLE KEYS */;
/*!40000 ALTER TABLE `aliases` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `blacklist`
--

DROP TABLE IF EXISTS `blacklist`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `blacklist` (
  `senders` varchar(128) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `blacklist`
--

LOCK TABLES `blacklist` WRITE;
/*!40000 ALTER TABLE `blacklist` DISABLE KEYS */;
/*!40000 ALTER TABLE `blacklist` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `domains`
--

DROP TABLE IF EXISTS `domains`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `domains` (
  `domain` varchar(128) COLLATE utf8_bin NOT NULL DEFAULT '',
  `status` int(11) NOT NULL DEFAULT '1',
  `relay` varchar(45) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`domain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `domains`
--

LOCK TABLES `domains` WRITE;
/*!40000 ALTER TABLE `domains` DISABLE KEYS */;
INSERT INTO `domains` VALUES ('domain.com',1,'l');
/*!40000 ALTER TABLE `domains` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `whitelist`
--

DROP TABLE IF EXISTS `whitelist`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `whitelist` (
  `senders` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '[email protected]'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `whitelist`
--

LOCK TABLES `whitelist` WRITE;
/*!40000 ALTER TABLE `whitelist` DISABLE KEYS */;
/*!40000 ALTER TABLE `whitelist` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2017-04-17 16:36:13

save it in file exim_db.sql (use copy/paste)

and restore in your database:

$mysql -u root -p exim_db < exim_db.sql

Add some stuff:

$mysql -u root -p
mysql>use exim_db;
#add user mail box [email protected]
mysql>INSERT into exim_db.accounts (login, password, uid, gid, domain, quota, status) VALUES('admin1', 'password', 119, 8, 'domain.com', '250M', '1');
#add domain, current - domain.com, you can add any domains
mysql>INSERT into exim_db.domains (domain, status, relay) VALUES('domain.com', 1, 'l');
Ctrl+D

$cat /etc/exim4/exim4.conf.template

#your domain name, change it!
primary_hostname = domain.com # databasename and credentials hide mysql_servers = 10.10.10.10/exim_db/exim_user/password #local_domains is all domains in your mail server, in our case we have only one domain - domain.com
domainlist local_domains = ${lookup mysql{select domain from domains where domain='${domain}' AND relay='l'}} #domains you can send mails (this server you can use as smart host for another mail server)
domainlist relay_to_domains = ${lookup mysql{select domain from domains where domain='${domain}' AND relay = 'r'}} # IP addresses from you can accept mails
hostlist relay_from_hosts = localhost : 127.0.0.1 :4.34.146.111
#white list (we use mysql) hostlist cool_senders = ${lookup mysql{SELECT ipaddr FROM whiteipaddr WHERE ipaddr='${quote_mysql:$sender_host_address}' LIMIT 1}} #black list (we use file) domainlist rbl_blacklist = lsearch;/etc/exim4/rblblacklist acl_smtp_connect = acl_check_connect acl_smtp_helo = acl_check_helo acl_smtp_rcpt = acl_check_rcpt acl_smtp_data = acl_check_data #disable_ipv6 = true #you should create self-signed certificate tls_certificate = /etc/ssl/certs/mail.pem tls_privatekey = /etc/ssl/certs/mail.pem #port smtp daemon_smtp_ports = 25: 465 tls_on_connect_ports = 465 tls_advertise_hosts = * qualify_domain = domain.com qualify_recipient = domain.com allow_domain_literals = false exim_user = Debian-exim exim_group = Debian-exim never_users = root host_lookup = * : !+relay_from_hosts rfc1413_hosts = * rfc1413_query_timeout = 0s ignore_bounce_errors_after = 2h timeout_frozen_after = 14d return_size_limit = 10K split_spool_directory = true syslog_timestamp = no smtp_accept_max = 100 smtp_accept_max_per_connection = 50 smtp_accept_max_per_host = 20 smtp_accept_queue_per_connection = 30 remote_max_parallel = 15 av_scanner = clamd:/var/run/clamav/clamd.ctl #spamassassin, you will install it later
spamd_address = 127.0.0.1 783 smtp_banner = $smtp_active_hostname ESMTP #dns_again_means_nonexist = !+local_domains : !+relay_to_domains dns_again_means_nonexist = *.in-addr.arpa # Enable HELO verification in ACLs for all hosts helo_try_verify_hosts = *: !+local_domains : !+relay_from_hosts #structure of log file log_selector = \ +all_parents \ +lost_incoming_connection \ +received_sender \ +received_recipients \ +smtp_confirmation \ +smtp_syntax_error \ +smtp_connection \ +smtp_protocol_error \ -queue_run ######### ACL ######## begin acl acl_check_connect: # deny get mail from dynamic ip addresses deny message = "Dynamic hosts is forbidden!" condition = ${if match{$sender_host_name}\ {webcam|dsl|dial|dhcp|\.cable\.|static|dynamic|ppp} {yes}{no}} #except white listed senders
# !hosts = +cool_senders !hosts = ${lookup mysql{SELECT ipaddr FROM whiteipaddr WHERE ipaddr='${quote_mysql:$sender_host_address}' LIMIT 1}} accept ######################## acl_check_helo: # deny all senders who put own IP in HELO. deny message = "The use of IP is forbidden in HELO!" hosts = !+relay_from_hosts log_message = The use of IP is forbidden in HELO! condition = ${if eq{$sender_helo_name}\ {$sender_host_address}{true}{false}} accept ######################## acl_check_rcpt: accept hosts = : #deny symbols in local part of email
deny domains = +local_domains local_parts = ^[.] : ^.*[@%!/|] deny domains = !+local_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ #deny local part 'spam'
deny domains = !+local_domains : !+relay_to_domains local_parts = spam #deny message = Rejected because $sender_fullhost is blacklisted locally # log_message = Rejected because $sender_fullhost is blacklisted locally # senders = /etc/exim4/rblblacklist deny message = Rejected because $sender or $sender_helo_name in BL db senders=${lookup mysql{SELECT senders FROM blacklist \ WHERE senders='${quote_mysql:$sender_address}' \ OR senders='*@${quote_mysql:$sender_address_domain}' LIMIT 1}} ################ WARN!!! ############### # accept emails from IP addresses in relay domains. accept hosts = +relay_from_hosts accept authenticated = *
# deny relay except relay_to_domains deny message = relay not permitted to another domain log_message = relay not permitted to another domain domains = !+relay_to_domains: !+local_domains hosts = !+relay_from_hosts deny message = Reverse DNS lookup failed for host $sender_host_address. log_message = Reverse DNS lookup failed for host $sender_host_address !verify = reverse_host_lookup deny message = Message was delivered by ratware log_message = remote host used our name in HELO/EHLO greeting. condition = ${if match_domain{$sender_helo_name}\ {$primary_hostname:+local_domains:+relay_to_domains}\ {true}{false}} # deny numbers in HELO except localhost deny condition = ${if match{$sender_helo_name}{\N^\d+$\N}{yes}{no}} log_message = There can not be only numbers in HELO hosts = !127.0.0.1:!localhost:* message = "There can not be only numbers in HELO!" # deny with no return address. deny condition = ${if eq{$sender_address}{}{yes}{no}} log_message = Your message have not return address hosts = !+relay_from_hosts message = "Your message have not return address"
deny message = HELO/EHLO required by SMTP RFC log_message = HELO/EHLO required by SMTP RFC hosts = !+relay_from_hosts condition = ${if eq{$sender_helo_name}{}{yes}{no}} accept senders=${lookup mysql{SELECT senders FROM whitelist \ WHERE senders='${quote_mysql:$sender_address}' \ OR senders='*@${quote_mysql:$sender_address_domain}' LIMIT 1}} #check IP addresses in black list deny message = rejected because $sender_host_address \ is in a black list at $dnslist_domain\n$dnslist_text hosts = !+relay_from_hosts !authenticated = * log_message = found in $dnslist_domain dnslists = bl.spamcop.net : \ cbl.abuseat.org : \ dnsbl.njabl.org : \ pbl.spamhaus.org : \ zen.spamhaus.org # tor.ahbl.org : \ #require verify = sender drop message = Rejected - Sender Verify Failed log_message = Rejected - Sender Verify Failed hosts = !+relay_from_hosts !verify = sender/no_details/callout=2m,defer_ok !condition = ${if eq{$sender_verify_failure}{}} condition = ${if match_ip{$sender_host_address}{${lookup dnsdb{>: defer_never,a=$sender_helo_name}}}{no}{yes}} #warn !verify = sender # log_message = sender verify failed: $acl_verify_message accept domains = +local_domains endpass message = $acl_verify_message verify = recipient accept domains = +relay_to_domains endpass message = "Unrouteable address!" verify = recipient/callout=30s,defer_ok,use_postmaster #require message = Can't verify sender # verify = sender accept ##### Data ##### acl_check_data: deny malware = * message = This message contains a virus ($malware_name). #accept # hosts = +relay_from_hosts # check spam by spamassassin warn spam = Debian-exim:true !hosts = +relay_from_hosts add_header = X-Spam-Flag: YES\n\ X-Spam_score: $spam_score\n\ X-Spam_score_int: $spam_score_int\n\ X-Spam_bar: $spam_bar\n\ #X-Spam_report: $spam_report # China symbols deny message = This is spam - denied !senders = : condition = ${if match{$message_body}{105[-_]*51[-_]*86|778[-_]*98[-_]*94}{yes}{no}} #Extensions deny message = contains $found_extension file (blacklisted). !senders = : demime = com:vbs:bat:pif:scr:exe:wsb:pdf.zip #Check MIME deny message = This message contains a MIME error ($demime_reason) !senders = : hosts = !+relay_from_hosts demime = * condition = ${if >{$demime_errorlevel}{2}{1}{0}} #Messages with NUL- symbols deny message = This message contains NUL characters !senders = : log_message = NUL characters! condition = ${if >{$body_zerocount}{0}{1}{0}} # Headers deny message = Incorrect headers syntax hosts = !+relay_from_hosts:* !senders = : !verify = header_syntax accept ############ Routers ######### begin routers #route mail to relay_to_domains (exim in this case as smart host) mailenable_router: driver = manualroute domains = +relay_to_domains transport = remote_smtp route_list = * 10.10.10.148 no_more dnslookup: driver = dnslookup domains = !+local_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more system_aliases: driver = redirect allow_fail allow_defer data = ${lookup mysql{select goto from aliases where address='${quote_mysql:$local_part}' and domain='${quote_mysql:$domain}'}} user = Debian-exim group = mail file_transport = address_file pipe_transport = address_pipe userforward: driver = redirect check_local_user no_verify no_expn check_ancestor file_transport = address_file pipe_transport = address_pipe reply_transport = address_reply data = ${lookup mysql{select goto from aliases where address='${quote_mysql:$local_part}' and domain='${quote_mysql:$domain}'}} localuser: driver = accept domains = ${lookup mysql{select domain from domains where domain='${domain}' AND relay='l'}} local_parts = ${lookup mysql{select login from accounts where login='${local_part}' and domain='${domain}'}} transport = local_delivery cannot_route_message = Unknown user ##### Transport ##### begin transports remote_smtp: driver = smtp hosts_avoid_tls = 4.28.131.119: 10.0.1.148 local_delivery: driver = appendfile maildir_format maildir_tag = ,S=$message_size directory = /var/mail/$domain/$local_part create_directory delivery_date_add envelope_to_add return_path_add group = mail mode = 0660 no_mode_fail_narrower address_pipe: driver = pipe return_output address_file: driver = appendfile delivery_date_add envelope_to_add return_path_add address_reply: driver = autoreply begin retry * * F,2h,15m; G,16h,1h,1.5; F,4d,6h begin rewrite begin authenticators auth_plain: driver = plaintext server_set_id = $2 server_prompts = : public_name = PLAIN server_condition = ${lookup mysql{select login from accounts where login='${quote_mysql:${local_part:$2}}' and password='${quote_mysql:$3}'}{yes}{no}} auth_login: driver = plaintext public_name = LOGIN server_set_id = $1 server_prompts = Username:: : Password:: server_condition = ${lookup mysql{select login from accounts where login='${quote_mysql:${local_part:$1}}' and password='${quote_mysql:$2}'}{yes}{no}} auth_cram_md5: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${lookup mysql{select password from accounts where login='${quote_mysql:${local_part:$1}}'}{$value}fail} server_set_id = $1

try restart exim:

$sudo systemctl restart exim4.service

Tools for checking email delivery:

check routing

$exim -v [email protected]

check from fake IP address:

$exim -bh <IP address>

test routing delivery mail:

$exim -bt [email protected]

See next

Install Spamassassin

---

links:

Exim Documentation

Current rating: 2

Comments

There are currently no comments

New Comment

required

required (not published)

optional

required