Перевод выполнен Алексеем Паутовым в рамках некоммерческого проекта RussianLDP (http://www.rldp.ru/). Именно на этом сайте и надлежит искать новые версии, если таковые будут.

46. Некоторые общие конфигурационые опции

В этой главе обсуждаются некоторые конфигурационные настройки, которые кажутся наиболее общими.

46.1. Отсылка почты на умный хост

Если Вы хотите отсылать всю почту для нелокальных доменов на умный хост (smart host), Вы должны заменить роутер по умолчанию dnslookup на роутер явно задающий роутинг:
send_to_smart_host:
  driver = manualroute
  route_list = !+local_domains smart.host.name
  transport = remote_smtp

Если необходимо, можете использовать IP-адрес умного хоста вместо имени. Если используете exim лишь для передачи сообщений на умный хост, а не для получения входящих сообщений, должны принять меры для синхронизации подачи путём установки опции mua_wrapper (смотрите главу 47).

46.2. Использование exim для обработки списков рассылки

Exim может быть использован для запуска простого списка рассылки, но для больших и/или сложных требований рекомендуется использование дополнительного ПО для управления списками рассылки, типа Majordomo или Mailman.

Роутер redirect может быть использован для обработки списков рассылки, где каждый список поддерживается в отдельном файле, который поэтому может управляться независмыми менджерами. Опция domains роутера может использоваться для запуска этих списков в отдельных от нормальной почты доменах. Например:
lists:
  driver = redirect
  domains = lists.example
  file = /usr/lists/$local_part
  forbid_pipe
  forbid_file
  errors_to = $local_part-request@lists.example
  no_more

Этот роутер пропущен для доменов, иных нежели lists.example. Для адресов в этих доменах он ищет файл, совпадающий с локальной частью. Если файла нет, роутер не выполняется, но, поскольку установлена no_more, последующие роутеры не проверяются, и вся доставка заканчивается неудачей.

Опции forbid_pipe и forbid_file предотвращают раскрытие локальной части в доставку в канал или файл, что обычно неуместно в списках рассылки.

Опция errors_to задаёт, что любые ошибки доставки, вызыванные адресами взятыми из списка рассылки, должны быть отосланы на заданный адрес, а не оригинальному отправителю сообщения. Однако, до этого действия exim проверяет ошибочный адрес и игнорирует, если его проверка неудачна.

Например, используя конфигурацию выше, почта, посланная на dicts@lists.example, передаётся на адреса, содержащиеся в /usr/lists/dicts, с направлением сообщений об ошибках на dicts-request@lists.example при условии, что этот адрес может быть проверен. Также возможно, что тут мог бы быть файл с именем /usr/lists/dicts-request, содержащий адрес менеджера данного специфического списка, но иным подходом, типа установки более раннего роутера (возможно, использующего опции local_part_prefix или local_part_suffix) для обработки адресов в форме owner-xxx или xxx-request.

46.3. Синтаксические ошибки в списках рассылки

Если вхождение в данных перенаправления содержит синтаксическую ошибку, exim обычно задерживает доставку оригинального адреса. Это означает, что ошибка синтаксиса в списке рассылки задержит все доставки на этот список. Это может быть неподходящим, когда список обслуживается автоматически из данных, предоставленных пользователями, и адреса не проверены строго.

Если установлена опция skip_syntax_errors, роутер redirect просто пропускает вхождения, которые не может распарсить, отмечая инцидент в протоколах. Если дополнительно syntax_errors_to установлена в адрес, который можно проверить, сообщение посылается на него при каждом пропуске битого адреса. Обычно syntax_errors_to устнавливается в тот же адрес, что и errors_to.

46.4. Повторное раскрытие списков рассылки

Exim запоминает каждый индивидуальный адрес, на который было доставлено сообщение, для избежания дублирования, но обычно он сохраняет лишь оригинальный адрес получателя сообщения. Если все доставки на список рассылки не могут быть завершены в первую попытку, список рассылки раскрывается повторно, когда происходит следующая попытка доставки. Это означает, что изменения списка примаются во внимание при каждой попытке доставки, таким образом, адреса, которые были добавлены к списку с того времени как пришло сообщение, также получат копию сообщения, несмотря на то, что оно предшествовало их подписке.

Если такое поведение нежелательно, в роутере redirect может быть установлена опция one_time. Если это сделано, любые сгенерированные роутером адреса, которые не удалось доставить при первой попытке, добавляются к сообщению как верхний уровень (top level) адресов, и сгенерировавший их родительский адрес помечается как доставленный (delivered). Таким образом, раскрытие списков рассылки не происходит заново в последующие попытки доставки. Неудобство этого в том, что если любой неудачный адрес некоректен, его исправление в файле не имеет эффекта для предыдущих сообщений.

Оригинальный адрес высшего уровня запоминается с каждым сгенерированным адресом и выводится в протоколах. Однако, любые промежуточные родительские адреса не записываются. Это делает различие для протоколов лишь если установлен селектор all_parents, но так или иначе для списков рассылки обычен лишь один уровень раскрытия.

46.5. Закрытые списки рассылки

Примеры, пока предполагали открытые списки рассылки, в которые любой может послать почту. Также возможно настроить закрытые списки, где почта принимается лишь от специфических отправителей. Это производится путём использования общей опции senders для ограничения роутера, обрабатывающего список. Следующий пример использует один и тот же файл как список получателей и список разрешённых отправителей. Он требует трёх роутеров:
lists_request:
  driver = redirect
  domains = lists.example
  local_part_suffix = -request
  file = /usr/lists/$local_part
  $local_part_suffix
  no_more

lists_post:
  driver = redirect
  domains = lists.example
  senders = ${if exists {/usr/lists/$local_part} \
             {lsearch;/usr/lists/$local_part}{*}}
  file = /usr/lists/$local_part
  forbid_pipe
  forbid_file
  errors_to = $local_part-request@lists.example
  no_more

lists_closed:
  driver = redirect
  domains = lists.example
  allow_fail
  data = :fail: $local_part@lists.example is a closed mailing list

Все три роутера имеют одну и ту же установку domains, таким образом, для любых других доменов они пропущены. Первый роутер запускается, лишь если локальная часть завершается на -request. Он обрабатывает сообщения к менеджеру списка путём открытого списка рассылки.

Второй роутер запускается, лишь если удовлетворено предварительное условие senders. Он проверяет существование списка, соответствующего локальной части, а затем с помошью линейного поиска проверяет, что отправитель находится в списке. До попытки поиска по файлу необходимо проверить его существование, поскольку иначе exim подумает, что произошла конфигурационная ошибка. Если файл не существует, раскрытие senders приводит к *, что соответствует всем отправителям. Это означает, что роутер работает, но, поскольку нет списка, от него отказываются, и no_more гарантирует, что дальнейшие роутерыне запускаются. Адрес неудачен с ошибкой unrouteable address.

Третий роутер запускатся, лишь если второй роутер пропущен, что происходит когда список рассылки существует, но отправитель не в нём. Этот роутер принудительно создаёт неудачу адреса, давая подходящее сообщение об ошибке.

46.6. Переменные пути возврата конверта (VERP)

Variable Envelope Return Paths смотрите http://cr.yp.to/proto/verp.txt являются способом помочь администраторам списков рассылок обнаружить, какой адрес подписки является причиной специфической неудачи доставки. Идея в кодировании оригинального получателя адреса в исходящем адресе отправителя конверта, таким образом, если сообщение форвардится путём другого хоста и впоследствии создаётся рикошет, оригинальный получатель может быть извлечён из адреса получателя рикошета.

Адрес отправителя конверта может быть модифицирован exim, используя два различных средства: опцию errors_to в роутере (как показано в предыдущих примерах списков рассылки) или транспортную опцию return_path. Второй из них эффективен, лишь если сообщение успешно доставлено на иной хост, она не используется для ошибок, детектируемых на локальном хосте (смотрите описание return_path в части 24). Вот пример использования return_path для осуществления VERP в транспорте smtp:
verp_smtp:
  driver = smtp
  max_rcpt = 1
  return_path = \
    ${if match {$return_path}{^(.+?)-request@your.dom.example\$} \
      {$1-request=$local_part%$domain@your.dom.example}fail}

Он имеет эффект перезаписи обратного пути (отправителя конверта) в исходящих SMTP-сообщениях, если локальная часть оригинального получателя завершается на -request, и домен your.dom.example. Перезапись вставляет локальную часть и домен получателя в путь возврата. Предположим, например, что сообщение, чей путь возврата установлен в somelist-request@your.dom.example, посылается на subscriber@other.dom.example. В транспорте путь возврата переписывается как:
somelist-request=subscriber%other.dom.example@your.dom.example

Чтобы это работало, Вы также должны сделать, чтобы исходящие сообщения, которые имеют в своём пути возврата -request, имели лишь одного получателя. Это достигается путём установки max_rcpt в 1. Без этого одна копия сообщения может быть послана нескольким различным получателям в одном домене, когда $local_part недоступна в транспорте, поскольку она не уникальна.

Если Ваш хост не только производит доставки списков рассылки, Вы, вероятно, должны использовать отдельный транспорт для доставок VERP, чтобы не использовать дополнительные ресурсы для других. Это легко может быть сделано путём раскрытия опции transport в роутере:
dnslookup:
  driver = dnslookup
  domains = ! +local_domains
  transport = \
    ${if match {$return_path}{^(.+?)-request@your.dom.example\$}\
      {verp_smtp}{remote_smtp}}
  no_more

Если Вы хотите изменить путь возврата, используя errors_to в роутере вместо использования return_path в транспорте, Вам необходимо установить errors_to во всех роутерах, которые обрабатывают адреса списков рассылок. Это будет гарантировать, что все ошибки доставки, включая детектируемые на локальном хосте, посылаются на адреса VERP.

На хосте, который не делает локальных доставок и не имеет ручного роутинга, в изменении нуждается лишь роутер dnslookup. Для доставко SMTP не нужен специальный транспорт. Каждый получатель списка рассылки имеет свой собственный путь возврата, и таким образом exim должен передать их транспорту по одному. Вот пример роутера dnslookup, который осуществляет VERP:
verp_dnslookup:
  driver = dnslookup
  domains = ! +local_domains
  transport = remote_smtp
  errors_to = \
    ${if match {$return_path}{^(.+?)-request@your.dom.example\$}}
     {$1-request=$local_part%$domain@your.dom.example}fail}
  no_more

