пятница, 25 марта 2011 г.

Декодирование писем в формате TNEF в Postfix

Вчера столкнулся с интересной проблемой, корень которой в очередной раз нашёлся в Microsoft. Один из сотрудников пожаловался, что некоторые письма к нему приходят без вложений. Я попытался разобраться в ситуации и выяснил, что письма в почтовом клиенте имеют точно такой же размер, какой они имеют, когда их принимает Postfix. Стало быть почтовый сервер, почтовый клиент, антивирус на сервере и на компьютере почтового клиента никаких изменений в письма не вносят.

Потом я обратил внимание на размер письма (несколько сотен килобайт) и на отображаемый в клиенте текст. Письмо было явно слишком большим для такого небольшого объёма информации. Я заглянул в исходный текст письма и обнаружил, что в нём имеется вложение с именем файла "winmail.dat" и MIME-типом "application/ms-tnef".

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

Первым делом я нашёл рецепт отключения этой фичи в Outlook отправителя
Файлы winmail.dat в письмах и отправил эту ссылку отправителю.

Предвидя возможные повторы этой проблемы и необходимость снова и снова отправлять эту ссылку разным людям, я поискал, а нельзя ли этот TNEF преобразовывать прямо на сервере? Нашёл следующую заметку Postfix + ytnef filter, которая, к слову, была написана всего полтора месяца назад. Так что если бы я столкнулся с проблемой раньше, возможно мне так и пришлось бы отправлять людям ссылку.

Там описывается настройка прокси-конвертера ytnef smtpd для FreeBSD. Поскольку у меня сервер работает под Debian Lenny, я решил выложить тут адаптированный вариант, а иначе просто ограничился бы ссылкой.

Итак, перво-наперво, ставим сам конвертер ytnef и python:
# aptitude install --with-recommends ytnef
# aptitude install python
Качаем архив со скриптом по ссылке и распаковываем его:
$ wget http://www.viraj.org/ytnef_smtpd/ytnef_smtpd-1.1.tar.gz
$ tar xzvf ytnef_smtpd-1.1.tar.gz
$ cd ytnef_smtpd-1.1
Копируем скрипт туда, где ему положено лежать:
# cp ytnef_smtpd.py /usr/local/bin/
# chmod +x /usr/local/bin/ytnef_smtpd.py
И меняем настройки скрипта, которые находятся в нём самом-же. У меня в Postfix уже есть два прокси, первый сканирует письма на предмет наличия вирусов, а второй проставляет оценки уровня спама. Наша задача - встроить новый прокси в начало цепочки, чтобы сначала письмо преобразовывалось, а затем уже проверялось и оценивалось.

Приведу лишь изменённые строки:
LISTEN_PORT = 10028
REMOTE_PORT = 10026
YTNEF_BIN = '/usr/bin/ytnef'
FILE_BIN = '/usr/bin/file'
LOG_FILE = '/var/log/ytnef_smtpd.log'
Скрипт будет ожидать подключений к порту 10028, а преобразованное письмо будет отправлять на порт 10026, где его будет ловить уже антивирус.

Теперь создадим скрипт автозапуска /etc/init.d/ytnef_smtpd.sh (он немного отличается от оригинала):
#!/bin/sh

case "$1" in
  start)
    if [ -f /var/run/ytnef_smtpd.pid ]
    then
      echo "Script already launched. PID: "`cat /var/run/ytnef_smtpd.pid`"
    else
      echo "Starting ytnef smtpd..."
      /usr/local/bin/ytnef_smtpd.py &
      echo $! > /var/run/ytnef_smtpd.pid
      echo "...Done!"
    fi
    ;;
  stop)
    if [ -f /var/run/ytnef_smtpd.pid ]
    then
      echo "Shutting down ytnef smtpd..."
      kill -TERM `cat /var/run/ytnef_smtpd.pid`
      rm -f /var/run/ytnef_smtpd.pid
      echo "...Done!"
    else
      echo "ytnef smtpd not launched."
    fi
    ;;
  *)
    echo "Use start script for: { start | stop }" >&2
    exit 1
    ;;
esac
Пропишем его автозапуск и запустим:
# chmod +x /etc/init.d/ytnef_smtpd.sh
# update-rc.d ytnef_smtpd.sh defaults
# /etc/init.d/ytnef_smtpd.sh start
Теперь скрипт должен прослушивать порт 10028, это можно проверить следующей командой:
# netstat -nlp4 | grep 10028
Если это так, значит пока что всё идёт нормально.

Теперь нужно перенастроить Postfix, так чтобы он перенаправлял только что полученные письма на обработку ytnef smtpd.

В файле /etc/postfix/main.cf прописываем порт первого прокси в цепочке (в нашем случае это порт ytnef smtpd - 10028):
content_filter = scan:127.0.0.1:10028
И если до этого у вас не было прокси, добавляем в файл /etc/postfix/master.cf следующие строчки (обратите внимание на пробелы в начале всех строк, кроме первой):
127.0.0.1:10025 inet n - n - 16 smtpd
  -o content_filter=
  -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
  -o smtpd_helo_restrictions=
  -o smtpd_client_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks_style=host
  -o smtpd_authorized_xforward_hosts=127.0.0.0/8
Эти строчки настроят ещё один smtp-сервер, который будет принимать письма на порту 10025 только от локальных программ, но при этом не будет отправлять письма на дальнейшую проверку. Именно этот порт необходимо указать в настройке "REMOTE_PORT", если у вас больше нет никаких прокси в цепочке.

Осталось перезапустить postfix и всё должно заработать:
# /etc/init.d/postfix restart
Я специально ради этого устанавливал себе на компьютер Outlook, отправил из него письмо в формате tnef и принял в Outlook Express. Письмо прочиталось вместе с вложениями.

5 комментариев:

Анонимный комментирует...

Спасибо за статью.
Недавно столкнулся с такой же проблемой. Все сделал как описано, но в результате в проходящее письмо X-header добавляется а вложение так и остается winmail.dat. Единственное до чего докопался:
после окончания работы ytnef временные файлы, вытащенные из winmail.dat остаются лежать в директории откуда был запущен стартовый скрипт, причем их имена имеют вид _tmp_tmptq9hf8_attache1.docx
Видно что где-то '/' меняется на '_' где понять не могу.

Прошу помощи

morbo комментирует...

Может быть вы забыли поставить сам конвертер - пакет ytnef?

Анонимный комментирует...

Товарищи, у кого есть ytnef_smtpd-1.1.tar.gz? Авторский сайт недоступен, в интернете не могу найти. Выложите, пожалуйста, кто может.
Заранее спасибо :)

morbo комментирует...

Скачал с того сервера, на котором когда-то настраивал. Благо доступ ещё сохранился. Положил сюда: http://stupin.su/files/ytnef_smtpd-1.1.tar.gz

Анонимный комментирует...

Огромное спасибо, взял :)