Используем procmail для управления почтой

Установка

Первым делом необходимо получить последнюю версию procmail. Когда писалась эта статья, последней версией была 3.11pre7.

После получения исходного кода программы, для инсталляции его необходимо разархивировать следующей командой: tar -xzvf procmail.tar.gz

Следующий шаг заключается в редактировании файлов Makefile и config.h. Поскольку эта статья только введение, и чтобы его чрезмерно не усложнять, мы не будем объяснять различные опции конфигурации этих файлов. Заинтересовавшийся читатель может посмотреть в справочных страницах (manual pages) и поставляемой с исходным текстом документации.

Тем не менее, о существовании опции BASENAME в Makefile обычно упоминается. Этой опцией мы указываем базовый каталог, в который будет установлен procmail. Из указанного нами базового каталога пойдут другие каталоги, такие как bin и man.

Наконец, для компиляции пакета мы должны выполнить команду make install.

Procmail можно установить для всей системы и затем вызывать некоторым правилом sendmail(8), или он может быть установлен любым пользователем для личного использования. В последнем случае пользователь указывает использование procmail в своем файле .forward, где должна присутствовать строка на подобии следующей:

|IFS=' ' && exec /home/juan/procmail/bin/procmail -f- || exit 75 #juan

В этой строке я предположил, что пользователь juan установил procmail в свой домашний каталог HOME. Для этой конкретной строки BASENAME, указываемое во время компиляции, будет /home/juan/procmail.

Основные функции

Procmail читает из своего стандартного входа. Он проверяет конфигурационный файл .procmailrc, который должен находиться в каталоге HOME пользователя. В этом файле определяются некоторые правила, которые указывают procmail, какие действия надо предпринять после получения сообщения. Он может решить, что с ним делать - сохранить его, игнорировать, автоматически ответить и т.д. - проверив некоторые строки в заголовке сообщения.

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

Конфигурация

Используется конфигурационный файл .procmailrc и он должен находиться в каталоге HOME.

Любая строка, начинающаяся с # считается комментарием.

Строки, начинающиеся с :0 или :0: указывают на начало нового правила, которое говорит procmail что делать с сообщением.

Строки, начинающиеся с *, обозначают условие выполнения правила. Procmail использует этот механизм для определения сообщения, которое необходимо обработать этим правилом.

Оставшиеся строки, то есть те, которые не начинаются с : или * рассматриваются как команды, или, другими словами, предпринимаемые procmail'ом действия, удовлетворяющие условию. Некоторыми возможными действиями или командами могут быть удалить сообщение, переслать сообщение, сохранить сообщение и т.д.

Первым делом необходимо указать в .procmailrc некоторые переменные окружения, здесь приведены некоторые из переменных, которые бы я порекомендовал определить в вашем .procmailrc

MAILDIR
Указывает на каталог, в котором procmail сохраняет файлы с почтовыми сообщениями. Обычно эта переменная указывает на $HOME/mail или $HOME/Mail. Тот или иной каталог, зависит от используемого почтового клиента.

LOGFILE
Указывает на имя лог-файла, в котором procmail записывает все выполненные операции.

SENDMAIL
Указывает на то, где найти sendmail, который используется для автоматического ответа на сообщения.

FORMAIL
Указывает на то, где найти formail. Эта программа распространяется вместе с procmail и ее задачей является изменение почтовых заголовков или переформатирование сообщения для отправки или сохранения.

DEFAULT
Файл, в котором сохраняется сообщение, если procmail не может применить к нему ни одного определенного правила.

Определять переменную окружения можно в любом месте .procmailrc. Если переменная записана без символа =, за которым следует значение, то такая переменная удаляется.

Что касается правил, то они делятся на две группы: Первые предполагают, что после их применения сообщение доставлено, и остальные.

Первые правила простые, после обработки предполагается, что к этому сообщению дальнейшие правила не применяются и поэтому сообщение считается доставленным.

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

Общий синтаксис правила следующий:

           :0 [опции] [ : [исполняемый файл] ]
           * условие 1
           * условие 2
                 .
                 .
                 .
           * условие N
           команда
           

Пройдемся по каждой части и проанализируем ее конструкцию. Прежде всего, каждое правило начинается с :0, после этого могут следовать любые из этих опций:

H Условие применяется к заголовку почты.
B Условие ищется в теле сообщения.
D Это условие означает, что верхний и нижний регистры различаются.
A Это правило применяется только когда применялось предыдущее.
a Как и A, за исключением того, что при применении предыдущего правила ошибок не должно быть.
E Это правило выполняется, если предыдущее не было применено.
e Это правило будет исполнено, если предыдущее был выполнено, но завершилось с ошибками.
h Команде передается заголовок сообщения.
b Команде передается тело сообщения.
f Команда интерпретируется как фильтр.
c Создать копию cc сообщения. При применении этого правила предполагается, что сообщение доставляется с этим флагом и после его доставки дальнейшие правила можно применять к копии сообщения.
w Ждать окончания исполнения команды для получения результата.
W Так же как и предыдущая опция, но в случае ошибки не выдавать ни каких сообщений.
i Игнорировать возможные опечатки.
r Пишет сообщение таким, как оно есть. Проверка на окончание пустой строкой не выполняется.

По умолчанию, если не была указана ни одна опция, условие применяется к заголовку сообщения (опция H). На стандартный вход команды поуступает и заголовок и тело сообщения (опции h и g). Верхний и нижний регистры не различаются.

После :0 и возможных опций может следовать второе :. Если так и есть, то это указывает на то, что файл назначения, куда должно быть записано сообщение, должен быть блокирован во избежание ситуации, когда два процесса одновременно пишут в один файл. Можно указать файл, который будет использован в качестве блокирующего.