До того, как Вы начнёте рассылать сообщения с VERP путём возврата, Вы также должны сконфигурировать exim на приём рикошетов, которые возвращаются с таким путём. Обычно это производится путём установки опции local_part_suffix для роутера и использования этого для роутинга сообщения туда, где Вы его хотели бы обработать.

Накладные расходы при использовании VERP очень сильн о зависят от размера сообщения, числа получателей адресов, которые ресолвятся на один и тот же удалённый хост, и скорости соединения, через которое посылается сообщение. Если много адресов ресолвятся на один и тот же хост, а соединение медленное, посылка отдельной копии сообщения для каждого адреса может быть существенно дольше, чем посылка одной копии сообщения с многими получателями (что не может использоваться с VERP).

46.7. Виртуальные домены

Фраза virtual domain, к сожалению, используется для двух различных смыслов:

Первое использование, вероятно, наиболее часто, и действительно кажется более виртуальным, чем второе. Этот вид доменов может быть обработан exim прямым роутером алиасов. Один подход состоит в создании отдельного файла алиасов для каждого виртуального домена. Exim может проверять существование файла алиасов для определения, существует ли домен. Тут полезен тип поиска dsearch, приводя к роутеру такой формы:
virtual:
  driver = redirect
  domains = dsearch;/etc/mail/virtual
  data = ${lookup{$local_part}lsearch{/etc/mail/virtual/$domain}}
  no_more

