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

Перевод выполнен Алексеем Паутовым в рамках некоммерческого проекта 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, к сожалению, используется для двух различных смыслов:

  • Домен, для которого нет реальных почтовых ящиков: все действительные локальные части алиасы для лругих почтовых адресов. Общие примеры: организационные домены верхнего урвоня и тщеславные (vanity) домены.
  • Один из множества незавсимых доменов, которые обрабатываются одним и тем же хостом, с почтовыми ящиками на этом хосте, но владельцы почтовых ящиков не обязательно обладают логином на этом хосте.

Первое использование, вероятно, наиболее часто, и действительно кажется более виртуальным, чем второе. Этот вид доменов может быть обработан 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, которые могут быть использованы для упрощения этого процесса для пользователей:

  • Префикс локальной части, типа vacation-, может быть задан в роутере, который используется для непосредственной доставки сообщений к программе vacation, или, альтернативно, может использоваться транспорт exim autoreply. Тогда содержимое пользовательского файла vacation намного более простое. Например:
    spqr, vacation-spqr
    
  • Общая опция роутеров require_files может использоваться для вызова доставки отпуска путём проверки существования определённого файла в домашнем каталоге пользователя. Также должна использоваться общая опция unseen для гарантии, что произойдёт оригинальная доставка. В этом случае все использующие это пользователи, должны создать файл, называемый, скажем, .vacation, содержащий сообщение об отпуске. Другое преимущество обоих этих методов состоит в том, что они оба работают, даже когда пользователям запрещено использование произвольных каналов.

    46.10. Отбор копий сообщений

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

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

    46.11. Периодически подключенные хосты

    Для хостов стало весьма обычным (поскольку дешевле) подключаться к интернету периодически, а не всё время быть подключенными. Обычная настройка для таких хостов то, что почта для них накапливается на системе, постоянно соединенённой с интернетом.

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

    46.12. Exim на вышестоящих серверных хостах

    Exim принимает меры, чтобы входящая почта для периодически подключаемых хостов оставалась в очереди exim, пока клиент не подключится. Однако, этот подход не очень хорошо масштабируется. Два различных вида ожидания сообщения смешиваются в одной очереди: те, которые нельзя доставить из-за каких-то временных проблем, и те, которые ждут соединения их хоста назначения. Это делает тяжёлым управление очередью так же, как и растрату ресурсов, поскольку каждый обработчик очереди сканирует всю очередь.

    Лучший подход состоит в отделении тех сообщений, которые ждут временно подключаемых хостов. Это может быть сделано путём доставки этих сообщений в локальные файлы пакетного SMTP, mailstore или иной формат, сохраняющий конверт, из которого они передаются путём иного программного обеспечения к их месту назначения. Это облегчает сборку всей почты для одного хоста в одном каталоге и применения правил локального таймаута на основании сообщений, если требуется.

    Для очень небольшого масштаба можно сделать, чтобы exim оставлял почту в очереди. Если Вы это делаете, Вы должны сконфигурировать exim с длинным периодом повтора для временно подключенных хостов. Например:

    cheshire.wonderland.fict.example    *   F,5d,24h
    

    Этим останавливается множество неудачных попыток доставки, но exim запоминает, какие сообщения находились в очереди для этого хоста. Как только непостоянный хост появляется в сети, принудительная доставка одного сообщения (используя опции -M или -R) или путём использования команды ETRN SMTP (смотрите раздел 44.8) вызывает доставку всех находящихся в очереди сообщений, часто по одному соединению. Когда хост остаётся на связи, любые новые сообщения доставляются немедленно.

    Если подключающиеся хосты не имеют фиксированного IP-адреса, то есть хост появляется каждый раз с различным IP-адресом, механизмы повтора на хосте-владельце запутываются, поскольку IP-адрес обычно используется как часть ключевой строки для информации повторов. Этого можно избежать путём сброса retry_include_ip_address в smtp транспорте. Так как это неудобно для хостов, постоянно связанных с интернет, для периодически связанных хостов лучше организовать отдельный транспорт.

    46.13. Exim на периодически подключаемом клиентском хосте

    Значение smtp_accept_queue_per_connection, вероятно, должно быть увеличено или даже установлено в ноль (отключено) на периодически подключаемых хостах для того, чтобы все входящие сообщения немедленно отсылались по одному соединению.

    Почта, ожидающая отсылки с периодически подключаемого хоста, вероятно, не будет роутится, поскольку без соединения с DNS поиски невозможны. Это означает, что нормальная обработка очереди завершается за время соединения, каждое сообщение, вероятно, будет отправлено в отдельной SMTP-сессии. Этого можно избежать путём запуска обработки очереди с опциями командной строки, начинающимися с -qq вместо -q. В этом случае очередь сканируется дважды. В первый проход завершается роутинг, но доставки не происходит. Во второй проход нормальная обработка очереди, так как все сообщения предварительно были сроучены, то предназначенные для одного и того же хоста, вероятно, будут отосланы в одном SMTP-соединении.