- Основные термины
- Введение
- Структура таблиц в базе данных
- Агент доставки почты Dovecot
- Агент пересылки почты Exim
- Веб интерфейс Roundcube
- Заключение
- Список литературы
- Комментарии
4. Агент пересылки почты Exim
Exim является одним из лучших MTA, т.к. он чертовски быстр, бесплатен, обладает большим количеством возможностей и поддерживаемых технологий, а также возможностью гибкой и тонкой настройки под любые задачи. Одной из самых классных фич Exim,а являются списки контроля доступа (ACL), с помощью которых можно управлять потоком писем практически не ограничивая себя ни в чем. Exim из коробки поддерживает различные форматы почтовых ящиков. Также стоит отметить возможность поиска конфигурации в обычных файлах и различных базах данных (PostgreSQL, MySQL, LDAP и д.р.). В общем, у него есть куча достоинств, которые можно перечислять практически до бесконечности...
Теперь пару слов про конфигурцию MTA... Как уже было сказано ранее Exim у нас будет заниматься только приемом и передачей почтовых сообщений, поэтому в конфиге можно увидеть, что запускаю я его под пользователем smmsp. smmsp — является стандартным системным пользователем, из описания которого можно увидеть, что он предназначен для процесса, занимающегося пересылкой почты. То есть Exim будет работать от пользователя, не имеющего доступа к почтовым ящикам пользователей, что является несомненным плюсом в безопасности почтовой системы. Если вы сделаете также, то вам необходимо будет переназначить права на служебные папки и файлы Exim,а (/var/log/exim, /var/spool/exim) и переназначать их после каждой переустановки/обновлении Exim (поскольку после установки права переназначаются), либо задать переменные EXIM_USER и EXIM_GROUP в /etc/make.conf.
В моей конфигурации предполагается использование антивируса ClamAV. Про его установку здесь я писать не буду, но может быть, потом вынесу это дело в отдельную статью. В общем, там нет ничего сложного: залезть в порты, установить, подправить конфигурационный файл под себя, обновить базы и запустить. Если вам антивирус не нужен, то закомментируйте ответственные за сканирование почты строки в конфиге.
Теперь самое интересное — защита от спама. Я нигде не использую внешние средства фильтрации, такие как SpamAssasin или DSPAM, поскольку предпочитаю рубить его еще до приема текста сообщения. Вот тут мощь и гибкость списков контроля доступа Exim,а раскрываются во всей красе. Определение хоста (желающего отправить почту на наш сервер) как спамера происходит на основе баллов. Это значит, что практически все проверки в ACL не являются запрещающими, а накидывающими некоторое количество баллов при попадании под какое-нибудь правило. Хосты, набравшие сравнительно большое количество баллов, благополучно размещаются в локальном черном списке (таблица blacklist_tb). Хосты, набравшие такое количество баллов, что их нельзя отнести ни к легитимным хостам, ни к спам хостам заворачиваются в серый список на 29 минут (таблица greylist_tb). По прошествии 29 минут, если хост повторил передачу, то от него принимается письмо и отправитель заносится в белый список, точнее хэш сумма от отправителя и получателя (таблица whitelist_tb). От остальных хостов почта принимается в обычном порядке. Чисткой устаревших записей в таблицах занимается скрипт. Также отмечу, что с целью упрощения отладки правил в ACL и решения проблем, в случае их возникновения на этапе приема письма, в данной конфигурации я сохраняю информацию о проведенных проверках в ACL, которые не прошла отправляющая сторона (см. переменную acl_c_spamlog).
Хочу отметить, что не маловажным при конфигурировании почтового сервера будет использование таких технологий, как SPF и DKIM. Поскольку такие почтовики, как yandex, gmail и другие гиганты очень сильно не доверяют хостам, не имеющих даже той же записи SPF. Например, пока я не настроил на своих серверах DKIM, почтовик гугла помечал все письма с моих серверов как спам и размещал их в соответствующей папке у пользователей.
4.1 Установка
На момент написания статьи в портах доступна версия 4.80.1. Устанавливаем Exim:- # cd /usr/ports/mail/exim
- # make install clean
- CONTENT_SCAN — включить поддержку внешних сканеров (например: ClamAV).
- PGSQL — поддержка СУБД PostgreSQL.
- READLINE — включить библиотеку readline(3).
- SPF — поддержка Sender Policy Framework.
4.2 Настройка
Конфигурационный файл Exim распологается здесь — /usr/local/etc/exim/configure. Файл очень большой, но при желании его можно разбить на небольшие и отвечающие за определенный функционал файлы, как например, это сделали во второй версии Dovecot (смотрите в документации Exim директиву include). У меня конфигурационный файл имеет следующий вид:- ####################################################################
- # Конфигурационный файл Exim #
- ####################################################################
- # Это стандартный конфигурационный файл, который можно использовать
- # для простых конфигураций. Смотрите документацию, чтобы узнать
- # какие опции можно использовать в данном файле. Их гораздо больше,
- # чем представлено здесь. Документация находится в doc/spec.txt
- # в дистрибутиве Exim в обычном текстовом формате. Другие форматы
- # (PostScript, Texinfo, HTML, PDF) доступны на ftp. Документацию
- # так же можно найти на официальном сайте.
- # Данный файл разделен на несколько частей, все части, кроме первой,
- # начинаются с ключевого слова "begin". Пустые строки и строки,
- # начинающиеся с символа # игнорируются.
- ####################################################################
- # Важно знать #
- ####################################################################
- # После изменения конфигурационного файла вы должны послать сигнал #
- # HUP демону Exim, чтобы тот перечитал файл. Однако, любой другой #
- # запускаемый процесс Exim, например, процесс запущенный MUA #
- # для отправки сообщения увидит новый конфигурационный файл. #
- # #
- # Не обязательно посылать сигнал HUP процессу Exim, когда изменяются#
- # дополнительные (вспомогательные) файлы подключенные из конфига. #
- # Данные файлы читаются каждый раз, когда это необходимо. #
- # #
- # Хорошей идеей будет тестирование нового конфигурационного файла #
- # на предмет синтаксических ошибок (например, #
- # exim -C /config/file.new -bV) #
- ####################################################################
- ######################################################################
- # Определение макросов #
- ######################################################################
- EXTRA_PREFIX = /usr/local/etc/exim/extra
- DKIM_DIRECTORY = /usr/local/etc/exim/dkim
- # Запрос, возвращающий синонимы для почтового адреса, если они есть
- CHECK_VIRTUAL_ALIASES = \
- ${lookup pgsql{SELECT "aliases_tb"."mailaddr" FROM "aliases_tb" \
- INNER JOIN "domains_tb" ON ("aliases_tb"."domain_id" = "domains_tb"."id") \
- WHERE "aliases_tb"."aliasname" = '${quote_pgsql:$local_part}' AND \
- "domains_tb"."domainname" = '${quote_pgsql:$domain}' AND \
- "aliases_tb"."active" = 'true' AND "domains_tb"."active" = 'true'}}
- # Запрос проверяет существование пользователя в почтовой системе
- CHECK_VIRTUAL_USER = \
- ${lookup pgsql{SELECT "users_tb"."id" FROM "users_tb" \
- INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
- WHERE "users_tb"."username" = '${quote_pgsql:$local_part}' AND \
- "domains_tb"."domainname" = '${quote_pgsql:$domain}' AND \
- "users_tb"."active" = 'true' AND "domains_tb"."active" = 'true'}{yes}fail}
- # Запрос возвращает идентификатор группы пользователя в системе
- GET_VIRTUAL_GROUP = \
- ${lookup pgsql{SELECT "users_tb"."gid" FROM "users_tb" \
- INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
- WHERE "username" = '${quote_pgsql:$local_part}' AND \
- "domains_tb"."domainname" = '${quote_pgsql:$domain}'}}
- # Запрос возвращает идентификатор пользователя в системе
- GET_VIRTUAL_USER = \
- ${lookup pgsql{SELECT "users_tb"."uid" FROM "users_tb" \
- INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
- WHERE "username" = '${quote_pgsql:$local_part}' AND \
- "domains_tb"."domainname" = '${quote_pgsql:$domain}'}}
- # Запрос возвращает домашнюю директорию пользователя
- GET_VIRTUAL_DIR = \
- ${lookup pgsql{\
- SELECT "users_tb"."homedir" || '${quote_pgsql:/$domain/$local_part/Maildir}' FROM "users_tb" \
- INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
- WHERE "username" = '${quote_pgsql:$local_part}' AND \
- "domains_tb"."domainname" = '${quote_pgsql:$domain}'}}
- # Запрос возвращает данные о предалах квот в килобайтах
- GET_VIRTUAL_QUOTA = \
- ${lookup pgsql{\
- SELECT "users_tb"."quota" || 'K' FROM "users_tb" \
- INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
- WHERE "username" = '${quote_pgsql:$local_part}' AND \
- "domains_tb"."domainname" = '${quote_pgsql:$domain}'}}
- ####################################################################
- # Основные параметры
- ####################################################################
- # Данные для поключения к базе данных
- hide pgsql_servers = 192.168.7.253/vmail/vmail/1234
- # Укажите здесь имя своего хоста. Правильно будет указать его в
- # формате FQDN. Если данный параметр не задан, то будет использован
- # результат вызова функции uname(). В большинстве случаев задавать
- # параметр не требуется, так как uname() возвращает верное значение.
- primary_hostname = mx.info-x.org
- # В следующих трех параметрах задается два списка доменов и один
- # список хостов. На эти списки можно ссылаться далее в
- # конфигурационном файле, используя следующий синтаксис
- # +local_domains, +relay_to_domains, и +relay_from_hosts.
- # Во всех списках элементы разделены двоеточием:
- domainlist local_domains = ${lookup pgsql{SELECT "domainname" FROM "domains_tb" WHERE "domainname" = '${quote_pgsql:$domain}' AND "active" = 'true'}}
- domainlist relay_to_domains = ${lookup pgsql{SELECT "domainname" FROM "domains_tb" WHERE "domainname" = '${quote_pgsql:$domain}' AND "active" = 'true'}}
- hostlist relay_from_hosts = localhost : 192.168.7.0/24
- hostlist blacklist = ${lookup pgsql{SELECT "ip" FROM "blacklist_tb" WHERE "ip" = '${quote_pgsql:$sender_host_address}'}}
- hostlist badhosts = ${lookup pgsql{SELECT "ip" FROM "badhosts_tb" WHERE "ip" = '${quote_pgsql:$sender_host_address}'}}
- # Большинство требований к правилам доступа может быть удовлетворено
- # заданием вышеуказанных опций. В боевых конфигурациях вам может
- # потребоваться изменить ACL,ки, которые находятся далее в этом файле.
- # В первом параметре указываются ваши локальные домены, например:
- #
- # domainlist local_domains = my.first.domain : my.second.domain
- #
- # Вы можете использовать символ "@", что означает "имя локального хоста",
- # как сделано выше в файле. Это имя, которое задается с помощью
- # параметра primary_hostname. Если вам не нужны локальные доставки,
- # то удалите символ "@". Если вы хотите принимать сообщения с адресом
- # назначения в виде "user@[IP]", "user@[192.168.23.44]", то вы можете
- # добавить "@[]", как элемент списка локальных доменов. Так же вам
- # потребуется раскомментировать параметр "allow_domain_literals" ниже.
- # Такое не приветствуется в сегодняшнем интернете.
- # Во втором параметре указываются домены, которым ваш хост может
- # пересылать письма. Если вы не хотите осуществлять пересылку, то
- # оставьте значение этого параметра пустым. Однако, если ваш хост
- # является резервным или шлюзом для некоторых доменов, то вы
- # должны указать их здесь. Например:
- #
- # domainlist relay_to_domains = *.myco.com : my.friend.org
- #
- # Это позволяет любому хосту пересылать письма через ваш, указанным
- # доменам. Смотрите секцию "Control of relaying" в документации, чтобы
- # получить больше информации.
- # В третьем параметре указываются хосты, которым можно отправлять
- # письма в Интернет через ваш хост. Так здесь можно указать список
- # локальных сетей, ну и localhost. Например:
- #
- # hostlist relay_from_hosts = 127.0.0.1 : 192.168.0.0/16
- #
- # "/16" - это маска переменной длины (CIDR). Учтите, что вы должны
- # включить 127.0.0.1, чтобы разрешить процессам на вашей машине
- # отправить письма, используя адрес loopback.
- # Эти три параметра могут содержать различные элементы, включая
- # wildcard имена, регулярные выражения, а так же данные из других
- # источников. За дополнительной информацией обращайтесь к
- # документации. Данные списки используются в ACL,ках для проверки
- # входящей почты. Имена ACL,ок заданы здесь:
- acl_smtp_connect = acl_check_connect
- acl_smtp_mail = acl_check_mail
- acl_smtp_rcpt = acl_check_rcpt
- acl_smtp_predata = acl_check_predata
- acl_smtp_data = acl_check_data
- # Вы не должны изменять эти параметры, если не понимаете
- # как работают ACL,ки.
- # Если Exim скомпилирован с поддержкой content-scanning, то вы можете
- # отправлять входящие сообщения на проверку антивирусу. Для этого вам
- # потребуется сделать изменения в двух местах. Первое - здесь, где
- # вы определяете интерфейс к сканеру. Тут указан ClamAV; смотрите
- # документацию, чтобы узнать, как подключить другие антивирусы.
- # Второй место в ACL,ке acl_check_data (смотрите ниже).
- av_scanner = clamd:/var/run/clamav/clamd.sock
- # Для проверки на спам, эта опция предоставляет интерфейс к SpamAssassin.
- # Так же вам необходимо будет сделать изменения в ACL,ке acl_check_data.
- # spamd_address = 127.0.0.1 783
- # Если Exim скомпилирован с поддержкой TLS, то возможно вы захотите
- # задать следующие параметры, чтобы Exim позволял клиентам
- # устанавливать защищенные соединения. В секции аутентификаторов
- # ниже, находятся шаблоны конфигураций для аутентификации
- # пользователей открытым текстом. Аутентификация открытым текстом
- # будет безопасной, если соединение шифруется.
- # Разрешить любому клиенту использовать TLS.
- tls_advertise_hosts = *
- # Где Exim взять TLS сертификат и приватный ключ. Приватный ключ
- # не должен быть защищен паролем. Вы можете объединить сертификат
- # и приватный ключ в один файл, тогда вам понадобится только первый
- # параметр, в другом случае используйте оба параметра.
- tls_certificate = /usr/local/etc/exim/exim.crt
- tls_privatekey = /usr/local/etc/exim/exim.pem
- # Для пользователей, которые могут отправить письма откуда угодно,
- # вам может понадобиться изменить порты, на которых Exim будет
- # принимать подключения. Например, если фаервол в удаленной сети
- # блочит 25 порт. Конечно, выделен стандартный порт в таком случае,
- # порт 587 (за деталями в RFC 4409). Почтовые клиенты Microsoft
- # не могут корректно работать в таком режиме, поэтому (если у вас
- # в сети есть такие продукты, то вы можете сделать TLS доступ для
- # пользователей).
- daemon_smtp_ports = 25 : 465 : 587
- tls_on_connect_ports = 465
- # Укажите здесь домен, который будет добавляться к адресатам
- # в письмах, если там домен не указан. Домен может быть только один,
- # символ "@" писать не нужно. Например, "caesar@rome.example"
- # полный адрес, в котором указан пользователь и домен (то есть FQDN). Но
- # адрес "caesar" не полный (то есть это не FQDN), а просто имя пользователя.
- # По умолчанию не полные адреса принимаются только с локальных хостов.
- # Смотрите параметр recipient_unqualified_hosts, если вы хотите разрешить
- # принимать и добавлять домен в письмах от удаленных хостов. Если
- # этот параметр не задан, то используется значение параметра
- # primary_hostname.
- qualify_domain = info-x.org
- # Если в письме не задан FQDN получателя (а только логин), то подставить
- # в письмо в адрес получателя указанный здесь домен. Если этот параметр
- # не задан, то используется значение параметра qualify_domain.
- qualify_recipient = info-x.org
- # Раскомментируйте данный параметр, если вы хотите, чтобы Exim
- # принимал письма с адресатами вида "user@[10.11.12.13]". Это
- # не нарушает RFC, но в наше время такая плюшка ни к чему. Учтите,
- # что этот старый формат может использоваться спамерами. Если вам
- # действительно необходимо работать с такими письмами, то
- # раскомментируйте параметр и смотрите ниже роутер "domain_literal".
- # allow_domain_literals
- # Не использовать указанные здесь идентификаторы для доставки почты.
- # Можно использовать имена пользователей, список разделяется двоеточием.
- # Попытка использования данных идентификаторов для передачи почты
- # будет отражена в логе паники, а доставка будет отложена. Есть еще
- # более строгий вариант этого параметра - вшивание в код при сборке
- # макроса (или переменной, что там не смотрел) FIXED_NEVER_USERS.
- # Список пользователей в FIXED_NEVER_USERS уже никак не изменить
- # после сборки Exim,а. Значением по умолчанию для FIXED_NEVER_USERS
- # является - "root", но чтобы быть абсолютно уверенным (что пользователь
- # root никак не задействуется), значение этого параметра по умолчанию
- # тоже "root".
- # Учтите, что настройки по умолчанию не позволят доставлять почту руту,
- # как обычному пользователю. Но это не проблема, так как большинство
- # конфигураций имеет алиас, который перенаправляет письма для рута
- # на нужный адрес.
- #exim_user = mailnull
- #exim_group = mailnull
- exim_user = smmsp
- exim_group = smmsp
- never_users = root
- # Следующий параметр заставляет Exim делать обратный запрос к DNS
- # для проверки IP адреса, с которого идет передача писем. Если вы
- # считаете, что это пустая трата времени или на это уходит слишком
- # много времени, то укажите здесь адреса, для которых нужно делать
- # такие запросы или закомментируйте/удалите этот параметр вообще.
- #host_lookup = *
- # Следующие параметры заставляют Exim делать обратные запросы (ident)
- # для входящих SMTP соединений (RFC 1413). Вы можете указать здесь
- # хосты, для которых необходимо делать данные запросы и задать
- # таймаут. Если выставить таймаут в 0, то данные запросы делаться
- # не будут. Вызовы RFC 1413 не требуют много ресурсов и являются
- # хорошим средством для выявления проблем с передаваемой почтой,
- # но могут возникнуть проблемы с некоторыми хостами из-за файерволов.
- # Так же может быть, что из-за таймаута Exim не будет знать, что
- # соединение закрыто, что вызовет задержки в работе. (Начиная с релиза
- # 4.61 таймаут уменьшен до 5 секунд.)
- rfc1413_hosts = *
- rfc1413_query_timeout = 0s
- # По умолчанию Exim принимает только почту, в которой адресаты заданы
- # верно, то есть в FQDN. Если вы хотите, чтобы Exim работал с почтой
- # не имеющей адресатов в FQDN, то укажите здесь хосты с которых
- # можно отправлять такие письма. В таком случае, Exim просто добавит
- # к адресату значение параметра qualify_domain и/или qualify_recipient.
- #
- # sender_unqualified_hosts =
- # recipient_unqualified_hosts =
- # Если вы хотите, чтобы Exim поддерживал хак с процентом для некоторых
- # доменов, то раскомментируйте опцию ниже и укажите список доменов.
- # Данный хак позволяет использовать адрес вот такого вида x%y@z (где
- # z - один из указанных в этой опции доменов), который будут перенаправлен
- # на адрес x@y. Если домен z не из списка, то часть адреса x%y будет
- # интерпретирована как есть. В наши дни в использование данного хака
- # нет необходимости. Используйте данную фишку, если только она вам
- # действительно необходима.
- #
- # percent_hack_domains =
- #
- # Если вы включите данный функционал, то не забудьте так же поправить
- # правила в секции ACL - уберите проверку символа % в локальной части.
- # Когда Exim не может доставить рикошет к отправителю, то он
- # замораживает его. Есть так же другие обстоятельства, при которых
- # Exim может заморозить рикошет. Они остаются в очереди пока
- # не истечет заданное здесь время.
- # Данная опция размораживает рикошет по прошествии 2-х дней,
- # далее Exim снова пытается его доставить и игнорирует любые
- # ошибки о доставке.
- ignore_bounce_errors_after = 2d
- # Замороженные сообщения удаляются из очереди, когда истечет
- # указанное здесь время.
- timeout_frozen_after = 7d
- # По умолчанию, ожидающие сообщения в очереди Exim,а хранятся
- # в одной директории, называемой "input", которая находится в Exim
- # директории spool. (По умолчанию эта директория задается на этапе
- # компиляции и имеет такой путь - /var/spool/exim/.) Exim работает
- # быстрее, когда очередь сохраняет небольшой размер, но бывают
- # обстоятельства, при которых такое не всегда возможно. Если вы
- # раскомментируете параметр ниже, то сообщения будут храниться
- # в 62 поддиректориях в директории "input", вместо одной общей.
- # Поддиректории именуются 0, 1, ... A, B, ... a, b, ... z. Это хорошо
- # тем, что:
- # 1) если ваша ОС тормозит, когда в директории много файлов, то
- # такой подход поможет не допустить этого.
- # 2) Exim может обрабатывать очередь в каждой директории отдельно,
- # вместо одной общей, что приведет к увеличению производительности
- # при больших размерах очереди.
- split_spool_directory = true
- # Если вы находитесь в такой части мире, где ASCII не достаточен
- # для большей части текста, то вы наверняка знакомы с RFC2047.
- # По умолчанию, Exim придерживается спецификации, которая
- # делает ограничение в 76 символов в строке.
- #
- # check_rfc2047_length = false
- #
- # Разрабы Exim,а получали много жалоб от российских админов о
- # проблемах в работе с включенной опцией, потому что некоторые
- # популярные почтовые клиенты имеют баги.
- # If you wish to be strictly RFC compliant, or if you know you'll be
- # exchanging email with systems that are not 8-bit clean, then you may
- # wish to disable advertising 8BITMIME. Uncomment this option to do so.
- # accept_8bitmime = false
- # Не использовать протокол IPv6
- disable_ipv6 = true
- #
- freeze_tell = admin@info-x.org
- #helo_try_verify_hosts = *
- # не робит с некоторыми клиентами
- #helo_verify_hosts = *
- # Ограничение размера почтового сообщения
- message_size_limit = 30M
- # Проверять заголовки DKIM у каждого отправителя
- dkim_verify_signers = $sender_address_domain
- bounce_return_message = true
- bounce_return_body = true
- bounce_return_size_limit = 20K
- smtp_accept_max = 50
- smtp_accept_max_per_connection = 100
- smtp_accept_max_per_host = 10
- smtp_connect_backlog = 50
- smtp_enforce_sync = yes
- smtp_banner = $smtp_active_hostname ESMTP MTA :)
- # Здесь можно задать опции для библиотеки OpenSSL, которые будут использоваться
- # в рамках установки защищенного соединения с клиентами. Задается как список,
- # разделенные пробелами, где каждый элемент может быть добавлен "+added"
- # или исключен "-substracted" из текущего набора опций.
- # Внимание: для тех, у кого библиотека OpenSSL версии >= 1.0.0, желательно
- # в целях повышения надежности задать опцию "+no_compression" ("CRIME" attack)
- # (см. https://lists.exim.org/lurker/message/20121009.173420.ed5bd052.en.html)
- openssl_options = +no_sslv2
- # В данной опции возможно задать разрешенные шифры (ciphers) для входящих SLL/TLS
- # соединений (Exim должен быть скомпилирован с поддержкой OpenSSL. Для тех,
- # кто использует GnuTLS параметр задается по-другому, см. документацию).
- # Дополнительную информацию по шифрам можно получить по команде man ciphers.
- tls_require_ciphers = ${if =={$received_port}{25}\
- {DEFAULT}\
- {HIGH:MEDIUM:!LOW:!ADH:!RC4:!MD5:!EXP:!aNULL:!eNULL:!NULL}}
- # Что пишем в лог?
- log_selector = +all_parents \
- +connection_reject \
- +incoming_interface \
- +lost_incoming_connection \
- +received_recipients \
- +received_sender \
- +smtp_confirmation \
- +smtp_protocol_error \
- +smtp_syntax_error \
- -queue_run
- #####################################################################
- # Параметры ACL
- #####################################################################
- begin acl
- # Проверки выполняются по порядку до первого попадания в правило,
- # где указано принять или отклонить письмо.
- acl_check_connect:
- # Сохраняем в переменную содержимое обратной записи (PTR) для IP подключенного клиента
- warn set acl_c_reverse_address = ${escape:${lookup dnsdb{ptr=$sender_host_address}{$value}}}
- accept
- acl_check_mail:
- warn set acl_c_spamscore = 0
- # Блочим клиентов из локального черного списка
- deny message = Your IP address in local blacklist
- hosts = +blacklist
- deny message = Your IP address in local blacklist. Please contact with postmaster if you consider that your address got there by mistake.
- hosts = +badhosts
- # Различные проверки HELO/EHLO
- #---------------------------------------------------------
- # Накидываем сверху очков за неверный HELO/EHLO
- warn !authenticated = *
- hosts = !+relay_from_hosts
- condition = ${if and{\
- {!match{$sender_helo_name}{\N(?i)^([a-z0-9]([a-z0-9\-]{0,61}[a-z0-9])?\.)+[a-z]{2,6}$\N}}\
- {!eqi{$sender_helo_name}{[$sender_host_address]}}\
- }\
- }
- set acl_c_spamscore = ${eval:$acl_c_spamscore + 25}
- set acl_c_spamlog = $acl_c_spamlog Bad HELO/EHLO;
- # Накидываем очки, за использование в HELO любых данных,
- # принадлежащих нашему серверу
- warn !authenticated = *
- hosts = !+relay_from_hosts
- set acl_m_islocal = ${lookup pgsql{SELECT "domainname" FROM "domains_tb" \
- WHERE "domainname" = '${quote_pgsql:$sender_helo_name}'}{yes}{no}}
- condition = ${if or{\
- {eq{$sender_helo_name}{$interface_address}}\
- {eqi{$sender_helo_name}{$primary_hostname}}\
- {eq{$acl_m_islocal}{yes}}\
- }\
- }
- set acl_c_spamscore = ${eval:$acl_c_spamscore + 50}
- set acl_c_spamlog = $acl_c_spamlog Your HELO is one of local domain name;
- # Проверки DNS
- #---------------------------------------------------------
- # warn message = your reversed address is $acl_c_reverse_address
- # Добавляем очков за то, что нет указателя в DNS для данного IP
- warn !authenticated = *
- hosts = !+relay_from_hosts
- condition = ${if eq{$acl_c_reverse_address}{}}
- set acl_c_spamscore = ${eval:$acl_c_spamscore + 30}
- set acl_c_spamlog = $acl_c_spamlog PTR == NULL;
- # Добавляем еще очков за то, что обратная DNS запись не совпадает с прямой.
- warn !authenticated = *
- hosts = !+relay_from_hosts
- condition = ${if !eqi{$acl_c_reverse_address}{$sender_helo_name}}
- set acl_c_spamscore = ${eval:$acl_c_spamscore + 30}
- set acl_c_spamlog = $acl_c_spamlog PTR != HELO;
- # Добавляем очков за то, что IP клиента из диапазона динамических адресов
- warn !authenticated = *
- hosts = !+relay_from_hosts
- condition = ${lookup{$acl_c_reverse_address}wildlsearch{EXTRA_PREFIX/dynamic_pools}{yes}{no}}
- set acl_c_spamscore = ${eval:$acl_c_spamscore + 50}
- set acl_c_spamlog = $acl_c_spamlog PTR in dynamic pools;
- # Проверка SPF
- #---------------------------------------------------------
- # Накидываем очки за попытку отправить почту с сервера,
- # не указанного в SPF
- warn !authenticated = *
- hosts = !+relay_from_hosts
- spf = fail : softfail
- set acl_c_spamscore = ${eval:$acl_c_spamscore + 50}
- set acl_c_spamlog = $acl_c_spamlog SPF fail;
- # За отсутствие записи SPF накидываем достаточное
- # для попадания в серый список количество очков
- warn !authenticated = *
- hosts = !+relay_from_hosts
- spf = none
- set acl_c_spamscore = ${eval:$acl_c_spamscore + 50}
- set acl_c_spamlog = $acl_c_spamlog SPF none;
- # Накидываем немного очков за некорректно оформленную SPF запись
- # или при возникновении ошибки при ее получении
- warn !authenticated = *
- hosts = !+relay_from_hosts
- spf = permerror : temperror : neutral
- set acl_c_spamscore = ${eval:$acl_c_spamscore + 25}
- set acl_c_spamlog = $acl_c_spamlog SPF syntax error or not received;
- # Проверка IP в черных списках. За каждое срабатывание правила
- # накидываем еще немного очков.
- #---------------------------------------------------------
- warn !authenticated = *
- hosts = !+relay_from_hosts
- dnslists = xen.spamhaus.org
- add_header = X-Warning: $sender_host_address is in a black list at $dnslist_domain
- set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
- set acl_c_spamlog = $acl_c_spamlog Blacklist xen.spamhaus.org;
- warn !authenticated = *
- hosts = !+relay_from_hosts
- dnslists = relay.mail-abuse.org
- add_header = X-Warning: $sender_host_address is in a black list at $dnslist_domain
- set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
- set acl_c_spamlog = $acl_c_spamlog Blacklist relay.mail-abuse.org;
- warn !authenticated = *
- hosts = !+relay_from_hosts
- dnslists = bl.spamcop.net
- add_header = X-Warning: $sender_host_address is in a black list at $dnslist_domain
- set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
- set acl_c_spamlog = $acl_c_spamlog Blacklist bl.spamcop.net;
- warn !authenticated = *
- hosts = !+relay_from_hosts
- dnslists = relays.ordb.org
- add_header = X-Warning: $sender_host_address is in a black list at $dnslist_domain
- set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
- set acl_c_spamlog = $acl_c_spamlog Blacklist relays.ordb.org;
- warn !authenticated = *
- hosts = !+relay_from_hosts
- dnslists = dns.rfc-ignorant.org
- add_header = X-Warning: $sender_host_address is in a black list at $dnslist_domain
- set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
- set acl_c_spamlog = $acl_c_spamlog Blacklist dns.rfc-ignorant.org;
- # Проверяем авторизованного пользователя на предмет подмены адреса отправителя
- deny message = Address ($sender_address) does not match with authenticated data ($authenticated_id). Check your email program settings.
- authenticated = *
- condition = ${if !eq{$sender_address}{$authenticated_id}{yes}{no}}
- accept
- # Данная ACL используется для каждой команды RCPT при получении писем.
- acl_check_rcpt:
- # Принять, если отправитель - локальный хост (т.е. не через TCP/IP).
- accept hosts = :
- control = dkim_disable_verify
- ###################################################################
- # Следующая секция ACL проверяет локальную часть адреса на предмет
- # содержания символов [@%!/|.(точка)] в правильных местах.
- #
- # Символы кроме точек часто находятся не на своих местах, такое часто
- # делают люди, которые надеются обойти ограничения. Поэтому, несмотря
- # на то, что они допустимы в локальных частях, эти правила блокируют
- # такие попытки.
- #
- # Пустые компоненты адреса (случай, когда в адресе стоят две точки
- # подряд) запрещены в RFC 2822, но Exim позволяет обойти такое
- # ограничение, потому что они встретились (х/з как тут перевести:
- # ....but Exim allows them because they have been encountered).
- # (Предполагается, что адрес имеет вид
- # "firstinitial.secondinitial.familyname", но что делать тем кто не имеет
- # "secondinitial"). Однако, локальная часть адреса, начинающаяся с
- # точки или содержащая /../ может доставить неприятности, если
- # используется как часть файла (например, для списка рассылки).
- # Такое же замечание справедливо и для локальных частей,
- # которые содержат наклонные черты. Символ переадресации
- # вывода (<, |, >) может также доставить проблемы, если локальная
- # часть легкомысленно включена в командную строку оболочки.
- #
- # В связи с этим для проверки используется два правила. Первое
- # используется для писем направленных для локальных доменов.
- # Строка "domains = +local_domains" реализовывает сказанное:
- # только локальные домены. Правило блокирует локальные части,
- # начинающиеся с точки или содержащие символы @ % ! / или |.
- # Если у вас есть локальные учетки имеющие в названии данные
- # символы, то вам необходимо модифицировать данное правило.
- deny message = Restricted characters in address
- domains = +local_domains
- local_parts = ^[.] : ^.*[@%!/|]
- # Второе правило применяется для остальных доменов и оно
- # не такое строгое как предыдущее.
- # Строка "domains = !+local_domains" указывает для каких доменов
- # применять правило. Данное правило позволяет локальным
- # пользователям отправлять письма во внешний мир, где адресаты
- # могут иметь косую или вертикальную черту в локальной части.
- # Так же правило блокирует адреса, локальная часть которых
- # начинается с точки, косой или вертикальной черты, но допускает
- # их использование в любом другом месте локальной части.
- # Локальная часть такого вида - /../ запрещена. Использование
- # символов @ % и ! запрещено, как и в предыдущем правиле.
- # Это сделано, чтобы локальные пользователи (или вирусы на их
- # компьютерах) не могли каким-либо образом осуществить
- # атаку на удаленный хост.
- deny message = Restricted characters in address
- domains = !+local_domains
- local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
- ###################################################################
- # Добавляем очков за то, что адрес отправителя совпадает с адресом получаетеля
- warn condition = ${if eq{$sender_address}{$local_part@$domain}{yes}{no}}
- set acl_c_spamscore = ${eval:$acl_c_spamscore+20}
- set acl_c_spamlog = $acl_c_spamlog Sender == recipient;
- # Добавляем очков за отправку письма на адрес-ловушку
- # P.S. В качестве адресов ловушек используются давно забытые заброшенные
- # адреса или специально созданные. То есть это обычный почтовый ящик.
- warn local_parts = spam : spamtrap
- domains = +local_domains
- set acl_c_spamscore = ${eval:$acl_c_spamscore+50}
- set acl_c_spamlog = $acl_c_spamlog Spamtrap;
- # Отправляем на следующую ACL,ку клиентов, набравших достаточное
- # количество очков для попадения в локальный черный список.
- accept condition = ${if >={$acl_c_spamscore}{100}{yes}{no}}
- # Принимать письма для пользователя postmaster для любого локального
- # домена независимо от источника и без проверки отправителя.
- #accept local_parts = postmaster
- # domains = +local_domains
- # Не принимать письма, если не удалось проверить отправителя.
- #require verify = sender
- deny !authenticated = *
- hosts = +relay_from_hosts
- !verify = sender
- # Добавляем очков за невозможность проверки существования адреса отправителя
- warn hosts = !+relay_from_hosts
- !verify = sender/callout=3m,defer_ok
- set acl_c_spamscore = ${eval:$acl_c_spamscore+20}
- set acl_c_spamlog = $acl_c_spamlog Callout error;
- # Проверять получателя во входящих письмах. Эта правило будет
- # проводить проверку локальной части для локальных доменов, а
- # а для удаленных проверку доменной части. Единственным способом
- # проверять локальную часть для удаленных доменов использовать
- # механизм обратных вызовов (добавить /callout), но сначала
- # прочитайте в документации про этот механизм.
- require verify = recipient
- # Принимать письма, которые приходят с хостов, для которых этот хост
- # является релеем. Подразумевается, что эти хосты скорее всего MUA,
- # так что здесь установлен модификатор control=submission, который
- # заставляет Exim работать в режиме передачи. Это позволит подправить
- # некоторые ошибки в письме, например, нет заголовка Date. Если этот
- # хост является релеем для других MTA, то вам может понадобиться
- # отключить эту плюшку. Если вы хотите пересылать письма с MTA
- # и в "режиме передачи" с MUA, то вы должны разделить это правило
- # на два и обрабатывать такие письма отдельно.
- accept hosts = +relay_from_hosts
- control = submission
- control = dkim_disable_verify
- # Принимать сообщение, если оно отправлено клиентом, прошедшим
- # аутентификацию.
- accept authenticated = *
- control = submission
- control = dkim_disable_verify
- # Запрещаем пересылать письма через нашу машину неизвестным
- # хостам.
- require message = relay not permitted
- domains = +local_domains : +relay_to_domains
- ###################################################################
- # Этот тест закомментирован, потому что подходит не для каждого случая.
- # Если вы включите этот тест, то будет производится проверка
- # Client SMTP Authorization (csa) хоста отправителя. Эта проверка включает
- # в себя просмотр записей SRV в DNS. CSA предложен для внедрения
- # в Интернет в мае 2005. Вы можете добавить дополнительные проверки
- # к этому тесту для того, чтобы не проверять какие-нибудь хосты методом
- # CSA.
- #
- # require verify = csa
- ###################################################################
- accept
- acl_check_predata:
- # Запрещаем письма, отправленные нескольким адресатам от "пустого" отправителя.
- deny message = Sorry, sender address <> disallowed for many rcpt commands
- senders = :
- condition = ${if >{$rcpt_count}{1}{yes}{no}}
- # Я пишу в лог дополнительную ифномарцию о сообщениях, которые
- # набрали немного спам очков, чтобы добавить еще какие-нибудь проверки,
- # если это сообщение все же окажется спамом.
- warn condition = ${if <{$acl_c_spamscore}{50}{yes}{no}}
- condition = ${if >{$acl_c_spamscore}{0}{yes}{no}}
- logwrite = Debug: $acl_c_spamlog
- # Принимаем сообщение, которые набрали мало спам очков
- accept condition = ${if <{$acl_c_spamscore}{50}{yes}{no}}
- # Помучаем хост небольшой задержкой
- warn delay = 20s
- # Блочим клиентов с большим количеством спам очков и добавляем их
- # в локальный черный список.
- deny message = Sorry, your spam score very high
- condition = ${if >={$acl_c_spamscore}{100}{yes}{no}}
- condition = ${lookup pgsql{\
- DELETE FROM "blacklist_tb" WHERE "ip" = '$sender_host_address';\
- INSERT INTO "blacklist_tb" VALUES ('$sender_host_address', DEFAULT)}{yes}{yes}}
- # Реализация серого списка. Сюда попадают клиенты, набравшие недостаточное
- # количество спам очков для попадания в локальный черный список, но
- # превысившие минимальный порог для прохождения письма. Эти хосты нельзя
- # отнести ни к легитимным ни к спам хостам, поэтому лучше еще помучить
- # их серым списком.
- #---------------------------------------------------------
- accept condition = ${lookup pgsql{\
- SELECT "ip" FROM "whitelist_tb" WHERE "ip" = '$sender_host_address' \
- AND "addrhash" = md5('$sender_address')\
- }{yes}{no}}
- defer message = Message deferred. Your address already exists in Greylist. Try again later.
- condition = ${lookup pgsql{\
- SELECT "ip" FROM "greylist_tb" WHERE "ip" = '$sender_host_address' \
- AND "addrhash" = md5('$sender_address$local_part@$domain') \
- AND "ctime" + 1740 > date_part('epoch'::text, now())\
- }{yes}{no}}
- delay = ${eval:$acl_c_spamscore/2}s
- accept condition = ${lookup pgsql{\
- SELECT "ip" FROM "greylist_tb" WHERE "ip" = '$sender_host_address' \
- AND "addrhash" = md5('$sender_address$local_part@$domain') \
- AND "ctime" + 1740 <= date_part('epoch'::text, now())\
- }{yes}{no}}
- condition = ${lookup pgsql{\
- DELETE FROM "greylist_tb" WHERE "ip" = '$sender_host_address' \
- AND "addrhash" = md5('$sender_address$local_part@$domain'); \
- INSERT INTO "whitelist_tb" VALUES('$sender_host_address', \
- md5('$sender_address'), DEFAULT)\
- }{yes}{yes}}
- defer message = Message deferred. Your address added to Greylist. Try again later.
- condition = ${lookup pgsql{\
- INSERT INTO "greylist_tb" VALUES('$sender_host_address',\
- md5('$sender_address$local_part@$domain'), DEFAULT);\
- }{yes}{yes}}
- delay = ${eval:$acl_c_spamscore/2}s
- deny
- # Этот ACL используется после того, как получено тело письма. В этом ACL
- # вы можете проверять тело письма или его заголовки, в частности здесь
- # можно отправить тело письма на проверку антивирусом или спам сканером.
- # Примеры некоторых тестов приведены ниже и закомментированы.
- # Без этих тестов данная ACL принимает все сообщения. Если вы хотите
- # использовать данные тесты, то Exim должен быть собран с
- # соответствующими опциями (WITH_CONTENT_SCAN=yes in Local/Makefile).
- acl_check_data:
- # Блочить письма с вирусами. Чтобы использовать данный тест
- # вы должны задать параметр av_scanner.
- deny malware = *
- message = This message contains a virus ($malware_name).
- # Добавить заголовки о набранных очках в спам тестах. Чтобы использовать
- # данный тест вы должны установить SpamAssassin и задать
- # параметр spamd_address.
- #
- # warn spam = nobody
- # add_header = 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
- # Блочить письма с неверным синтаксисом заголовков. При очень большом потоке
- # писем лучше отключить эту проверку.
- deny message = Invalid header syntax
- !verify = header_syntax
- # Добавляем заголовок в письмо с количеством набранным спам очков
- warn add_header = X-Spamscore: $acl_c_spamscore
- # Принять сообщение.
- accept
- #####################################################################
- # Параметры роутеров
- #####################################################################
- # Здесь важен порядок, в котором заданы роутеры.
- # Адрес передается по порядку в роутеры до тех пор,
- # пока какой-нибудь не подойдет.
- #####################################################################
- begin routers
- # Этот роутер направляет почту на удаленные машины через SMTP,
- # когда получатель указан в виде IP адреса, например,
- # <user@[192.168.35.64]>. В RFC требуется, чтобы почтовик умел
- # работать с такими письмами. Однако, в наши дни такие адреса
- # практически нигде не используются, разве что только спамерами.
- # Поэтому данный роутер по умолчанию закомментирован. Если
- # вы его раскомментируете, то вы также должны раскомментировать
- # параметр allow_domain_literals, тобы Exim не считал такие адреса
- # синтаксически неверными.
- # domain_literal:
- # driver = ipliteral
- # domains = ! +local_domains
- # transport = remote_smtp
- # Данный роутер отправляет письма, если они не предназначены
- # локальным, на удаленные домены. Знак восклицания в записи
- # "domains = ! +local_domains" означает отрицание, что можно
- # читать как "не".
- #
- # Любой домен, адрес которого 0.0.0.0 или 127.0.0.0/8 обрабатывается
- # так, как будто у него нет DNS записи. Учтите, адрес 0.0.0.0 тоже самое,
- # что и 0.0.0.0/32, который означает в большинстве систем, что это
- # локальный хост. Если DNS запрос не дал результатов, то адрес
- # не направляется в другие роутеры, так как здесь указан параметр
- # 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
- # Остальные роутеры обрабатывают адреса в локальных доменах,
- # которые определены в "domainlist local_domains".
- # Роутер обрабатывает алиасы, ища их в файле с именем
- # SYSTEM_ALIASES_FILE. Значение подставляется автоматом
- # на этапе сборки. По умолчанию файл располагается здесь:
- # /etc/aliases. Если у вас данный файл располагается в другом
- # месте, то вам необходимо указать правильный путь до него
- # в параметре "data".
- #
- ##### NB Данный файл должен всегда существовать в системе.
- ##### NB Практически в каждой Unix системе он есть, потому что
- ##### NB используется Sendmail. В наши дни, в некоторых системах
- ##### NB данный файл может отсутствовать. Файл должен
- ##### NB содержать как минимум одну запись - для "postmaster".
- #
- # Если ваш алис разворачивается в трубу (pipe) или файл,тогда вам
- # нужно задать пользователя, под которым будет происходить работа
- # с трубой или файлом. Если вам необходимо, то вы можете
- # раскомментировать (и изменить) опцию "user" ниже, а так же
- # добавить опцию "group". Есть другой способ - указать опцию
- # "user" в транспортах.
- system_aliases:
- driver = redirect
- allow_fail
- allow_defer
- data = ${lookup{$local_part}lsearch{/etc/aliases}}
- user = mailnull
- group = mail
- file_transport = address_file
- pipe_transport = address_pipe
- virtual_aliases:
- driver = redirect
- allow_fail
- allow_defer
- data = CHECK_VIRTUAL_ALIASES
- user = mailnull
- group = mail
- # Этот роутер пересылает почту согласно файлу .forward в директории
- # пользователя. Если вы хотите фильтровать почту, тогда файл
- # .forward должен начинаться со строки "# Exim filter" или "# Sieve filter",
- # так же необходимо раскомментировать опцию "allow_filter".
- # Опция no_verify нужна для того, чтобы пропустить данный роутер,
- # когда Exim проверяет адрес. Аналогично, опция no_expn нужна,
- # чтобы роутер пропускался, когда Exim обрабатывает команду EXPN.
- # Если вы хотите, чтобы роутер понимал локальную часть адреса
- # с суффиксами (символом "-" или "+") так, как будто их нет, то
- # раскомментируйте пару опций local_part_suffix. Например, адрес
- # xxxx-foo@your.domain будет воспринят как xxxx@your.domain
- # данным роутером. Если вы раскомментируете эти опции, то вам
- # нужно будет сделать подобные изменения в роутере localuser
- # (так надо, потому что данный роутер не используется при проверке
- # существования пользователя).
- # Опция check_ancestor означает, что если файл .forward генерирует
- # адрес, который является предыдущим для этого (то есть обратно
- # отправителю), то такое правило будет просто опущено.
- # Предотвращает случай, когда есть такие алиасы A -> B, а у B
- # B -> A.
- # Один из трех транспортов используется при пересылке,
- # в зависимости от указанных правил в файле .forward.
- #userforward:
- # driver = redirect
- # check_local_user
- # local_part_suffix = +* : -*
- # local_part_suffix_optional
- # file = $home/.forward
- # allow_filter
- # no_verify
- # no_expn
- # check_ancestor
- # file_transport = address_file
- # pipe_transport = address_pipe
- # reply_transport = address_reply
- # condition = ${if exists{$home/.forward} {yes} {no} }
- # Данный роутер срабатывает, если письмо пришло для зарегистрированного
- # пользователя в системе. Если доставка не удалась, то генерируется
- # сообщение об ошибке - "Unknown user".
- virtual_user:
- driver = accept
- transport = dovecot_delivery
- domains = +local_domains
- condition = CHECK_VIRTUAL_USER
- no_more
- #####################################################################
- # Настройка транспортов
- #####################################################################
- # Порядок транспортов не имеет значения.
- # Только один транспорт отрабатывает при каждой доставке.
- #####################################################################
- # Транспорт используется только после обработки письма роутером.
- begin transports
- # Этот транспорт используется для доставки писем по SMTP.
- # Практически для всех доменов я использую технологию DKIM.
- # Подписывать сообщение или нет, определяется в параметре
- # dkim_private_key, если он будет пуст, либо 0, либо false, то
- # сообщение подписано не будет.
- #
- # Сгенерировать ключ для домена можно так:
- # openssl genrsa -out domain.key 1024
- # Вывод конмады (открытый ключ):
- # openssl rsa -in info-x.org.key -pubout
- # Разместить в DNS записе домена, например:
- # _dkim._domainkey.example.net IN TXT "v=DKIM1; k=rsa; t=s; p=your_key"
- # Описание ключей можно без проблем найти в RFC.
- # Полезным будет добавление еще одной записи в зону:
- # _adsp._domainkey.example.net IN TXT "dkim=all"
- # Данная запись означает, что все сообщения для данного домена
- # должны быть подписаны. То есть принимающая сторона, увидев
- # данную запись будет принимать соответствующие решения, если
- # например, вдруг письмо, отправленное с этого домена окажется
- # не подписанным.
- remote_smtp:
- driver = smtp
- dkim_domain = ${lc:${domain:$h_from:}}
- dkim_selector = _dkim
- dkim_private_key = ${if exists{DKIM_DIRECTORY/${dkim_domain}.key}{DKIM_DIRECTORY/${dkim_domain}.key}{false}}
- dkim_canon = relaxed
- dkim_strict = yes
- # Этот транспорт используется для доставки писем в ящики локальных
- # пользователей в традиционном для BSD формате - mailbox.
- # По умолчанию процесс доставки запускается с правами пользователя
- # (uid, gid), поэтому необходимо, чтобы был установлен sticky бит
- # на директорию /var/mail. В некоторых системых доставка
- # осуществляется по другому - вместо sticky бита используется общая
- # группа. Закомментированные опции показывают как такое может быть
- # реализовано в Exim.
- #local_delivery:
- # driver = appendfile
- # file = /var/mail/$local_part
- # delivery_date_add
- # envelope_to_add
- # return_path_add
- # group = mail
- # user = $local_part
- # mode = 0660
- # no_mode_fail_narrower
- # Транспорт доставки писем для виртуальных пользователей.
- # При использовании данного транспорта Exim сам будет сохранять письма
- # в почтовый ящик.
- # Раньше у меня он работал так, но щас письма доставляются с использованием
- # Dovecot LDA. Поэтому этот транспорт не используется в данной конфигурации.
- # Удалять не стал, вдруг пригодится где-нибудь.
- #virtual_delivery:
- # driver = appendfile
- # create_directory
- # delivery_date_add
- # envelope_to_add
- # return_path_add
- # message_prefix =
- # message_suffix =
- # maildir_format
- # maildir_tag = ,S=$message_size
- # maildir_use_size_file
- # mode = 0600
- # directory_mode = 0700
- # group = GET_VIRTUAL_GROUP
- # user = GET_VIRTUAL_USER
- # directory = GET_VIRTUAL_DIR
- # quota = GET_VIRTUAL_QUOTA
- # quota_size_regex = ,S=(\d+)
- # quota_is_inclusive = false
- # Транспорт доставки писем для виртуальных пользователей.
- # Сохранение писем в ящик возложено на плечи Dovecot LDA.
- dovecot_delivery:
- driver = pipe
- command = /usr/local/libexec/dovecot/dovecot-lda -e -d $local_part@$domain -f $sender_address -a $original_local_part@$original_domain
- message_prefix =
- message_suffix =
- delivery_date_add
- envelope_to_add
- return_path_add
- return_fail_output
- log_output
- umask = 077
- group = GET_VIRTUAL_GROUP
- user = GET_VIRTUAL_USER
- temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78
- # Этот транспорт используется при доставке писем, адресаты
- # которых были сгенерированы через файл алиасов или .forward.
- # Если pipe что-нибудь выводит на стандартный дескриптор вывода,
- # то этот вывод используется как сообщение об ошибке
- # и направляется отправителю. Если вы хотите, чтобы сообщение
- # отправлялось только в случае ошибки, то используйте опцию
- # return_fail_output вместо return_output. если оно вам нужно, то
- # можете сделать различные транспорты для файла алиасов
- # и файла .forward.
- address_pipe:
- driver = pipe
- return_output
- # Этот транспорт используется для доставки писем в файлы,
- # адреса которых были сгенерированы файлом алиасов или
- # файлом .forward.
- address_file:
- driver = appendfile
- delivery_date_add
- envelope_to_add
- return_path_add
- # Транспорт используется для обработки автоответов.
- address_reply:
- driver = autoreply
- ######################################################################
- # Конфигурация повторных попыток передачи
- ######################################################################
- begin retry
- # Это единственное правило применяется для всех доменов и для всех типах
- # ошибок. Повторные попытки будут происходить каждые 15 минут в течении
- # 2 часов. После чего эти интервалы будут увеличены, начиная с 1 часа и
- # увеличивая каждый раз в 1.5 раза до 16 часов. После повторная передача
- # будет производиться каждые 6 часов, до тех пор, пока не пройдет 4 дня
- # с первой неудачной попытки.
- # Осторожно: Если вы не сконфигурируете повторную передачу (т.е., если
- # этой секции не будет или она будет пустой), то Exim не будет делать
- # повторных попыток передачи вообще. Поэтому, не удаляйте это правило,
- # если в этом нет необходимости.
- # Address or Domain Error Retries
- # ----------------- ----- -------
- * * F,2h,15m; G,16h,1h,1.5; F,4d,6h
- ######################################################################
- # Параметры перезаписи
- ######################################################################
- # There are no rewriting specifications in this default configuration file.
- begin rewrite
- ######################################################################
- # Параметры аутентификации
- ######################################################################
- # Следующие аутентификаторы поддерживают аутентификацию открытым
- # текстом, используя стандартные механизмы PLAIN и LOGIN. Данные
- # механизмы поддерживает большинство почтовых клиентов.
- #
- # Аутентификаторы не настроены до конца, поэтому вам необходимо
- # задать параметр server_condition, чтобы Exim мог проверять
- # переданные учетные данные.
- #
- # По умолчанию в правиле RCPT ACL есть проверка на предмет
- # зареганого пользователя и если он прошел его, то письмо будет принято
- # независимо от того, окуда оно будет отправляться.
- begin authenticators
- # PLAIN метод. Клиент отправляет идентификатор сессии (который тут
- # не используется), логин и пароль. После, доступ к логину и паролю
- # можно получить через переменные $auth2 и $auth3 и проверить
- # их корректность.
- # Аутентификация пользователя проводится средствами Dovecot.
- # Правило server_advertise_condition = ${if def:tls_cipher } запрещает
- # пользователям проходить аутентификаю, если соединение не защищено.
- PLAIN:
- driver = dovecot
- public_name = PLAIN
- server_set_id = $auth1
- server_socket = /var/run/dovecot/auth-client
- server_advertise_condition = ${if def:tls_cipher }
- # LOGIN метод. Здесь нет идентификатора сессии, поэтому логин
- # и пароль доступны через переменные $auth1 и $auth2.
- # Аутентификация пользователя проводится средствами Dovecot.
- # Правило server_advertise_condition = ${if def:tls_cipher } запрещает
- # пользователям проходить аутентификаю, если соединение не защищено.
- LOGIN:
- driver = dovecot
- public_name = LOGIN
- server_set_id = $auth1
- server_socket = /var/run/dovecot/auth-client
- server_advertise_condition = ${if def:tls_cipher }
- ######################################################################
- # Конфигурация local_scan()
- ######################################################################
- # Если вы собрали Exim с поддержкой функции local_scan(), которая
- # содержит таблицы для приватных опций, то здесь вы можете указать их.
- # Не забудьте раскомментировать строку с "begin". По умолчанию
- # закомментирована, потому что вылезет ошибка, если Exim собран
- # без данной плюшки.
- # begin local_scan
- # Конец конфигурационного файла
- ^.*([0-9]+).([0-9]+).([0-9]+).([0-9]+).*
- ^.*dhcp.*
- ^.*host.*
- ^.*dsl.*
- ^.*dial.*
- ^.*broad.*
- ^.*band.*
- ^.*user.*
- ^.*pool.*
- ^.*client.*
- ^.*cable.*
- ^.*pppoe.*
- ^.*hsd.*
- ^.*dyn.*
- ^.*static.*
- ^.*ppp.*
- ^.*speedy.*
- ^.*customer.*
- #!/usr/bin/env perl
- use DBI;
- use strict;
- use warnings;
- my $db_user = 'vmail';
- my $db_pass = 'vmail';
- my $db_host = '192.168.7.253';
- my $db_port = 5432;
- my $db_dsn = "DBI:Pg:db=mail_system;host=$db_host;port=$db_port";
- my %con_attr = (
- 'RaiseError' => 1,
- 'PrintError' => 1,
- 'AutoCommit' => 1
- );
- my $query = '
- DELETE FROM "blacklist_tb" WHERE "ctime" <= date_part($$epoch$$, now()) - 1209600;
- DELETE FROM "greylist_tb" WHERE "ctime" <= date_part($$epoch$$, now()) - 604800;
- DELETE FROM "whitelist_tb" WHERE "ctime" <= date_part($$epoch$$, now()) - 2678400;
- ';
- $dbh->disconnect();
- sendmail /usr/local/sbin/exim
- send-mail /usr/local/sbin/exim
- mailq /usr/local/sbin/exim -bp
- newaliases /usr/local/sbin/exim -bi
- hoststat /usr/local/sbin/exim
- purgestat /usr/local/sbin/exim
- daily_status_include_submit_mailq="NO"
- daily_clean_hoststat_enable="NO"
- daily_queuerun_enable="NO"
- daily_submit_queuerun="NO"
4.3 Запуск и проверка конфигурации
Для автоматического запуска Exim во время старта системы необходимо добавить следующие строки в /etc/rc.conf:- # echo 'sendmail_enable="NONE"' >> /etc/rc.conf
- # echo 'sendmail_submit_enable="NO"' >> /etc/rc.conf
- # echo 'exim_enable="YES"' >> /etc/rc.conf
- # service exim start
- # sockstat -4 -l | grep exim
- smmsp exim-4.80. 88757 3 tcp4 *:25 *:*
- smmsp exim-4.80. 88757 4 tcp4 *:465 *:*
- smmsp exim-4.80. 88757 5 tcp4 *:587 *:*
- # telnet 127.0.0.1 25
- Trying 127.0.0.1...
- Connected to localhost.
- Escape character is '^]'.
- 220 mx.info-x.org ESMTP MTA :)
- HELO localhost
- 250 mx.info-x.org Hello localhost [127.0.0.1]
- MAIL FROM: <test@info-x.org>
- 250 OK
- RCPT TO: <nekit@info-x.org>
- 250 Accepted
- DATA
- 354 Enter message, ending with "." on a line by itself
- From: <test@info-x.org>
- To: <nekit@info-x.org>
- Subject: Test message
- Hello world!!!
- .
- 250 OK id=1U9KRy-000M9i-7F
- QUIT
- 221 mx.info-x.org closing connection
- Connection closed by foreign host.
- # cat /var/log/exim/mainlog | grep 1U9KRy-000M9i-7F
- 2013-02-24 01:09:28 1U9KRy-000M9i-7F <= test@info-x.org H=(localhost) [127.0.0.1] I=[127.0.0.1]:25 P=smtp S=387 from <test@info-x.org> for nekit@info-x.org
- 2013-02-24 01:09:28 1U9KRy-000M9i-7F => nekit <nekit@info-x.org> R=virtual_user T=dovecot_delivery
- 2013-02-24 01:09:28 1U9KRy-000M9i-7F Completed