На главную

Крылатая почта юниксоида

 

Почтовая система в стиле UNIX-way

Для чего, по-твоему, предназначен почтовый клиент? Правильно, читать почту. А ты никогда не задумывался, почему все современные MUA (Outlook Express, Thunderbird, Sylpheed), кроме выполнения своих непосредственных задач, еще и сортируют почту, получают и отправляют письма, обрабатывают спам, в общем, занимаются всем, чем угодно, разве что кофе не варят? Так уж повелось в современном мире «дружелюбных к пользователю» систем, что все связанное с определенным кругом задач (в нашем случае - с почтой) делает Одна Большая Программа. И пользователь даже не задумывается, что тем самым сильно себя ограничивает. Зачем, например, мне держать эту Программу запущенной, если я хочу всего лишь автоматически забирать новую почту с сервера. Или автоматически пересылать определенные сообщения на другой ящик. Или отправлять почту не сразу, а в определенное время. К счастью, есть путь, способный освободить нас от рамок одной программы. И имя ему - UNIX-way.

[ингредиенты]

Для приготовления нашей почтовой пользовательской системы нам понадобятся следующие компоненты: mutt, getmail, procmail, spamassassin, msmtp, а также vim, gnupg, antiword и mairix - по вкусу. Я использую FreeBSD, поэтому весь софт будем ставить из портов. Разумеется, нетрудно спроецировать процесс установки и на твой любимый дистрибутив.

Mutt - превосходный консольный почтовый клиент, способный творить с письмами невероятные вещи. Расписывать все его достоинства не имеет смысла, достаточно сказать, что это самый популярный MUA среди разработчиков из opensource-сообщества, кернел-хакеров и просто крутых юниксоидов ;-). Мы будем ставить его devel-версию 1.5.х («стабильная» ветка имеет сейчас номер 1.4.х), которая имеет такие преимущества, как скорость работы, поддержку SMIME-расширений (1.4.х умеет только PGP-шифрование), и в то же время достаточно стабильна. Мы научим mutt читать news-конференции.

# cd /usr/ports/mail/mutt-devel

# make WITH_MUTT_MAILDIR_MTIME_PATCH=yes WITH_MUTT_NNTP=yes WITH_MUTT_IMAP_HEADER_CACHE=yes
WITH_MUTT_MAILDIR_HEADER_CACHE=yes WITH_MUTT_EDIT_THREADS=yes install clean

Как видно, вместо традиционного mbox я собираюсь использовать Maildir-формат почтового ящика. Для меня основным преимуществом Maildir является формат «одно письмо - один файл».

Getmail - программа для доставки почты с удаленных POP3/IMAP-серверов с множеством удобств и приятностей (поддержка SSL, доставка в Maildir-style ящики, докачка сообщений после разрыва сессии и т.п.), написанная на Питоне. Более популярный вариант - fetchmail.

# cd /usr/ports/mail/getmail

# make install clean

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

# cd /usr/ports/mail/procmail

# make install clean

Msmtp - это легковесный почтовый агент, созданный для машин, на которых нет запущенного SMTP-демона. Исторически (так сказать, by design) подразумевается, что на каждой *nix-машине работает почтовый сервер (хотя бы для обработки локальных отчетов администратору, см. periodic(8)), настроенный, при необходимости, на релей «внешнего» почтовика. Но часто на desktop-машинах это совсем не так: periodic tasks убирают из crontab(5), а почтовый сервер выключают. В этом случае вместо sendmail можно использовать msmtp, который имеет поддержку SMTP-авторизации, TLS, множества аккаунтов, но при этом не выступает в роли полноценного MTA (не слушает порт и не принимает соединения).

# cd /usr/ports/mail/msmtp

# make WITH_OPENSSL=yes install clean

Со спамом можно бороться разными способами, но если ты пользователь, а не админ почтового сервера, то для тебя остается один путь - SpamAssassin. Он использует текстовые анализаторы и black-листы для определения спама.

# cd /usr/ports/mail/p5-Mail-SpamAssassin

# make install clean

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

# cd /usr/ports/security/gnupg

# make install clean

Забегая вперед, скажу, что mutt умеет отображать вложения ничуть не хуже, чем The BAT'ы и Outlook'и, вызывая сторонние программы для обработки аттача в зависимости от его MIME-типа. Так, для просмотра M$ Word-файлов нам понадобится antiword - по сути, преобразователь ".doc" в ".txt":