Далее идут условия, по одному в строке, и перед каждым ставится символ *. Условия обычно записываются в виде регулярных выражений для того, чтобы определить последовательность символов в заголовке или теле сообщения. Регулярное выражение среди прочих использует следующие символы:

^ Начало строки.
$ Конец строки.
. Любой символ, за исключением символа возврата каретки.
* Ноль или более раз.
+ Один или более раз.
? Ноль или более раз.
[a-z] Диапазон символов, в этом случае от a до z.
[^a-z] Любой символ вне диапазона от a до z.
a|b Или 'a' или 'b'

После условий идет одна команда. Если первый символ команды является одним из приведенных ниже, то предполагается особое поведение:

! Сообщение перенаправляется на все указанные почтовые адреса.
| Если после этого символа следует исполняемый файл, то он исполняется всякий раз, когда выполняется условие. Если после этого символа ничего не стоит, то весь текст сообщения отправляется на стандартный вывод. Если за | следует переменная, то результат указанной команды сохраняется в эту переменную.

Списки рассылки (mailing lists)

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

           [email protected]
           [email protected]
           [email protected]
         

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

Procmail решает эту проблему просто. Мы можем использовать файл .procmailrc со следующими очень простыми правилами сортировки нашей почты из различных списков рассылки по Линукс:

:0
* ^From.*[email protected]
l-linux

:0
* ^From.*[email protected]
linux-mx

:0
* ^From.*[email protected]
linux-security

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

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

В следующей строке находится условие, которое, поскольку оно упоминалось прежде, всегда распознается, так как первым стоит символ *. Условие является следующим регулярным выражением:

^From.*[email protected]

Подстрока ^From указывает procmail на то, что необходимо искать эти строки следом за подстрокой From.

Следующий символ .* означает любое количество символов. Ранее мы отметили, что в регулярном выражении символ "." эквивалентент любому символу, а * обозначает ноль или больше. Следовательно .* означает, что после начального From может быть ноль или более символов.

Дальше идет строка [email protected], которая является адресом, с которого пришло сообщение.

Подумав немного над этим регулярным выражением, вы поймете, что это правило "вычислит" следующие строки:

From: [email protected]
From:[email protected]
FROM [email protected]

Используя это правило, уже можно различать сообщения, приходящие с этого адреса и остальные. Что же теперь нужно сделать с сообщением?.

Следующей строкой является команда (или действие) и оно указывает, что делать с сообщением. В этом случае предполагается сохранить его в файле linux-mx. Если абсолютный путь к файлу не указан, по умолчанию принимается, что он добавляется к переменной окружения $MAILDIR.

Очевидно, сообщения приходящие из различных списков теперь можно распределять по различным файлам, в зависимости от адреса отправителя (поле From).

Автоматический ответ

Другой ситуацией, в которой procmail может пригодиться, являются автоответчики. Часто очень удобно, например, если вы хотите автоматически отправить ваш публичный ключ PGP любому, запросившему его по E-Mail

Чтобы это сделать, напишите правило, которое считает запросом вашего ключа PGP любое собщение, в строке subject которого есть строка PGP. Это правило можно записать как:

0:
* ^Subject.*PGP
| (formail -r ; cat $HOME/key.asc) | sendmail -t

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

0:
| (formail -r; cat $HOME/vacations.txt) | sendmail -t

В последнем случае условий нет, так как на все сообщения будут отправлены одни и те же ответы.

Как избежать зацикливания автоответчика

В предыдущих примерах не было попыток обработки возможного зацикливания, которое иногда случается, если почта отвечается автоматически.

Если в сообщении адресом отправителя является наш собственный E-Mail адрес, и программа должна ответить на этот адрес, то ответ вернется к нам же. На это сообщение следует еще один ответ и так далее до бесконечности. Чтобы этого избежать, при ответе на сообщение нужно добавить дополнительную строку к заголовку, чтобы указать, что на это сообщение уже отвечали. Используется опция -A formail:

formail -r -A"X-Loop: [email protected]"

Здесь [email protected] будет нашим собственным E-Mail адресом. В этом случае при создании заголовка ответа добавляется строка X-Loop с тем, чтобы позднее можно было проверить новым правилом:

:0
* !^X-Loop: [email protected]
| (formail -r -A"X-Loop: [email protected]" ;
    cat $HOME/vacation.txt) | sendmail -t

Это правило предотвращает зацикливание, так как любое собщение, содержащее в заголовке строку X-Loop не будет удовлетворять условиям, и в результате procmail на него не ответит.

Декодирование файлов

Еще одним интересным правилом нашего .procmailrc может быть декодировка поступающей почты, автоматически закодированной uuencode(1). Это правило можно задать как:

:0 B
* ^begin 644 .*
{
        MAILDIR=$HOME/files

        :0
        | uudecode
}

Здесь явно задано опцией B, что условие правила должно применяться только к телу сообщения.

Если правило находит строку, начинающуюся со строки "begin 644", то это означает, что это начало файла, закодированного uuencode(1), поэтому устанавливается переменная окружения MAILDIR, что эквивалентно изменению каталога, на который указывает эта переменная. С этого момента все действия по выводу сообщений будут выполняться с учетом указанного базового каталога. В нашем случае, нам необходимо, чтобы поступающие сообщения сохранялись в $HOME/files.

Дальше идет правило, безусловное, которое только направляет сообщение в канал для декодирования. Исходный файл будет отправлен в $HOME/files.

Заключение

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

Дальнейшая информация: