В прошлый раз я рассматривал пример создания подобного сервиса на примере 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 <IP>

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

<IP> 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 обработает входящий результат я планирую рассказать в следующей статье.

Для защиты от атак и вирусов можно заглянуть в http://help.ubuntu.ru/wiki/amavis_clamav_dspam_ubuntu_10_04.

http://wiki.dieg.info/postfix
http://www.postfix.org/postconf.5.html

Комментарии (5)


  1. bioskiller
    06.07.2015 03:50
    +4

    Зачем это здесь?
    Учитывая более полные инструкции уже опубликованные на Хабре ранее?


  1. Lockal
    06.07.2015 09:08

    С таким конфигом без DKIM/SPF в большинстве почтовых сервисов письма будут отправляться прямиком в спам.


    1. mmotor Автор
      06.07.2015 13:24

      О каком спаме может идти речь, если описываются лишь директивы для приема почты.


  1. elcamlost
    06.07.2015 09:44

    Статья вызывает недоверие уже с первого абзаца. Sendmail прекрасно работает и с SSL/TLS (https://www.sendmail.com/sm/open_source/docs/m4/starttls.html) и с maildir (хотя строго говоря, работа с mbox, maildir или любым другим форматом почтового ящика это задача MDA, а не MTA. См, например, www.vniigim.ru/~andr/openbsd/docs/steps/procmail.html).


  1. la0
    06.07.2015 10:10

    Вот бы кто написал, как стоить что-то такое без зависимости в виде mysql (к примеру, sqlite)