# cd /usr/ports/textproc/antiword

# make install clean

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

# cd /usr/ports/mail/mairix

# make install clean

Ну и, разумеется, сочинять письма мы будем в своем любимом текстовом редакторе. Это дело личного вкуса каждого. Я использую vim.

[готовим!]

Собрав и разложив по полкам ингредиенты, начинаем готовить. Начнем c «основы основ» - конфигурационного файла Mutt. Самый распространенный метод - занести все опции в конфиг ~/.muttrc. Это неудобно по нескольким причинам, главная из которых - как следует настроенный mutt имеет конфиг размером в несколько десятков килобайт, искать и править нужную опцию в этом случае - не самое веселое развлечение. Я предпочитаю логически разделить настройку клиента на несколько конфигов и подключать их в главный файл. В этом случае удобнее создать папку ~/.mutt, а в ней - muttrc (без точки).

Настройка mutt - длительный, но приятный процесс :). Почитывая документацию, ты открываешь для себя все новые опции, и все больше настраиваешь клиент по своему вкусу. Те же, кто не любит читать документацию, могут найти на нашем диске полностью отточенные конфиги, которыми я пользуюсь каждый день. Здесь же приведу основные опции, без которых не обойтись, с комментариями.

Сила mutt - в его конфигах. Синтаксис основного конфигурационного файла имеет вид: "set name[=value]". Этот конфиг будет содержать только главные опции, которые вряд ли придется часто менять. Переменная name, в зависимости от опции, может быть строкой, либо переменной вида "yes|no", а также ask-[yes|no], в этом случае клиент будет запрашивать подтверждение на операцию, с отмеченным по умолчанию значением yes или no. Допустимо также использование конструкций вида "unset value" и "set value", когда подразумевается no или yes. Например, "set quit=ask-yes" означает запрос подтверждения на выход из mutt (по нажатию клавиши 'q'), по умолчанию (если ничего не вводить в ответ на запрос) будет считаться ответ yes. В дополнительные конфиги мы вынесем настройку заголовков писем, привязок клавиш к действиям, настройку обработчиков событий («хуков»), PGP и цветовых оформлений (тем).

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

$ vi ~/.mutt/headers.mutt

# выключаем дефолтный порядок представления заголовков

ignore *

# включаем только интересующие нас поля

unignore Bcc Cc Date From Mailing-List Newsgroups Organization Reply-To Subject To User-Agent X-Mailer X-Spam-Status X-Qmail-Scanner X-Spam

# определяем порядок их вывода на экран

hdr_order Date From: To Cc Reply-To Subject User-Agent X-Mailer X-Spam-Status X-Qmail-Scanner X-Spam

# определяем SMTP-заголовки писем, которые будут подставляться в наши сообщения

my_hdr From: "Anton A. Karpov" <toxa@toxahost.ru>

my_hdr X-Comment-To: "Anton A. Karpov"

my_hdr User-Agent: Outluck Express 1.5.6i for MS-DOS 6.22-SMP

my_hdr X-Mailer: See User-Agent above :)

my_hdr X-Operating-System: MS-DOS 6.22-CURRENT on Sony VAIO laptop

my_hdr X-PGP-Public-Key: http://www.toxahost.ru/gpg/pubkey.asc

my_hdr X-Useless-Header: Do Androids Dream of Electric Sheep?

Хуки - один из мощных бонусов mutt. С помощью условий можно переопределять указанные ранее опции, привязывать их, например, к имени получателя и т.п.

$ vi ~/.mutt/hooks.mutt

# данный хук меняет заголовок From в случае, если получатель письма имеет адрес вида <name>@real.xakep.ru

send-hook '~t @real\.xakep\.ru' 'my_hdr From: Anton Karpov <toxa@real.xakep.ru>'

# а этот хук включает pgp-шифрование (по умолчанию я не шифрую письма), если получатель - putin@gov.ru

send-hook '~t ^putin@gov\.ru$' 'set pgp_autoencrypt'

Мне не нравятся сочетания клавиш по умолчанию. Плюс к этому, я хочу повесить свои хоткеи на часто выполняемые операции.

$ vi ~/.mutt/bindings.mutt

