- Не требуется доступность извне, т.е. ненужен белый IP-адрес.
- Не нужно настраивать полноценный почтовый сервер и отвечать за него.
- Отложенная доставка. В случае отключения Mailman письма будут оставаться на удаленном сервере. При включении они будут обработаны Mailman.
- Дополнительная нагрузка на сеть. Т.к. приходится опрашивать POP3/IMAP сервер на предмет наличия почты.
- Как следствие более длительная рассылка почты в зависимости от интервала опроса.
Установка Mailman
Далее произведем установку и подготовку пакета. Для примера настройки выбран дистрибутив Slackware64-14.1 и mailman 2.1.18-1. Использовались следующие зависимости в системе:- python >= 2.6
- dnspython >= 1.11 (http://www.dnspython.org/)
- apache >= 2.4
groupadd -g 204 mailman
useradd -u 204 -d /home/mailman -s /bin/bash -g mailman mailman
Качаем слакбилд и исходники mailman:
cd /tmp/
wget http://slackbuilds.org/slackbuilds/14.1/network/mailman.tar.gz
tar zxvf ./mailman.tar.gz && cd mailman
wget http://ftp.gnu.org/gnu/mailman/mailman-2.1.18-1.tgz
В моем случае слакбилд был для версии 2.1.17, таким образом пришлось модифицировать пару строк внутри:
sed -i 's/\(VERSION:-\)[0-9.]*/\12.1.18-1/' ./mailman.SlackBuild
sed -i '/makepkg/c\/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-${VERSION/-/_/}-$ARCH-$BUILD$TAG.${PKGTYPE:-tgz}' ./mailman.SlackBuild
Собираем пакет:
MAIL_GID=mailman VAR_PREFIX="/var/mailman" ./mailman.SlackBuild
Если ранее были установлены все зависимости, пакет должен быть собран без проблем. Пакет подготовлен для установки в /opt/mailman.
Далее установка пакета:
installpkg /tmp/mailman-2.1.18_1-x86_64-1_SBo.tgz
Теперь исправляем права доступа:
сhgrp -R apache /var/mailman/archives/public
cd /opt/mailman; ./bin/check_perms -f
cp /opt/mailman/Mailman/Handlers/SMTPDirect.py /opt/mailman/Mailman/Handlers/ASMTPDirect.py
patch -d /opt/mailman/ -p0 -i `pwd`/ASMTPDirect.patch
Нажмите для просмотра файла ASMTPDirect.patch
--- Mailman/Handlers/ASMTPDirect.py 2014-10-29 18:09:11.729196543 +0600
+++ Mailman/Handlers/ASMTPDirect.py 2014-10-30 21:07:16.702143716 +0600
@@ -15,9 +15,9 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
-"""Local SMTP direct drop-off.
+"""Local/Remote SMTP direct drop-off.
-This module delivers messages via SMTP to a locally specified daemon. This
+This module delivers messages via SMTP to a local or remote server. This
should be compatible with any modern SMTP server. It is expected that the MTA
handles all final delivery. We have to play tricks so that the list object
isn't locked while delivery occurs synchronously.
@@ -44,6 +44,8 @@
from email.Header import Header
from email.Charset import Charset
+import re
+
DOT = '.'
try:
@@ -60,14 +62,23 @@
self.__conn = None
def __connect(self):
- self.__conn = smtplib.SMTP()
- self.__conn.connect(mm_cfg.SMTPHOST, mm_cfg.SMTPPORT)
+ if mm_cfg.SMTP_SSL:
+ self.__conn = smtplib.SMTP_SSL()
+ else:
+ self.__conn = smtplib.SMTP()
+ self.__conn.connect(mm_cfg.SMTP_HOST, mm_cfg.SMTP_PORT)
self.__numsessions = mm_cfg.SMTP_MAX_SESSIONS_PER_CONNECTION
+ if mm_cfg.SMTP_STARTTLS:
+ self.__conn.starttls()
+ if mm_cfg.SMTP_AUTH:
+ self.__conn.login(mm_cfg.SMTP_USERNAME,mm_cfg.SMTP_PASSWORD)
def sendmail(self, envsender, recips, msgtext):
if self.__conn is None:
self.__connect()
try:
+# syslog('smtp-failure',"\n%s\n",
+# msgtext)
results = self.__conn.sendmail(envsender, recips, msgtext)
except smtplib.SMTPException:
# For safety, close this connection. The next send attempt will
@@ -376,6 +387,18 @@
if mlist.include_sender_header:
del msg['sender']
msg['Sender'] = '"%s" <%s>' % (mlist.real_name, envsender)
+
+ # Set properly From header
+
+ out_addr = mm_cfg.SMTP_USERNAME
+ p = re.compile(r'([-\w\.]+)@((?:\w+\.)+)(\w{2,4})')
+ old_from = msg['From']
+ if 'Reply-To' not in msg:
+ msg.add_header('Reply-To',old_from)
+ del msg['From']
+ msg['From'] = p.sub(out_addr,old_from)
+ envsender = out_addr
+
# Get the plain, flattened text of the message, sans unixfrom
# using our as_string() method to not mangle From_ and not fold
# sub-part headers possibly breaking signatures.
Теперь настроим доступ к веб-интерфейсу. Создадим файл /etc/httpd/mailman.conf:
Alias /pipermail/ /var/mailman/archives/public/
<Directory "/var/mailman/archives/public">
Options Indexes FollowSymlinks
AllowOverride None
Require all granted
</Directory>
ScriptAlias /mailman/ /opt/mailman/cgi-bin/
<Location "/mailman/">
Options +ExecCGI
Require all granted
</Location>
Alias /mailman_icons/ /opt/mailman/icons/
<Directory "/opt/mailman/icons">
Require all granted
</Directory>
И подключим его в /etc/httpd/httpd.conf:
# Access to mailman
#
Include /etc/httpd/mailman.conf
В httpd.conf также необходимо включить поддержку CGI.
LoadModule cgid_module lib64/httpd/modules/mod_cgid.so
LoadModule cgi_module lib64/httpd/modules/mod_cgi.so
В остальном Apache настраивается как обычно. Не забываем заставить httpd перечитать конфиг с нашими изменениями:
/etc/rc.d/rc.httpd graceful
Настройка
# Прежде всего необходимо прописать почтовый домен с которым работает Mailman:
DEFAULT_EMAIL_HOST = 'mydomain.ru'
# Укажем DNS имя сервера на котором работает веб интерфейс Mailman:
DEFAULT_URL_HOST = 'localhost'
# Дополнительно укажем язык по умолчанию и URL для иконок:
DEFAULT_SERVER_LANGUAGE = 'ru'
IMAGE_LOGOS = '/mailman_icons/'
# Укажем пропатченный модуль SMTP с применением аутентификации:
DELIVERY_MODULE = 'ASMTPDirect'
# SMTP сервер:
SMTP_TLS = Yes
SMTP_HOST = 'smtp.yandex.ru'
SMTP_PORT = 587
# Далее приведем настройки аутентификации аккаунта SMTP
# от которого будут отправляться все письма Mailman:
SMTP_AUTH = Yes
SMTP_USERNAME = 'noreply'
SMTP_EMAIL_HOST = 'mydomain.ru'
SMTP_PASSWORD = 'mypass'
Далее укажем пароль к сайту:
cd /opt/mailman
./bin/mmsitepass
Пароль администратора сайта можно использовать для создания новых списков через веб интерфейс. Также рассмотрим создание списка рассылки с консоли.
Рассмотрим типичную структуру списка почтовых адресов в Mailman:| аккаунт | описание |
|---|---|
| somelist | отправка в список somelist |
| somelist-admin | отправка сообщения администраторам списка |
| somelist-bounces | письма от неразрешенных адресов перенаправляются сюда администратор также получит уведомление |
| somelist-confirm | подтверждение при подписке или отписке |
| somelist-join | запрос на подписку |
| somelist-leave | запрос на отписку |
| somelist-owner | отправка создателю списка |
| somelist-request | изменение настроек подписки |
| somelist-subscribe | синоним somelist-join |
| somelist-usubscribe | синоним somelist-leave |
Таким образом нам необходимо для каждого списка создать 10 email адресов в зоне mydomain.ru. А также 1 email noreply с которого будет происходить отправка писем с помощью модуля ASMTPDirect. Ещё 1 email администратора указывается при создании списка.
Создаем почтовый список somelist:
./bin/newlist somelist
GNU Mailman также требует создание списка mailman, иначе он не будет запускаться. ./bin/newlist mailman
Обязательно нужно указать email создателя списка и пароль для редактирования настроек списка через сайт.Также потребуется создать 10 email адресов в вашем домене для списка somelist, с которых мы будем забирать почту через fetchmail. Т.к. список mailman не используется, создавать для него 10 email не обязательно.
Исходный список синонимов для перенаправления в mailman для локального SMTP сервера выглядит следующим образом:
somelist: "|/opt/mailman/mailman/mail/mailman post somelist"
somelist-admin: "|/opt/mailman/mailman/mail/mailman admin somelist"
somelist-bounces: "|/opt/mailman/mailman/mail/mailman bounces somelist"
somelist-confirm: "|/opt/mailman/mailman/mail/mailman confirm somelist"
somelist-join: "|/opt/mailman/mailman/mail/mailman join somelist"
somelist-leave: "|/opt/mailman/mailman/mail/mailman leave somelist"
somelist-owner: "|/opt/mailman/mailman/mail/mailman owner somelist"
somelist-request: "|/opt/mailman/mailman/mail/mailman request somelist"
somelist-subscribe: "|/opt/mailman/mailman/mail/mailman subscribe somelist"
somelist-unsubscribe: "|/opt/mailman/mailman/mail/mailman unsubscribe somelist"
Далее настроим получение почты с удаленного сервера с помощью fetchmail. Тут есть один нюанс: у пользователя от которого запускается fetchmail, основная (первая) группа должна быть mailman. Именно поэтому я решил использовать пользователя mailman для хранения конфига fetchmail.
Создаем конфиг .fetchmailrc
touch /home/mailman/.fetchmailrc
chmod 600 /home/mailman/.fetchmailrc
Примерная конфигурация будет выглядеть следующим образом:poll pop.yandex.ru
port 995
protocol POP3
user "somelist@mydomain.ru" with password "pass" mda "/opt/mailman/mail/mailman post somelist"
ssl
sslcertpath /home/mailman/.sslcerts
sslfingerprint "44:A8:E9:2C:FB:A9:7E:6D:F9:DB:F3:62:B2:9E:F1:A9"
poll pop.yandex.ru
port 995
protocol POP3
user "somelist-admin@mydomain.ru" with password "pass" mda "/opt/mailman/mail/mailman admin somelist"
ssl
sslcertpath /home/mailman/.sslcerts
sslfingerprint "44:A8:E9:2C:FB:A9:7E:6D:F9:DB:F3:62:B2:9E:F1:A9"
...
И так далее для всех остальных email. Более подробно настройку сертификатов fetchmail смотри на OpenNET: http://www.opennet.ru/base/net/fetchmail_setup.txt.html
Запуск fetchmail от пользователя mailman будет выглядеть следующим образом:
su mailman -c 'fetchmail -d 120 -a -L ~/.fetchmail.log 2>&1'
Остановка: su mailman -c 'fetchmail -q 2>&1'
Эти строки я рекомендую прописать в /etc/rc.d/rc.mailman для запуска и остановки вместе с mailman. Я проверяю почту каждые 120 секунд. Такого быстродействия вполне достаточно для слабоактивных списков рассылки.
Пропишем crontab для пользователя mailman:
crontab /usr/local/mailman/cron/crontab.in -u mailman
И запустим mailman для обработки очередей входящих/исходящих писем:
/etc/rc.d/rc.mailman start
Заключение
При желании можно настроить Mailman для работы с удаленным почтовым сервером. После всех настроек необходимо проверить работоспособность конфигурации.Также был сделан SlackBuild который внутри уже содержит патч для создания модуля ASMTPDirect.py.
Ссылки: