Pull to refresh

Почтовый сервер на собственном сайте с помощью postfix

Reading time 6 min
Views 12K
В прошлый раз я рассматривал пример создания подобного сервиса на примере sendmail. Напомню, целью данного деяния создать на основе существующего сайта небольшой почтовый сервис с возможностью получения на сайте входящих сообщений для пользователей. Так как по изученным мною данным postfix является вторым по использованию агентом и используется где-то на 30% серверах, я решил изучить и его для решения данной задачи. Кроме прочего postfix имеет более широкие возможности защиты и в частности поддержку SSL/TLS, которую в sendmail я, к сожалению, так и не обнаружил. В довесок postfix позволяет напрямую обращаться к базе данных, а также поддерживает формат maildir, который насколько я помню в senfmail также отсутствует. А так как однозначного ответа на просторах интернета я, как и в прошлый раз, не нашел, думаю инструкция все-таки будет полезна.



В первую очередь необходимо прописать настройки в dns-зоне:

Для MX:

@ IN MX 10 mail.site.ru.


И для AAAA:

@ IN AAAA 2001:0db8:85a3:0000:0000:8a2e:0370:7334


И для A:

mail.site.ru. IN A 

Указанный в ДНС MX адрес также надо будет прописать в /etc/hosts, добавив:

mail.site.ru


В файле /etc/postfix/main.cf отредактируем параметр mydestination. Он не должен содержать домена на который мы будем принимать сообщения для виртуальных пользователей. Если кроме виртуальных пользователей других не планируется, то можно его и вовсе оставить пустым.

mydestination =


Для записи в файл нам понадобиться отредактировать все тот же /etc/postfix/main.cf

Добавим в него параметры virtual_uid_maps, virtual_gid_maps, virtual_mailbox_domains, virtual_mailbox_maps и virtual_mailbox_domains. Выглядеть все это дело будет следующим образом


virtual_uid_maps = static:1001, static:1002 
virtual_gid_maps = static:1001, static:1002
virtual_mailbox_domains = /etc/postfix/vhosts
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_mailbox_base = /home


Параметр virtual_uid_maps содержит идентификатор пользователя, от имени которого мы будем записывать сообщения, virtual_gid_maps делает тоже самое, но для группы. Если их несколько можно перечислить их через запятую. В директиву virtual_mailbox_base необходимо указать путь для корневого каталога всех возможных почтовых ящиков. Вдальнейшем он будет формировать примерно следующим образом virtual_mailbox_base+vmailbox и получится что-то навроде (/home)+(/)+(site.ru/public_html/mail)=/home/site.ru/public_html/mail

Далее создадим файл vhosts в папке /etc/postfix. В нем с каждой новой строчки необходимо прописать домены, с которых мы будем принимать сообщения для наших виртуальных пользователей.


site.ru
poddomen.site.ru
site.com


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


@site.ru                     site.ru/public_html/mail
@poddomen.site.ru   poddomen.site.ru/public_html/mail
@site.com                  site.com/public_html/mail


Такая инструкция будет записывать все входящие сообщения с доменом site.ru, в файл /home/site.ru/public_html/mail. Добавим в конце слеш и получим формат Maildir.


@site.ru                     site.ru/public_html/mail/
@poddomen.site.ru   poddomen.site.ru/public_html/mail/
@site.com                  site.com/public_html/mail/


Он будет более удобен, так как создает файл для каждого отдельного сообщения. Все новые сообщения передаются в папку /home/user/public_html/mail/new. Создаваемые файлы формируются из текущего времени, имени хоста, идентификатора процесса, создавшего этот файл, и некоторого случайного числа. Главный недостаток данной записи в отсутствии четкой номенклатуры. И разобрать где и чья почта довольно проблематично. Поэтому наиболее подходящим вариантом будет указать конкретных пользователей.


user1@site.ru site.ru/public_html/mail/user1/
user2@site.ru site.ru/public_html/mail/user2/
user3@site.ru site.ru/public_html/mail/user3/


Теперь нам необходимо добавить некоторой гибкости данному процессу. Его можно добиться перенеся наших пользователей и пути с директориями для хранения сообщений в базу. В postfix для этих целей по сути существует админка PostfixAdmin, но я ставлю целью внедрить данный функционал непосредственно в сайт, поэтому она нам не понадобится. Сами базы логичнее создавать конечно непосредственно в таблице с пользователями сайта, но я покажу на примере отдельной базы.

CREATE TABLE `virtual_domains` (
	`user` VARCHAR(50) NOT NULL COLLATE 'cp1251_general_ci',
	`mail` VARCHAR(50) NOT NULL COLLATE 'cp1251_general_ci',
	`dir` VARCHAR(50) NOT NULL COLLATE 'cp1251_general_ci',
	`domain` VARCHAR(50) NOT NULL
)
COLLATE='cp1250_general_ci'
ENGINE=MyISAM;


В первую очередь нас интересует колонка `dir`, в ней необходимо прописать путь к директории с сообщениями пользователя, например site.ru/public_html/mail/user1/. Поэтому при создании пользователя нужно убедиться в наличии данной папки и при необходимости ее создать, иначе сообщениям просто негде будет сохранятся. В колонке `user` хранится логин пользователя, т.е. левая часть адреса до знака @. В колонке `domain` правая часть. В колонке `mail` адрес целиком. Из них нам нужны всего 1 или 2 колонке, но для примера я решил указать все возможные варианты.

Теперь создадим файл /etc/postfix/vmailbox.cf и пропишем в нем настройки для запроса и соединение с базой.


user = mail_user
password = password
dbname = base_mail
hosts = localhost
query = select dir from virtual_domains where user='%u'


Специальная переменная %u будет запрашивать лишь левую часть адреса (логин пользователя) без знака @. Такой вариант будет вполне оправдан, если у Вас только один сайт, который будет принимать сообщения. В ином случае нужно будет сделать также и проверку домена


query = select dir from virtual_domains where user='%u' and domain='%d' 


Здесь специальная переменная %d запрашивает правую часть адреса (домен) без знака @. Либо можно и вовсе хранить адрес целиком.


query = select dir from virtual_domains where mal='%s'


Соответственно переменная %s будет запрашивать весь адрес.

В файле /etc/postfix/main.cf изменим значение директивы virtual_mailbox_maps.


virtual_mailbox_maps = proxy:mysql:/etc/postfix/vmailbox.cf


Если сайтов несколько, то инструкцию для каждой можно вынести в отдельный файл и перечислить через запятую


virtual_mailbox_maps = proxy:mysql:/etc/postfix/vmailbox.cf, proxy:mysql:/etc/postfix/vmailbox2.cf


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

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

Убираем директивы virtual_mailbox_base, virtual_mailbox_maps, virtual_uid_maps и virtual_gid_maps. Вместо них нам теперь понадобиться директива virtual_alias_maps. В ней мы будем указывать на конкретного пользователя, которому будем переадресовывать все входящие сообщения для того или иного домена. Создадим файл, где будем прописывать инструкцию для виртуальных пользователей /etc/postfix/valias, а в нем направим всю почту для домена конкретному пользователю, от имени которого и будет работать php-скрипт, а тот уже и будет распределять ее по виртуальным пользователям нашего сайта.


@site.ru user
@site.com user2


Как и в случае с каталогами можно создать базу, для обработки виртуальных доменов, что позволит отбрасывать почту предназначенную для несуществующих пользователей еще на начальном этапе. Я не буду повторять пример для виртуальных пользователей, так как он аналогичен настройкам директивы virtual_mailbox_maps за тем лишь исключением, что вместо колонки `dir`, логичнее указать колонку `alias`, в которой необходимо прописывать уже не путь к директории для хранения сообщений, а имя пользователя.

В файле /etc/aliases пропишем инструкцию на файл-обработчик


user:    "|php5-cgi -c /path/to/php.ini /site.ru/public_html/mail.php"
user2:   "|php5-cgi -c /path/to/php.ini /site.com/public_html/mail.php"


И обновим карту алиансов командой newaliases, а также перезагрузим postfix.

А о том, как mail.php обработает входящий результат я планирую рассказать в следующей статье.

Для защиты от атак и вирусов можно заглянуть в HOW-TO: Настройка Amavisd-new + ClamAV + Dspam.

Postfix
http://www.postfix.org/postconf.5.html
Tags:
Hubs:
-11
Comments 5
Comments Comments 5

Articles