# по умолчанию я использую свой сервер для отправки писем, но при нажатии в клиенте сочетания <Esc-4>, smtp-аккаунт для отправки писем будет меняться на gmail'овский:

macro generic "<esc>4" ":set sendmail=\"/usr/local/bin/msmtp -a gmail\""

# перемещаться по сообщениям клавишами UP и DOWN

bind pager <UP> previous-page

bind pager <DOWN> next-page

# при нажатии клавиши 'S' в окне просмотра писем вызывается написанный мной скрипт, который подсчитывает количество писем во всех ящиках

macro index S "!~/.mutt/scripts/msgnum.sh\r"

# при нажатии 'G' в окне просмотра писем, сообщения, или отправке письма, будет вызываться программа получения почты

macro pager G "!getmail\r"

macro browser G "!getmail\r"

macro index G "!getmail\r"

# нажатие 'z' на отмеченном письме, которое проскочило спам-фильтр, «обучит» SpamAssassin, чтобы в дальнейшем оно определялось как спам.

macro index z "|sa-learn --no-sync --spam\n"

# по сочетанию клавиш переходить в соответствующие папки

macro index ",f" "c=freebsd-list"

macro index ",o" "c=obsd-list""

Mutt может быть полностью перекрашен во все цвета радуги. Не буду приводить здесь описание цветовой схемы, на диске ты найдешь файл с темой toxapaint, где полностью расписаны все элементы оформления клиента.

$ vi ~/.mutt/themes/mytheme

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

$ vi ~/.mutt/gpg.mutt

Теперь перейдем к основному конфигурационному файлу.

$ vi ~/.mutt/muttrc

# подключаем написанные ранее конфиги

source ~/.mutt/headers.mutt

source ~/.mutt/hooks.mutt

source ~/.mutt/bindings.mutt

source ~/.mutt/gpg.mutt

source ~/.mutt/themes/mytheme

# нижеследующие опции мы не выносим в отдельные файлы, хотя у экстремалов muttrc состоит из одних source-включений

# группа опций, отвечающая за кодировку писем

set charset=koi8-r

set send_charset="koi8-r"

set allow_8bit=yes

# а это касается заголовков и редактора

set use_from=no

set envelope_from=no

set attribution="On %d, %n wrote:"

set editor="vim +':set textwidth=72' %s"

# удалять письма без подтверждения

set delete=yes

# спрашивать сохранение копии исходящего письма

set copy=ask-no

# спрашивать при печати письма

set print=ask-yes

# включать оригинальное письмо при ответе (цитирование)

set include=yes

# уточнять, действительно ли ты хочешь выйти из mutt

set quit=ask-yes

# не соединять аттачи в один файл

set attach_split

# при ответе на письмо не спрашивать про поля To, CC

set fast_reply

# не помечать непрочитанные письма как прочитанные после выхода

unset mark_od

# позволяет суспендить mutt в шелле стандартным сочетанием Ctrl^Z

set suspend

# не пищать ;)

unset beep

# не спрашивать про поле CC при написании письма

set askcc=no

# подпись выводится как результат скрипта

set signature="~/.mutt/scripts/signature|"

# просматривать письма встроенным пейджером; можно указать команды less|more

set pager=builtin

# не показывать следующее письмо после текущего

set pager_stop

# мы берем версию агента из самопальных заголовков

set user_agent=no

# если ты собрал mutt с патчем поддержки NNTP, то для чтения новостей потребуются следующие опции:

set news_cache_dir="~/Maildir/nntp"

set news_server="my.news.server"

set newsrc="~/.mutt/news.mutt"

set catchup_newsgroup=ask-yes

set nntp_context=2000

set nntp_load_description=yes

# если сервер требует авторизации

#set nntp_user=""

#set nntp_pass=""

set nntp_poll=60

set nntp_reconnect=ask-yes

# далее идет, пожалуй, самый важный параметр. По умолчанию mutt, как классический юниксовый почтовый клиент, хочет использовать локальный почтовый сервер, sendmail. Но у нас нет такового на рабочей машине, и мы используем msmtp.

set sendmail="/usr/local/bin/msmtp"

# следующие опции понадобятся для поддержки Maildir:

set mbox_type="Maildir"

set spoolfile=~/Maildir/default

set mbox=~/Maildir/default

# здесь складывается отложенная почта