Опция domains определяет, что роутер будет пропущен, если нет файла в каталоге /etc/mail/virtual, чьё имя такое же, как и обрабатываемый домен. Когда роутер работает, он ищет локальную часть в файле для нахождения нового адреса (или списка адресов). Установка no_more обеспечивает, что если поиск неудачен (приводит к data, являющейся пустой строкой), exim оставляет адрес, не пробуя последующие роутеры.

Этот роутер может обрабатывать все вирутальные домены, поскольку имена файлов алиасов следуют за фиксированым шаблоном. Разрешения могут быть разданы так, чтобы соответствующие люди могли редактировать различные файлы алиасов. Успешная операция алиасинга приводит к новому адресу получателя конверта, который затем роутится сначала.

Другой вид виртуальных доменов также может быть обработан прямым методом. Один подход состоит в создании файла для каждого домена, содержащего список действительных локальных частей, и используется в роутере типа такого:
my_domains:
  driver = accept
  domains = dsearch;/etc/mail/domains
  local_parts = lsearch;/etc/mail/domains/$domain
  transport = my_mailboxes

Адрес принимается, если есть файл для домена, а локальная часть может быть найдена в файле. Опция domains используется для проверки на существование файла, поскольку domains проверяется до опции local_parts (смотрите секцию 3.12). Вы не можете использовать require_files, поскольку эта опция проверяется после local_parts. Транспорт таков:
my_mailboxes:
  driver = appendfile
  file = /var/mail/$domain/$local_part
  user = mail

