Мы запускаем exim версии 4.72 в Debian Squeeze 6 (Squeeze) (LTS).
Exim используется для только исходящие письма - он не обрабатывает электронные письма с других серверов / доменов - он только обрабатывает (исходящее) сообщение от локального запущенного java (веб) приложения.
Для анонимности предположим, что домен, который мы используем для адресов электронной почты нашей компании, а также для домена, на котором работает наше веб-приложение java, называется example.com.
У нас есть веб-приложение, написанное на платформе java, которое позволяет пользователям отправлять электронные письма. В envelope-from
адрес этих писем принадлежит нашему домену: support@example.com.
Технически эти электронные письма создаются и отправляются из веб-приложения java (мы используем JavaMail API) локально в exim, который затем в конечном итоге отправляет их на их адрес назначения.
Входящие электронные письма в наш домен обрабатываются Google Apps / Gmail (мы также настраиваем записи SPF и т. Д.)
Эта установка пока работает нормально без каких-либо проблем.
Для завершения вот наш (анонимный) update-exim4.conf.conf
:
root@server:~# cat /etc/exim4/update-exim4.conf.conf
# ... comments are skipped ...
dc_eximconfig_configtype='internet'
dc_other_hostnames='node1.example.com'
dc_local_interfaces='127.0.0.1 ; ::1'
dc_readhost=''
dc_relay_domains=''
dc_minimaldns='false'
dc_relay_nets=''
dc_smarthost=''
CFILEMODE='644'
dc_use_split_config='true'
dc_hide_mailname=''
dc_mailname_in_oh='true'
dc_localdelivery='maildir_home'
В последнее время мы получаем сообщения о недоставке, потому что пользователи нашего веб-приложения на Java пытались отправить электронные письма на несуществующие адреса электронной почты.
Давайте посмотрим на такой случай в (анонимном) файле журнала:
root@server:~# cat /var/log/exim4/mainlog
# try to send an email to an unrouteable address
2014-06-01 17:34:07 1Wr7lv-0000CR-G0 <= support@example.com H=localhost (node1.example.com) [127.0.0.1] P=esmtp S=620363 id=484648301.663.1401636847496.JavaMail.webapp@node1
2014-06-01 17:34:07 1Wr7lv-0000CR-G0 ** doesnotexist@anotherdomain.com: Unrouteable address
2014-06-01 17:34:07 1Wr7lv-0000CR-G0 Completed
# Immediately a bounce message is generated and gets send to the the origin sender
2014-06-01 17:34:07 1Wr7lv-0000CU-OZ <= <> R=1Wr7lv-0000CR-G0 U=Debian-exim P=local S=108065
2014-06-01 17:34:09 1Wr7lv-0000CU-OZ => support@example.com R=dnslookup T=remote_smtp H=aspmx.l.google.com [74.125.136.26] X=TLS1.0:RSA_ARCFOUR_SHA1:16 DN="C=US,ST=California,L=Mountain View,O=Google Inc,CN=mx.google.com"
2014-06-01 17:34:09 1Wr7lv-0000CU-OZ Completed
Теперь мы хотим показать (или уведомить - что угодно) каждого пользователя веб-приложения Java. в веб-приложении Java что электронное письмо, которое он / она хотел отправить, на самом деле не было отправлено.
(Помните: письмо о недоставке в настоящее время отправляется обратно на адрес support@example.com - не на адрес электронной почты пользователей веб-приложения - чтобы эти пользователи понятия не имели, что их электронные письма не были отправлены)
Основная (и простая) идея, которая у нас теперь есть:
Заставьте exim написать id
каждого неудачного сообщения (которое в приведенном выше случае 484648301.663.1401636847496.JavaMail.webapp@node1) в локальную работающую базу данных PostgreSQL, как только мы узнаем, что доставка сообщения не удалась (или: как можно скорее было сгенерировано и / или отправлено соответствующее сообщение о недоставке).
Если это возможно, мы могли бы легко прочитать эти «неудачные» id
s из базы данных в нашем веб-приложении java и - вуаля! - мы можем показать пользователям, что их сообщения были возвращены.
Простая идея, не правда ли?
Просто для лучшего понимания: упомянутый (уникальный) id
s уже генерируются для каждого сообщения в веб-приложении Java. перед API JavaMail отправляет сообщение в exim, поэтому мы можем быть уверены, что наше веб-приложение Java знает каждый id
для каждого сообщения (и, конечно, также знает, какой пользователь отправил конкретное сообщение).
Я провел небольшое исследование, как это мог быть решенным, и это то, что я придумал к настоящему времени (пожалуйста, исправьте мое, если я ошибаюсь - это только мои мысли прямо сейчас):
Подход 1: Отправьте сообщение об ошибке, и оно id
в сценарий bash. Такой сценарий bash мог бы легко сохранить id
в локальной базе данных PostgreSQL. Возможно ли это и как этого добиться? Проблема, которую я вижу, заключается в том, что как только сообщение не удалось, ни один другой маршрутизатор exim не запускается - это означает, что я не могу написать маршрутизатор, который обрабатывает неудачное сообщение - неудачное сообщение никогда не достигнет маршрутизатора. Или я не прав?
Подход 2: Еще одна возможность, о которой я думал, - это не взгляните на исходное сообщение, которое не удалось, но на вновь созданное сообщение о недоставке. Насколько я понимаю, это новое сообщение о недоставке также проходит через все маршрутизаторы, пока его не примут. Так, может быть, мы могли бы написать маршрутизатор, который проверяет, является ли сообщение рикошетом, а затем перенаправляет его в сценарий bash? Но как мне узнать, является ли сообщение рикошетом? У него есть специальный заголовок или что-то еще значимое? (Помните: поскольку мы используем exim только для исходящий электронных писем, мы можем быть уверены, что это всегда будет сообщение о недоставке, «сгенерированное» пользователями нашего Java-приложения).
Подход 3: Подобно подходу 2, но вместо написания маршрутизатора мы могли бы использовать системный фильтр, который отслеживает сообщение о недоставке, а затем выполняет команду / канал ...
Подход 4: Можно ли настроить error_copy
или даже error_to
быть не адресом электронной почты, а каналом для сценария оболочки (который, конечно, получил идентификатор и / или все сообщение об ошибке)?
Еще две вещи: кажется, exim также может напрямую общаться с базами данных (я где-то это читал) - но я понятия не имею, как я могу использовать это для моей описанной проблемы. Плюс: Однако это решено, я не хочу изменять какие-либо файлы конфигурации, которые переопределяются при обновлении exim через apt-get
(Я не хочу заново настраивать exim после каждого обновления).
Как бы вы решили эту проблему (сохранение неудачного сообщения id
s в базу данных)? Пожалуйста, поправьте меня. Если я где-то ошибался - я не так глубоко разбираюсь в конфигурации exim. Кроме того, как вы можете видеть, решения, о которых я думаю, являются более теоретическими - было бы хорошо, если бы кто-нибудь мог показать мне конфигурации реального мира и где разместить эти конфигурации, чтобы они работали.
Большое спасибо за любую помощь!
Exim версии 4.82.1 имеет функцию под названием TPDA (Transport Post Delivery Action), которая позволит вам делать именно то, что вы хотите. У вас должна быть возможность переключить источники вашего репозитория и установить эту более новую версию exim, которая даст вам версию с такой возможностью.
Если вы настаиваете на использовании текущей версии, предоставленной дистрибутивом, я не думаю, что это хороший вариант.