set postponed=~/Maildir/postponed

# а здесь отправленная

set record=~/Maildir/sent

# помимо цветовых схем, mutt позволяет гибко настраивать вывод информации о ящиках на тулбар. Описание несложного синтаксиса можно найти в официальной документации, но и так ясно, что %d означает количество удаленных писем, а %n - новых, и т.д.

set status_format="%v [%f] [%m msgs (%l), %n new, %p unsent, %d deleted]"

set folder_format="%N %F %2l %-8.8u %-8.8g %8s %d %f"

set index_format="%3C %Z %{%b %d} %-20.20L (%?l?%4l&%4c?) %s"

Еще раз повторюсь, что здесь отмечены не все опции. Так, например, полностью опущена работа со списками рассылки. На диске ты найдешь ПОЛНЫЙ комплект моих рабочих конфигов, проверенных и оттачиваемых годами, со всеми комментариями. Актуальную версию конфигов (все-таки я время от времени что-нибудь исправляю) можно взять с www.toxahost.ru/projects.html.

[получаем и отправляем]

Читать почту мы уже умеем, а вот отправлять и получать - пока еще нет. Настройка msmtp не займет много времени. Его конфигурационный файл поделен на секции, каждая из которых начинается с директивы account <название_аккаунта>. По умолчанию msmtp ищет аккаунт с названием default, но можно указать любую другую учетную запись с помощью аргумента '-a'. Таким образом, переключение почтовых серверов, через которые будет отправляться почта, в связке mutt+msmtp будет осуществляться с помощью хоткея (см. bindings.mutt), устанавливающего переменную sendmail в значение вида msmtp -a account.

$ vi ~/.msmtprc

# минимальная настройка включает в себя имя аккаунта, имя хоста и поле from

account default

host toxahost.ru

from toxa@toxahost.ru

# если же требуется SMTP-авторизация или доступ по TLS - нет проблем

account toxahost-auth-tls

host toxahost.ru

auth login

user toxa

password mycoolpass

tls

tls_nostarttls

tls_nocertcheck

from toxa@toxahost.ru

За получение почты отвечает getmail. Ее конфигурационные файлы располагаются в каталоге ~/.getmail и имеют формат «один файл - один аккаунт». Getmail умеет доставлять почту как по plain POP3/IMAP, так и по POP3S/IMAPS (POP3/IMAP over SSL), достаточно указать соответствующий тип доставки. Типичный конфиг состоит из трех частей - общих опций (options), опций протокола (retriever) и опций доставки (destination).

$ vi ~.getmail/getmailrc

# здесь мы указываем общие опции, выставляемые для данного аккаунта

[options]

# включаем подробное журналирование действий

verbose = 1

# указываем получать все сообщения с POP3-сервера, в том числе и прочитанные

readall = yes

# удалять после получения

delete = yes

# протоколировать процесс

message_log = /var/log/getmail.log

timeout = 360

max_message_size = 0

# самая главная часть - протокол, логин, пароль

[retriever]

type = SimplePOP3Retriever

server = toxahost.ru

username = toxa

password = mycoolpass

# а здесь мы указываем, как будет осуществляться обработка почты

[destination]

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

type = MDA_external

# а именно - procmail

path = /usr/local/bin/procmail

Если вместо незащищенного плайнтекстового POP3 используется POP3-over-SSL, и демон принимает такие соединения на порту 995, надо всего лишь изменить секцию retriever на следующую:

[retriever]

type = SimplePOP3SSLRetriever

server = toxahost.ru

port = 995

username = toxa

password = mycoolpass

В сведениях о доставке мы указали, что вся почта будет отдаваться на обработку procmail, который и займется сортировкой писем по папкам. Это очень удобно, когда ты подписан на несколько списков рассылки, или просто хочешь раскладывать письма по разным папкам в зависимости от отправителя. Синтаксис конфигурационного файла procmail выполнен в традиционном наркоманском стиле ;), характерным для oldschool-программ. Вкратце, после объявления переменных каждая запись имеет вид «действие до - условие - действие после», где «действие до» может быть перенаправлением другой программе, переписыванием полей письма и т.д., «условие» - регексп, по которому выполняется «действие после» - перемещение письма в заданную папку, вызов внешней программы и прочее. Синтаксис записей ужасен, но именно благодаря своим возможностям делать с почтой все, что душе угодно, procmail и по сей день остается самым мощным средством фильтрации сообщений.

$ vi ~/.procmailrc

MAILDIR=$HOME/Maildir/

LOGFILE=$HOME/.procmaillog

LOGABSTRACT=no

VERBOSE=no

DROPPRIVS=yes

FORMAIL=/usr/local/bin/formail

NL="

"

# прежде всего, вызываем проверку ВСЕХ писем на спам с помощью SpamAssassin. Об этом чуть позже.

:0fw: spamassassin.lock

| /usr/local/bin/spamc

# письма, помеченные как спам, уходят в трэш

:0:

* ^X-Spam-Status: Yes

$MAILDIR/junk/

# html-письма тоже уходят в трэш

:0

* ^Content-Type:.*html

$MAILDIR/junk/

# письма из списка рассылки freebsd перемещаются в отведенную для них папку

:0

* ^List-Id:.*freebsd

$MAILDIR/freebsd-lists/

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

:0

* ^(FROM|TO):.*root@*

$MAILDIR/toxahost/

# все остальное сыпется в основной ящик по умолчанию

:0

* .*

$MAILDIR/default/

Пару слов о спаме. Самым первым вызовом procmail была проверка писем на спам. В принципе, для этого достаточно просто установить SpamAssassin, так как утилита spamc, входящая в его комплект, позволяет проверять письма автономно, без запуска сервера СпамАссассина, spamd. Но при запущенном сервере проверка идет гораздо быстрее.

# echo spamd_enable="YES" >> /etc/rc.conf

# /usr/local/etc/rc.d/sa-spamd start

[финальный штрих]

Вот и все. Последний штрих - создание файла ~/.mailcap, в котором будут прописаны соответствия вызываемых программ различным MIME-типам. Так, кто сказал, что mutt не умеет читать вложенные doc-файлы?

$ echo "application/msword; antiword -m koi8-r.txt %s; copiousoutput" >> ~/.mailcap

Теперь при получении письма с аттачем MIME-типа application/msword (когда тебе во вложении пришлют doc-файл) mutt вызовет программу antiword, которая удобно представит тебе содержимое doc-файла в текстовом виде. По аналогии можно сопоставить другие программы различным MIME-типам. На диске ты найдешь полные варианты всех упомянутых сегодня конфигов, в том числе и «боевой» mailcap. Просто поставь из пакетов/портов недостающие утилиты и - готово.

Что такое UNIX-way?

Вопрос этот из разряда философских. И не стоит в компании фанатичных юниксоидов поднимать на обсуждение тему вроде «правда ли, что perl - это не UNIX-way» :). Технически же - это то, на чем основана вся работа в классическом UNIX: когда для каждой конкретной задачи существует одна маленькая программа, ничего больше не умеющая, зато выполняющая свою работу на все сто. Гибкость и сила проявляются в соединении этих программ, например, через каналы (pipes), когда вывод одной команды подается на ввод другой. Например, если я хочу посчитать, сколько человек запросило определенный файл с сервера по http, я набираю команду:

# cat /var/log/httpd-access.log | grep 46664.mpg | awk '{print $1}' | sort | uniq | wc -l

200

В этой простой команде задействовано 6 утилит. В *nix-системе их сотни, каждая делает что-то свое и имеет огромное количество опций, так что можно представить, откуда берется та пресловутая гибкость работы в *nix. Гибкость увеличивается также и классической юниксовой парадигмой «все - файл», когда любая прикладная задача сводится, по сути, к работе с текстовыми файлами с помощью вышеозначенных утилит.

Разбираемся с терминологией

Почтовый клиент сокращенно называют MUA (Mail User Agent). По аналогии, почтовый сервер называют MTA (Mail Transfer Agent). Программа же, занимающаяся доставкой почты от сервера клиенту (но не обработкой, ни чтением, ни, тем более, составлением писем), называется MDA - Mail Delivery Agent.

Будь внимателен, убирая из crontab все запуски periodic. Взгляни на скрипты в /etc/periodic: помимо составления отчетов руту, регулярно выполняются такие вещи, как обновления базы для locate(1). Бездумно удаляя все подряд можно, например, лишить себя свежей locate.database.

 

(Администратор не несет ответственности (Автор Денис Евгеньевич)