Транспорт “pipe” использует доставку через трубу (pipe) к команде, выполняющейся в ином процессе. Один пример - использование “pipe” как псевдоудалённого транспорта для передачи сообщений какому-то иному механизму доставки (типа UUCP). Другой - использование отдельными пользователями для автоматической обработки их входящих сообщений. Транспорт “pipe” может использоваться одним из следующих способов:
Маршрутизатор направляет один адрес на транспорт обычным способом, и транспорт сконфигурен как транспорт “pipe”. В этом случае, “
$local_part
” содержит локальную часть адреса (как обычно), и запускаемая команда задана в транспорте, опцией “command”.
Если опция “batch_max” установлена более чем в 1 (значение по умолчанию - 1), транспорт может обработать более одного адреса за один запуск. В этом случае, когда к транспорту роутится более одного адреса, “
$local_part
” не установлена (поскольку она не уникальна). Однако, псевдопеременная “
$pipe_addresses
” (описанная в разделе 29.3) содержит все адреса которые роутятся к транспорту.
Роутер переадресует адрес напрямую к команде pipe (например, из файла альясов или форвардов). В этом случае, “
$address_pipe
” содержит текст команды pipe, и опция “command” в роутере - игнорируется. Если транспортируется лишь один адрес (“batch_max” более одного, или лишь один адрес был передаресован к команде трубы), “
$local_part
” содержит переадресованную локальную часть.
Транспорт “pipe” - неинтерактивный метод доставки. Также, exim может доставлять сообщения через трубы, используя интерактивный протокол LMTP. Это осуществляется транспортом “lmtp”.
В случае, когда “pipe” работает как следствие совпадения в локальном пользовательском файле “.forward”, команда запускается под uid и gid этого пользователя. В других случаях, uid и gid должны быть заданы явно, или в транспорте, или в маршрутизаторе обрабатывающем адрес. Текущая и “домашняя” директории также управляемы. Для получения дополнительных деталей о окружении долальной доставки, смотрите раздел 23, и раздел 25 для обсуждения пакетной локальной доставки.
29.1 Конкурирующие доставки
Если два сообщения приходят почти одновременно, и оба роутятся на доставку pipe, два транспорта “pipe” могут быть запущены одновременно. Вы должны гарантировать, что любые команды pipe, установленные вами, являются корректными для этого случая. Есди команда пишет в файл, может быть полезна утилита “exim_lock”.
29.2 Возвращаемый статус и данные
Если команда выходит со статусом отличным от нуля, доставка считается неудачной, если не установлена опция “ignore_status” (в этом случае код возврата обрабатывается как ноль), или возвращаемый код - один из перечисленных в опции temp_errors”, которые интерпретируются со смыслом “попробуйте позднее” (“try again later”). В этом случае, доставка задерживается. Детали постоянной ошибки логгируются, но не включаются в рикошет, просто содержащий “local delivery failed”.
Если код возврата более чем 128, и выполняемая команда - shell-скрипт, это, обычно, означает, что скрипт был уничтожен сигналом, чьё значение равно - код возврата минус 128ю
Если exim не может запустить команду (т.е. - если “
execve()
” неудачна), код возврата устанавливается равным 127. Это - значение, возвращаемое shell`ом, если запрашивают о запуске невыполняемой команды. Формулировка для логов наводит на мысль, что проблемой может быть несуществующая команда.
Опция “return_output” может затрагивать результат доставки. Если она установлена, и команда производит какой-либо вывод на своём стандартном выводе, или в стандартном потоке ошибок, предполагается, что произошла ошибка команды, даже если она вернула нулевой код возврата, или установлена опция “ignore_status”. Вывод команды включается как часть сообщения рикошета. Опция “return_fail_output” подобна вышеописанной, за исключением что вывод возвращается лишь когда команда выходит с ошибочным кодом возврата, т.е. значениями кроме нуля или совпадающим с “temp_errors”.
29.3 Как выполняется команда
Командная строка (по умолчанию) разбирается в имя команды и аргументы непосредственно транспортом “pipe”. Опции “allow_commands” и “restrict_to_path” могут использоваться для ограничения команд, которые могут быть запущены.
Элементы не помещённые в кавычки разделяются по пробелам. Если аргумент помещён в двойные кавычки, обратный слэш интерпретируется как обычно, - как специальный символ. Если аргумент фигурирует в одинарных кавычках, интерпретации специальных символов не производится (имеются ввиду символы начинающиеся с обратного слэша - прим. lissyara).
К командной строке применяется раскрытие строки, кроме случаев когда она приходит из традиционного файла “.forward” (команды из файла фильтра раскрываются). Раскрытие применяется по очереди, к каждому аргументу, а не ко всей строке. Поэтому, любой любой элемент раскрытия, содержащий пробелы, должен быть помещён в кавычки таким образом, чтобы он был внутри одного аргумента. Установка типа
для гарантирования, что всё это в одном аргументе. Раскрытие производится этим способом, аргумент за аргументом, таким образом, число аргументов не может быть изменено в результате раскрытия, и кавычки или обратные слэши во вставленных параметрах не взаимодействуют с внешними кавычками. Однако, это приводит к проблемам - если вы хотите генрировать много параметров (или имя команды, плюс аргументы) из одного раскрытия. В этой ситуации, самое простое решение - использовать shell. Например:
Имеет место специальная обработка, когда аргумент состоит в точности из текста “
$pipe_addresses
”. Это - не общая переменая раскрытия; единственное место, где распознаётся эта строка, - когда она появляется как парметр для трубы, или команды транспортного фильтра. Она вызывает каждый обрабатываемый адрес для вставки в список аргументов, в этой точке, как отдельный параметр. Это позволяет избежать любых проблем с пробелами или метасимволами shell, и используется когда транспорт “pipe” обрабатывает группу адресов в пакете.
После разделения на параметры и раскрытие, результирующая команда запускается в субпроцессе напрямую от транспорта, не под shell`ом. Доставляемое сообщение предоставялется на стандартном вводе, и оба - стандартный вывод, и стандартный вывод для ошибок, связаны с одной трубой, читаемое exim`ом. Опция “max_output” - контролирует,как много вывода может произвести команда, и опции “return_output” и “return_fail_output” - управляют, что с ним делается.
Невыполнение команды под shell`ом (по умолчанию), уменьшает риск безопасности в случаях, когда команда из пользовательского фильтра строится из данных взятых из входящего сообщения. Если shell требуется, он, разумеется, может быть явно определён как оамнда, которая выполнится. Однако, существуют обстоятельства, когда существующие команды (например, в файлах “.forward”) ожидают своего выполнения под shell`ом,и не могут быть легко модифицированы. Для разрешениия этих случаев, есть опция, называемая “use_shell”, которая изменяет способ работы транспорта “pipe”. Вместо описанной разбивки командной строки, она раскрывает её как одну строку, и передаёт результат “/bin/sh”. Опция “restrict_to_path” и средство “
$pipe_addresses
” не могут использоваться с “use_shell”, и весь механизм - менее безопасен.
29.4 Переменные окружения
Перечисленные ниже переменные окружения устанавливаются при вызове команды. Список - компромисс, для максимальной совместимости с другими MTA. Отметтьте, что для добавления дополнительных переменных окружения может использоваться опция “environment”.
имя
значение
DOMAIN
домен адреса
HOME
домашняя директория; если задана
HOST
имя хоста при вызове из роутера (смотрите ниже)
LOCAL_PART
смотрите ниже
LOCAL_PART_PREFIX
смотрите ниже
LOCAL_PART_SUFFIX
смотрите ниже
LOGNAME
смотрите ниже
MESSAGE_ID
локальный идентификатор сообщения exim`a
PATH
как задано путём опции “path”
QUALIFY_DOMAIN
квалификационный домен отправителя
RECIPIENT
полный адрес получателя
SENDER
отправитель сообщения (пустой - если рикошет)
SHELL
/bin/sh
TZ
значение опции “timezone”; если установлена
USER
смотрите ниже
Когда транспорт “pipe” вызывается непосредственно из (например) роутера “accept”, LOCAL_PART устанавливается в локальную часть адреса. Когда он вызывается как результат раскрытия форварда или альяса, LOCAL_PART устанавливается в локальную часть адреса, который был раскрыт. В обоих случаях, любые аффиксы удаляются из локальной части, и становятся доступны в LOCAL_PART_PREFIX и LOCAL_PART_SUFFIX, соответственно. LOGNAME и USER устанавливаются в тоже значение, что и LOCAL_PART, для совместимости с другими MTA.
HOST - устанавливается лишь когда транспорт “pipe” вызывается из роутера, который ассоциирует хосты с адресами, типично используя “pipe” как псевдоудалённый транспорт. HOST устанавливается в первое имя хоста заданное роутером.
Если установлена общая транспортная опция “home_directory”, её значенеи используется для переменной окружения HOME. Иначе, домашняя директория может быть установлена роутером, путём опции “transport_home_directory”, иеющей дефолтовое значение на домашнюю директорию пользователя, если установлена “check_local_user”.
29.5 Частные опции для “pipe”
Имя
Использование
Тип
Дефолтовое значение
allow_commands
pipe
string list†
незадана
Строка раскрывается, и, затем, интерпретируется как раздёлённый двоеточиями список допустимых команд. Если “restrict_to_path” не установлена, разрешены лишь команды перечисленные в списке “allow_commands”. Они не должны быть абсолютными путями; опция “path” продолжает использоваться для относительных путей. Если “restrict_to_path” установлена с “allow_commands”, команда должна быть в списке “allow_commands”, или именем без каких-либо слэшей наёденным в путях. Другими словами, если не установлена ни “allow_commands”, ни “restrict_to_path” - нет никаких ограничений на команды, но иначе, разрешены лишь команды допускаемые той или другой опциеями. Например, если
allow_commands = /usr/bin/vacation
и “restrict_to_path” не установлена, разрешена лишь команда “/usr/bin/vacation”. Опция “allow_commands” не может быть установлена, если установлена “use_shell”.
Имя
Использование
Тип
Дефолтовое значение
batch_id
pipe
string†
незадана
Смотрите описание пакетной локальной доставки в разделе 25.
Имя
Использование
Тип
Дефолтовое значение
batch_max
pipe
integer
1
Эта опция ограничивает число адресов, которые могут быть обработаны в одной доставке. Смотрите описание пакетной локальной доставки в разделе 25.
Имя
Использование
Тип
Дефолтовое значение
check_string
pipe
string
незадана
Когда “pipe” пишет сообщение, начало каждой строки проверяется на совпадение с “check_string”, и если оно происходит, начальные совпавшие символы заменяются содержимым “escape_string”, если обе установлены. Значение “check_string” - литеральная строка, а не регулярное выражение, и регистр букв имеет значение. Когда установлена “use_bsmtp”, содержимое “check_string” и “escape_string” приводится к значениям, которые оформлены протоколом экранирования SMTP (? - невкурил... - прим. lissyara). Любые настройки сделанные в конфигурационном файле - игнорируются.
Имя
Использование
Тип
Дефолтовое значение
command
pipe
string†
незадана
Эта опция не должна быть установлена, когда “pipe” используется для доставки в трубы, полученные непосредственно от переназначения адресов. В других случаях, опция должна быть установлена, для предоставления команды, которая будет выполнена. Она не нуждается в абсолютном пути (смотрите ниже, опцию “path”). Команда разделяется exim`ом на отдельные параметры, и каждый аргумент отдельно раскрывается, как описано выше, в разделе 29.3.
Имя
Использование
Тип
Дефолтовое значение
environment
pipe
string†
незадана
Эта опция используется для добавления дополнительный переменных к среде окружения, в которой выполняется команда (смотрите раздел 29.4, для получения списка дефолтовых значений). Ее значение - строка, которая вначале раскрывается, и затем интерпретируется, как список, разделённый двоеточиями, установок среды окружения в форме “<name>=<value>”.
Имя
Использование
Тип
Дефолтовое значение
escape_string
pipe
string
незадана
Смотрите выше, опцию “check_string”.
Имя
Использование
Тип
Дефолтовое значение
freeze_exec_fail
pipe
boolean
ложь
Ошибка выполнения команды в транспорте “pipe”, по умолчанию, обрабатывается как любая другая ошибка при запуске команды. Однако, если установлена опция “freeze_exec_fail”, ошибка выполнения обрабатывается особым образом, и вызывает заморозку сообщения вне зависисмости от установки “ignore_status”.
Имя
Использование
Тип
Дефолтовое значение
ignore_status
pipe
boolean
ложь
Если эта опция истинна, статус возвращаемый субпроцессом запустившим команду - игнорируется, и exim ведёт себя так, как будто был возвращён ноль. Иначе, ненулевой статус или завершение по сигналу вызывают ошибку из транспорта, если статус - не одно из значений перечисленных в “temp_errors”; они вызывают задержку доставки и дальнейшие, более поздние попытки доставки. Отметтьте: Эта опция не касается таймаутов, которые не возвращают статус. Смотрите опцию “timeout_defer”, для информации о обработке таймаутов.
Имя
Использование
Тип
Дефолтовое значение
log_defer_output
pipe
boolean
ложь
Если эта опция установлена, и статус возвращаемый командой - один из кодов перечисленных в “temp_errors” (т.е. доставка была задержана), и её был сгенерён какой-либо вывод, его первая строка записывается в главный лог.
Имя
Использование
Тип
Дефолтовое значение
log_fail_output
pipe
boolean
ложь
Если эта опция установлена, и команда возвращает какой-либо вывод, и, также, завершается с кодом возврата не равным ни нулю, ни кодам перечисленным в “temp_errors” (т.е. - доставка неудачна), первая строка вывода записывается в главный лог. Эта опция, и “log_output” - взаимоисключаемы. Лишь одна из них может быть установлена.
Имя
Использование
Тип
Дефолтовое значение
log_output
pipe
boolean
ложь
Если эта опция установлена, и команда возвращает какой-либо вывод, первая строка вывода записывается в главный лог вне зависимости от возвращённого кода. Эта опция, и “log_fail_output” - взаимоисключаемы. Лишь одна из них может быть установлена.
Имя
Использование
Тип
Дефолтовое значение
max_output
pipe
integer
20K
Эта опция определяет максимальное количество вывода, который команда может сгенерить на своём стандартном выводе и объединённом стандартном файле ошибок. Если лимит исчерпан, процесс, выполняющий команду, уничтожается. Это - мера безопасности, для поимки неудержиморастущих процессов. Ограничение применяется независимо от настроек опций контролирующих что происходит с этим выводом (например, “return_output”). Из-за эффекта буферизации, объём вывода может немного превысить ограничение, до того, как exim это заметит.
Имя
Использование
Тип
Дефолтовое значение
message_prefix
pipe
string†
смотрите ниже
Заданная строка раскрывается, и выводится в начале каждого сообщения. По умолчанию, она незадана, если установлена опция “use_bsmtp”. Иначе, она
message_prefix = \
From ${if def:return_path{$return_path}{MAILER-DAEMON}}\
${tod_bsdinbox}\n
Обычно, это требуется для программы “/usr/bin/vacation”. Однако, она не должна присутствовать, если производится доставка на Cyrus IMAP server, или локальному агенту доставки “tmail”. Преффикс может быть запрещён путём установки
message_prefix =
Имя
Использование
Тип
Дефолтовое значение
message_suffix
pipe
string†
смотрите ниже
Заданная строка раскрывается, и выводится в начале каждого сообщения. По умолчанию, она незадана, если установлена опция “use_bsmtp”. Иначе, она - одна новая строка. Суффикс может быть запрещён путём установки
message_suffix =
Имя
Использование
Тип
Дефолтовое значение
path
pipe
string
/bin:/usr/bin
Эта опция определяет строку, которая устанавливается в переменную окружения PATH, субпроцесса. Если опция “command” не приводит к абсолютному пути к имени, команда разыскивается в директориях PATH обычным способом. Предупреждение: Это не применяется к команде, заданной как транспортный фильтр.
Имя
Использование
Тип
Дефолтовое значение
pipe_as_creator
pipe
boolean
ложь
Если незадана общая опция “user”, и эта опция истинна, процесс доставки запускается под uid, который был у exim при при изначальном вызове для приёма сообщения. Если не установлен идентификатор группы (через общую опцию “group”), в силе gid, который был у exim при при изначальном вызове для приёма сообщения.
Имя
Использование
Тип
Дефолтовое значение
restrict_to_path
pipe
boolean
ложь
Когда эта опция установлена, любое имя команды не перечисленное в “allow_commands” не должно содержать какихбы-то ни было слэшей. Команда ищется лишь в директориях перечисленных в опции “path”. Эта опция предназначена для случая, когда команда трубы была сгенерена из пользовательского файла “.forward”. Обычно, это обрабатывается транспортом “pipe”, называемым “address_pipe”.
Имя
Использование
Тип
Дефолтовое значение
return_fail_output
pipe
boolean
ложь
Если эта опция установлена в истину, и команда производит какой-либо вывод, и завершается с кодом возврата не равным нулю или несодержащимся в кодах перечисленных в “temp_errors” (т.е. ошибка доставки), вывод возвращается в рикошете. Однако, если сообщение имеет пустого отправителя (т.е. оно само по себе рикошет), вывод команды отбрасывается. Эта опция и “return_output” - взаимоисключаемы. Лишь одна из них может быть установлена.
Имя
Использование
Тип
Дефолтовое значение
return_output
pipe
boolean
ложь
Если эта опция установлена в истину, и команда производит какой-либо вывод, доставка считается неудачной вне зависмости от кода возврата, и вывод возвращается в рикошете. Иначе, вывод просто игнорируется. Однако, если сообщение имеет пустого отправителя (т.е. оно само по себе рикошет), вывод всегда команды отбрасывается, вне зависимости от установки этой опции. Эта опция и “return_fail_output” - взаимоисключаемы. Лишь одна из них может быть установлена.
Имя
Использование
Тип
Дефолтовое значение
temp_errors
pipe
boolean
незадана
Эта опция содержит или список, разделённый двоеточиями, или единственную звёздочку. Если опция “ignore_status” - ложна, и “return_output” - незадана, и команда выходит с ненулевым кодом, ошибка обрабатывается как временная, и доставка задерживается - если код возврата совпадает с одним из чисел, или если стоит звёздочка. Иначе, ненулевые коды возврата обрабтываются как постоянные ошибки. Значение по умолчанию сожержит коды заданные EX_TEMPFAIL и EX_CANTCREAT в “sysexits.h”. Если exim скомпилен на системе не задающей эти макросы, они принимают значения 75 и 73, соответственно.
Имя
Использование
Тип
Дефолтовое значение
timeout
pipe
time
1h
Если команда не смогла завершится в течение этого времени, она уничтожена. Обычно, это вызывает ошибку доставки (но, посмотрите опцию “timeout_defer”). Нулевой интервал времени задаёт, что нет таймаута. Для гарантии, что любые созданные командой субпроцессы также уничтожены, exim делает начальный процесс лидером группы процессов, и по таймауту всю группу процессов. Однако, это может быть обойдено, если один из процессов начинает новую группу процессов.
Имя
Использование
Тип
Дефолтовое значение
timeout_defer
pipe
boolean
ложь
Таймаут в транспорте “pipe”, или в команде, запускаемой транспортом, или в ассоциированном с ним транспортном фильтре, по дефолту обрабтывается как жёсткая ошибка, и доставка неудачна. Однако, если “timeout_defer” установлена в истину, оба вида таймаута становятся временными, вызывая задержку доставки.
Имя
Использование
Тип
Дефолтовое значение
umask
pipe
octal integer
022
Эта опция определяет установку umask для субпроцесса выполняющего команду.
Имя
Использование
Тип
Дефолтовое значение
use_bsmtp
pipe
boolean
ложь
Если эта опция установлена в истину, транспорт “pipe” пишет сообщения в формате “пакетного SMTP”, с отправителем конверта и получателем (получателями) включенными как SMTP-команды. Если вы хотите включить начальную команду HELO с каждым сообщением, вы можете сделать это, путём установки опции “message_prefix”. Для получения дополнительных деталей о пакетном SMTP, смотрите раздел 44.10.
Имя
Использование
Тип
Дефолтовое значение
use_classresources
pipe
boolean
ложь
Эта опция доступна лишь в случае, если exim работает на FreeBSD, NetBSD, или BSD/OS (FreeBSD - форева; - извините, прим. lissyara :)). Если она установлена в истину, функция “
setclassresources()
” используется для установки ограничений ресурсов, когда транспорт “pipe” производит доставку. Лимиты для uid, под которым работает труба, лолучаются из БД классов логинов (/etc/login.conf - прим. lissyara).
Имя
Использование
Тип
Дефолтовое значение
use_crlf
pipe
boolean
ложь
Эта опция заставляет завершаться строки двухсимвольной CRLF последовательностью (возврат каретки, новя строка), вместо одного символа перевода строки. В случае пакетного SMTP, записанная в трубу последовательность байтов - точное подобие того, что было бы послано в реальном SMTP-подключении.
Содержимое опций “message_prefix” и “message_suffix” пишется дословно, таким образом, они должны содержать свои символы возврата каретки, если они им необходимы. Так как сдефолтовое значение для обоих - “message_prefix” и “message_suffix” содержит один перевод строки, их значения должны быть изменены, чтобы они завершались “\r\n”, если задана опция “use_crlf”.
29.6 Использование внешнего (стороннего) агента локальной доставки
Транспорт “pipe” может использоваться для передачи всех сообщений, которым требуется локальная доставка, отдельному локальному агенту доставки, типа “procmail”. Когда это делается, нужно быть осторожным, чтобы гагантировать, что труба выполняется под соответствующими uid и gid. В некоторых конфигурациях, требуется, чтобы это был uid, которому доверяет агент доставки, для предоставления корректного отправителя сообщения. Может потребоваться повторно пересобрать или переконфигурировать агента доставки таким образом, чтобы он доверял соответтсвующему пользователю. Далее - пример конфигурации транспорта и роутра, для “procmail”:
# transport
procmail_pipe:
driver = pipe
command = /usr/local/bin/procmail -d $local_part
return_path_add
delivery_date_add
envelope_to_add
check_string = "From "
escape_string = ">From "
user = $local_part
group = mail
# router
procmail:
driver = accept
check_local_user
transport = procmail_pipe
В этом примере, труба запускается как локальный пользователь, но с установленнной группой “mail”. Как альтернатива - запускать трубу под определённым пользователем, типа “mail” или “exim”, но в этом случае вы должны принять меры, чтобы “procmail” доверял этому пользователю для предоставления корректного адреса отправителя. Если вы не задаёте или опцию “group” или опцию “user”, команда трубы запускается под локальным пользователем. Домашняя директория - дефолтовая домашняя директория пользователя. Отметтьте: Команда, которая запускает транспорт “pipe”, не начинается с
IFS=" "
как показано в некоторой документации на “procmail”, поскольку exim, по умолчанию, не использует shell для запуска команд канала.
Следующий пример показывает транспорт и роутер для систем, где локальные доставки обрабатываются Cyrus IMAP server.
# transport
local_delivery_cyrus:
driver = pipe
command = /usr/cyrus/bin/deliver \
-m ${substr_1:$local_part_suffix} -- $local_part
user = cyrus
group = mail
return_output
log_output
message_prefix =
message_suffix =
# router
local_user_cyrus:
driver = accept
check_local_user
local_part_suffix = .*
transport = local_delivery_cyrus
Отметтьте, что незаданы “message_prefix” и “message_suffix”, и использование “return_output”, для того, чтобы любой текст, записанный Cyrus`ом, был возвращён отправителю.