Вот мой конфиг!
CONFIG_PREFIX=/usr/local/etc/exim
ACL_PREFIX=CONFIG_PREFIX/acls
CERTDIR=CONFIG_PREFIX/certs
# Здесь мы указываем, где находить наш postgresql сервер, соединение
# осуществляется через локальный сокет, команда hide помогает спрятать эту
# настройку при вызове exim -bP, когда exim выводит все конфигурационные опции в
# стандартный вывод. Учтите,
# что сам /usr/local/etc/exim/configure должен иметь владельца root:wheel и
# иметь права доступа 0600, что отличается от того, что принято по умолчанию
# (0644)
hide pgsql_servers = (тут коннектимся к базе postgre)
# Тут мы описываем списки доменов
# Local_domains включает домены, считающиеся локальными, то есть те домены, для
# которых exim делает локальную доставку, для остальных доменов почта
# доставляется по MX записям в DNS. Обратите внимание на дополнительные файлы
# ACL_PREFIX/localdomains и ACL_PREFIX/hostingdomains, в которых перечислены
# домены, разделенные переводом строки (то есть, по одному домену на каждую строку)
#domainlist local_domains = mxpost.tcn.ru : ACL_PREFIX/hostingdomains : ACL_PREFIX/localdomains
domainlist local_domains = mxpost.tcn.ru : mxpost : ACL_PREFIX/hostingdomains : ${lookup pgsql {select domainname from localdomains where domainname='$domain'}{$value}fail}
# Дополнительная настройка
#domainlist hosting_domains = ${lookup pgsql {select domainname from localdomains}{yes}{no}}
domainlist hosting_domains = ACL_PREFIX/hostingdomains
# Список хостов, почту на которые мы явно отвергаем
hostlist host_reject = ACL_PREFIX/hostreject
domainlist relay_to_domains =
# Список адресов, с которых разрешена передача почты во внешний мир
hostlist relay_from_hosts = localhost : mxpost.tcn.ru : ACL_PREFIX/relayfromhosts
# Проверка получателя
acl_smtp_rcpt = acl_check_rcpt
# Проверка mime содержимого
acl_smtp_mime = acl_check_mime
# Проверка на спам и вирусы
acl_smtp_data = acl_check_virus
# Здесь мы описываем наш антивирус
av_scanner = clamd:127.0.0.1 3310
# И spamassasin
spamd_address = 127.0.0.1 783
# Настройки пользователя и группы по умолчанию
exim_user = mailnull
exim_group = mail
# Никогда не осуществляем доставку под рутом - root должен быть алиасом на
# другого локального пользователя. Кстати, это _обязательное_ условие, заданное
# еще на этапе компиляции
never_users = root
# Настройки директории для очереди
spool_directory = /var/spool/exim
# Разделяем spool_directory на несколько более маленьких - аналог хеш таблицы,
# ускоряет обработку spool'а
split_spool_directory
# Пытаемся сделать соответствие прямой и обратной зоны dns для каждого хоста.
# Несколько затратно, но весьма полезно
host_lookup = *
# Убираем проверку identd на клиентской стороне. Из-за неправильно настроенных
# firewall'ов это часто вызывает длительные тайм-ауты, кроме того, этот сервис
# поднят не у многих
rfc1413_query_timeout = 0s
# Указываем кое-какие лимиты (их назначение ясно из названия)
smtp_accept_max = 50
smtp_connect_backlog = 40
smtp_accept_max_per_host = 10
smtp_accept_queue = 22
smtp_accept_queue_per_connection = 10
recipients_max = 16
recipients_max_reject = true
message_size_limit = 16M
accept_8bitmime
# Игнорируем сообщения, которые приходят нам же, давность которых более 12-ти часов
ignore_bounce_errors_after = 12h
# Удаляем замороженные сообщения, давность которых больше недели.
timeout_frozen_after = 7d
# Настройки TLS
tls_certificate = CERTDIR/mailed.crt
tls_privatekey = CERTDIR/mailed.key
tls_advertise_hosts = *
tls_verify_certificates = *
# Следующая опция закомментирована, но весьма полезна, позволяя авторизироваться
# только через безопасный ssl канал
auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}}
######################################################################
# ACL CONFIGURATION #
# Specifies access control lists for incoming SMTP mail #
######################################################################
begin acl
# Этот список доступа описывает проверки, осуществляемые при вызове любой RCPT
# команды
acl_check_rcpt:
# Вначале проверяем достоверность отправителя
require verify = sender
# Принимаем соединения от локальных MUA (то есть не через TCP/IP)
accept hosts = :
#############################################################################
# Проверка соответствия почтового адреса стандарту
deny message = Access denied - $sender_host_address listed by $dnslist_domain\n$dnslist_text
dnslists = dnsbl.sorbs.net
deny message = message from $sender_host_address rejected - see
http://njabl.org/ dnslists = dnsbl.njabl.org
deny message = rejected because $sender_host_address for bad WHOIS info, see
http://www.rfc-ignorant.org/ dnslists = ipwhois.rfc-ignorant.org
deny message = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
dnslists = dialups.mail-abuse.org
deny message = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
dnslists = list.dsbl.org
deny message = Spam blocked see:
http://www.spamcop.net/w3m?action=checkblock&ip=$sender_host_address dnslists = bl.spamcop.net
deny message = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
dnslists = relays.ordb.org
deny message = rejected, $sender_host_address Open Proxy, see: $dnslist_domain\n$dnslist_text
dnslists = dnsbl.void.ru
# deny message = Restricted characters in address
# domains = +local_domains
# local_parts = ^[.] : ^.*[@%!/|]
accept domains = +local_domains
# Здесь прописаны так называемые dnsbl, то есть черные списки MTA с открытым
# релеем, мы проверяем ip адрес отправителя на соответствие таким спискам и
# блокируем письмо, если отправитель был найден в таком списке
deny message = host is listed in $dnslist_domain
dnslists = blackholes.mail-abuse.org:relays.mail-abuse.org
# Правило на проверку всех почтовых адресов, кроме локальных (менее строгое)
deny message = Restricted characters in address
domains = !+local_domains
local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
#############################################################################
# Принимаем почту для пользователя postmaster локальных доменов, не взирая на
# отправителя
accept local_parts = postmaster
domains = +local_domains
# Deny unless the sender address can be verified.
accept domains = +local_domains
endpass
verify = recipient
# Если домен в списке relay_to_domains, то разрешаем релей
accept domains = +relay_to_domains
endpass
verify = recipient
accept domains = +hosting_domains
endpass
verify = recipient
accept hosts = +relay_from_hosts
# Принимаем любые соединения, которые были успешно авторизованы
accept authenticated = *
# Реализация нашего бан-листа
deny hosts = +host_reject
message = You are banned. Go away.
# Запрещаем все, что не разрешено, закрывая тем самым релей для спамеров
deny message = relay not permitted
# Список доступа для проверки mime частей сообщения
acl_check_mime:
# Произодим декодирование mime сообщений. Полезно для дальнейшей проверки на
# вирусы
warn decode = default
# Можно очень быстро отсеять сообщения, просто запретив некоторые mime
# вложения, чаще всего содержащие вирусы, хотя, конечно, это не панацея
deny message = Blacklisted file extension detected
condition = ${if match \
{${lc:$mime_filename}} \
{\N(\.wav|\.cpl|\.pif|\.bat|\.scr|\.lnk|\.com)$\N} \
{1}{0}}
# Много ли у нас людей, знающих китайский? А вот китайского спама это поубавит
#
deny message = Sorry, noone speaks chinese here
condition = ${if eq{$mime_charset}{gb2312}{1}{0}}
accept
# Проверка содержимого на вирусы и спам
acl_check_virus:
# Мы не запрещаем письма со спамом, а просто добавляем заголовок,
# содержащий количество спамерских очков, а пользователь на своей
# стороне уже просто настраивает свои фильтры. Так мы исключаем жалобы
# со стороны пользователей о потерянных письмах
# warn message = X-Spam-Score: $spam_score ($spam_bar)
# spam = spamd:true
#
# Добавляем заголовки, указывающие, что письма были проверены
# spamasssasin'ом
# warn message = X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on post.tcn.ru
# warn message = X-Spam-Scanned: Yes
# warn message = X-Spam-Scanner: SpamAssassin running on MXpost.tcn.ru
warn message = X-Spam-Score: $spam_score ($spam_bar)
hosts = !+relay_from_hosts
spam = spamd:true
warn message = X-Spam-Report: $spam_report
hosts = !+relay_from_hosts
spam = spamd:true
# warn message = Subject: ***SPAM*** $h_Subject:
# hosts = !+relay_from_hosts
# spam = spamd
warn message = X-Spam-Status: Yes
hosts = !+relay_from_hosts
spam = spamd
deny message = This message scored $spam_score spam points.
spam = spamd:true
hosts = !+relay_from_hosts
condition = ${if >{$spam_score_int}{120}{1}{0}}
# Вот что-что, а вирусы нам не нужны.
deny message = Message rejected: virus found. Your message was successfully trashed.
hosts = *
malware = *
accept
######################################################################
# ROUTERS CONFIGURATION #
# Specifies how addresses are handled #
######################################################################
# THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT! #
# An address is passed to each router in turn until it is accepted. #
######################################################################
begin routers
# Роутер, осуществляющий поиск по MX записям в DNS
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
no_more
# Все останльные роутеры обслуживают доставку локальной почты
# Драйвер алиасов пользователя. Обратите внимание на lookup в pgsql базе. Что
# интересно, этот lookup работает даже для иерархических алиасов, например,
# postmaster -> root -> cebka -> cebka@jet.msk.su Также определяются транспорты
# для передачи почты в файл (>/path/to/file) и в pipe
# (|/usr/local/libexec/slocal)
system_aliases:
driver = redirect
allow_fail
allow_defer
data = ${lookup pgsql{select alias from aliases where mail ='$local_part@$domain'}{$value}fail}
user = mailnull
group = mail
file_transport = address_file
pipe_transport = address_pipe
# Для локальных пользователей также создаем возможность перенаправления почты
# через ~/.forward файл. Если включена директива allow_filter, то в .forward
# файле можно использовать язык sieve фильтров. Для подробностей см.
# документацию на www.exim.org, т.к. на рассмотрение этой темы уйдет слишком
# много времени
userforward:
driver = redirect
check_local_user
file = $home/.forward
no_verify
no_expn
check_ancestor
# allow_filter
file_transport = address_file
pipe_transport = address_pipe
reply_transport = address_reply
condition = ${if exists{$home/.forward} {yes} {no} }
# Локальная доставка, если данный пользователь найдем в базе
localuser:
driver = accept
condition = ${lookup pgsql {select 150 as uid from accounts where login = '$local_part' and domain='$domain'}{yes}{no}}
transport = local_delivery
cannot_route_message = Unknown user
######################################################################
# TRANSPORTS CONFIGURATION #
######################################################################
# ORDER DOES NOT MATTER #
# Only one appropriate transport is called for each delivery. #
######################################################################
begin transports
# Драйвер для доставки через соединения с удаленными smtp серверами
remote_smtp:
driver = smtp
# Этот транспорт доставляет почту в локальные maildir'ы. Путь к maildir хранится
# опять же в таблице accounts. Разрешения на директорию 0700 для возможности
# работы с данными директориями imap сервера. При этом владельцем является
# группа и пользователь из accounts (потому при вставлении записей в эту таблицу
# надо начинать значения uid с достаточно большого числа, например, 2000 и
# пересекаться с реальными пользователями оно должно только если реальному
# пользователю нужен локальный доступ к maildir'у).
# Также из таблицы accounts извлекается данные о размере квоты, и
# устанавливается порог в 75% от квоты, когда пользователю посылается указанное
# предупреждение об подходе к порогу квоты
local_delivery:
driver = appendfile
# directory = ${lookup pgsql{select maildir from accounts where login = '$local_part@$domain'}{$value}fail}
directory = ${lookup pgsql{select '/usr/local/mailusers/'||c.domain||'/'||substring(c.login from 1 for 1)||'/'||c.login as maildir from accounts as c where login = '$local_part' and domain='$domain'}{$value}fail}
create_directory
directory_mode = 0770
maildir_format
delivery_date_add
envelope_to_add
return_path_add
group = ${lookup pgsql{select 150 as gid from accounts where login = '$local_part' and domain='$domain'}{$value}fail}
user = ${lookup pgsql{select 150 as uid from accounts where login = '$local_part' and domain='$domain'}{$value}fail}
mode = 0660
no_mode_fail_narrower
quota = ${lookup pgsql{select mailquota from accounts where login = '$local_part' and domain='$domain'}{$value}fail}M
quota_warn_message = "\
To: $local_part@domain\n\
From: postmaster@test.ru\n\
Subject: Your maildir is going full\n\
This message is automaticaly gnerated by your mail server.\n\
This means, that your mailbox is 75% full. If you would \n\
override this limit new mail would not be delivered to you!\n"
quota_warn_threshold = 75%
# Транспорт, осуществляющий доставку в pipe
address_pipe:
driver = pipe
return_output
# Транспорт, осуществляющий доставку прямо в файл
address_file:
driver = appendfile
delivery_date_add
envelope_to_add
return_path_add
# Этот транспорт используется для автоматического ответа на сообщения об ошибках
address_reply:
driver = autoreply
######################################################################
# RETRY CONFIGURATION #
######################################################################
begin retry
# Настройки по умолчанию, которые я не трогал, управляют интервала повторной
# передачи сообщений
# This single retry rule applies to all domains and all errors. It specifies
# retries every 15 minutes for 2 hours, then increasing retry intervals,
# starting at 1 hour and increasing each time by a factor of 1.5, up to 16
# hours, then retries every 6 hours until 4 days have passed since the first
# failed delivery.
# Address or Domain Error Retries
# ----------------- ----- -------
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
######################################################################
# REWRITE CONFIGURATION #
######################################################################
begin rewrite
# Создаем правило, по переписыванию заголовка To: с *@test.ru на локальный
# smart-host - @unona.test.ru. Это было сделано для локальных пользователей,
# по идее с хранением пользователей в postgres, уже не нужно, показано для
# примера.
*@test.ru $1@unona.test.ru T
######################################################################
# AUTHENTICATION CONFIGURATION #
######################################################################
# Описания аутентификации
begin authenticators
# CRAM-MD5 аутентификация, требует наличия пароля в открытом виде, имя
# пользователя должно быть в формате user@domain, как оно хранится в таблице
# accounts
lookup_cram:
driver = cram_md5
public_name = CRAM-MD5
server_secret = ${lookup pgsql {select password from accounts where login||'@'||domain='$1'}{$value}fail}
server_set_id = $1
# LOGIN аутентификация - не требует хранения пароля в открытом виде, однако, по
# сети пароль передается в открытом виде - требуется лишь выполнение условия
# server_condition - $1 - имя пользователя, а $2 - пароль. LOGIN безопасен
# только при установлении ssl соединения.
login:
driver = plaintext
public_name = LOGIN
server_prompts = Username:: : Password::
server_condition = ${lookup pgsql {select login from accounts where login||'@'||domain='$1' and password='$2'}{yes}{no}}
server_set_id = $1
######################################################################
# CONFIGURATION FOR local_scan() #
######################################################################
# If you have built Exim to include a local_scan() function that contains
# tables for private options, you can define those options here. Remember to
# uncomment the "begin" line. It is commented by default because it provokes
# an error with Exim binaries that are not built with LOCAL_SCAN_HAS_OPTIONS
# set in the Local/Makefile.
# begin local_scan
# End of Exim configuration file