Он использует каталог почтовых ящиков для каждого домена. Установка user требуется для задания, какой uid будет использоваться для записи в почтовые ящики.

Конфигурация, показанная здесь, лишь один пример, как Вы можете поддерживать это требование. Есть много других путей, которыми может быть настроен этот вид конфигурации, например, путём использования БД вместо раздельных файлов для хранения всей информации о доменах.

46.8ю Многочисленные пользовательские почтовые ящики

Большие пользователи почты часто хотят работать с многими почтовыми ящиками, в которых входящая почта сортируется автоматически. Популярный способ обработать это: разрешить пользователям использовать несколько адресов отправителя, таким образом, ответы могут быть легко идентифицированы. Для этой цели пользователям разрешают добавлять префиксы или суффиксы к их локальным частям. Для этой цели могут быть использованы средства групповых символов общих опций роутера local_part_prefix и local_part_suffix. Например, рассмотрите такой роутер:
userforward:
  driver = redirect
  check_local_user
  file = $home/.forward
  local_part_suffix = -*
  local_part_suffix_optional
  allow_filter

Он запускает пользовательский файл .forward для всех локальных частей формы username-*. В пределах файла фильтра пользователь может различать различные случаи путём проверки переменной $local_part_suffix. Например:
if $local_part_suffix contains -special then
   save /home/$local_part/Mail/special
endif

Если файл фильтра не существует или не имеет дело с такими адресами, они передаются следующим маршрутизаторам и (предполагая, что далее не используется опция local_part_suffix) они, по-видимому, будут неудачны. Таким образом, пользователь может контролировать, какие суффиксы являются действительными.

Альтернативно, суффикс может использоваться для вызова другого файла .forward, который является способом воплощения подобного средства в другом MTA:
userforward:
  driver = redirect
  check_local_user
  file = $home/.forward$local_part_suffix
  local_part_suffix = -*
  local_part_suffix_optional
  allow_filter

Если нет никакого суффикса, используется .forward, если суффикс -special, например, используется .forward-special. Ешё раз, если соответствующий файл не существует или не имеет дела с адресом, он передаётся последующим роутерам, которые, если требуется, ищут неполный файл .forward для использования.

46.9. Упрощённая обработка отпуска (vacation)

Традиционный способ запуска программы vacation для пользователей: установить команду канала в файле .forward (для деталей синтаксиса смотрите раздел 26.6). Это распространённая ошибка у неопытных пользователей. Есть две особенности exim, которые могут быть использованы для упрощения этого процесса для пользователей: