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

Основная идея заключается в следующем:

  • Почтовый адрес пользователя получается из его логина путём прибавление имени вашего домена. То есть если у вас домен domain.com, то у пользователя vasya будет адрес vasya@domain.com. При этом надо учесть, что в почтовых адресах могут использоваться только буквы латинского алфавита и символы «_-.», и при этом адреса нечувствительны к регистру. Чаще всего все эти ограничения прекрасно ложатся на существующие базы пользователей, но могут быть и исключения. Во многих движках у пользователя просто есть возможность сменить отображаемое имя, и при этом почти всегда имя нечувствительно к регистру. Это позволяет без проблем создавать почтовые адреса по описанной схеме пользователям, в них нуждающимся.
  • Почтовый адрес в вашем домене, выданный пользователю, будет всего лишь редиректом на основной почтовый ящик из профиля. То есть вся почта, приходящая на vasya@domain.com, будет перенаправляться на почтовый адрес пользователя vasya, указанный у него в профиле. Все современные движки, разрешающие регистрацию, требуют обязательного указания почтового адреса, так что с перенаправлением проблем не возникнет.
  • Поскольку вся почта пользователя перенаправляется на его основной ящик, то на вашем сервере ничего храниться не будет. Соответственно никакого IMAP, POP или веб-доступа к почте вам организовывать не придётся.
  • Доступа на отправку через ваш SMTP сервер у пользователя также быть не должно, поскольку он при такой схеме не нужен, а его организация требует дополнительных усилий и создаёт дополнительную проблему обеспечения безопасности. Для отправки от имени своего ящика в вашем домене пользователь может воспользоваться SMTP сервером своего провайдера или же подключить дополнительный адрес отправки к своему основному аккаунту почты (это позволяют делать все нормальные почтовые службы. Например Gmail и Yandex).

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

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

Практическая сторона вопроса

В качестве почтового сервера имеет смысл использовать Postfix, как один из самых надёжных и при этом нетребовательных к ресурсам. Postfix есть в стандартных репозиториях Ubuntu, соответственно его можно установить с помощью любого пакетного менеджера. Например, командой

sudo apt-get install postfix

Когда у вас спросят, какой тип настройки использовать — выберите интернет-сайт и введите какие-нибудь данные в ответ на дальнейшие вопросы от балды, чуть ниже будет готовый конфиг со всеми необходимыми настройками.

После установки необходимо настроить Postfix так, чтобы при запросе доставки письма на адрес vasya@domain.com, Postfix смотрел бы в вашу БД, узнавал бы, есть ли там искомый пользователь и активирован ли для него почтовый адрес, и, если всё в порядке, — на какой адрес перенаправить письмо. После чего Postifx должен принять письмо и перенаправить его на основной почтовый адрес указанного пользователя.

Эту задачу можно решить встроенными средствами Postfix, однако заставлять почтовый сервер для каждого нового письма отправлять запрос в основную базу данных — это далеко не лучшая идея, поскольку это создаст лишнюю нагрузку на вашу БД пользователей, благо спама сейчас в интернете гуляет очень и очень много. Гораздо лучше пару раз в сутки выгружать нужную информацию из вашей основной БД в Postfix, благо вся эта информация — это таблица из двух полей: имя пользователя и его основной адрес почты.

Для перенаправления почты в Postfix служат различные alias_maps. Поскольку описываемая система никак не привязана к системным пользователям сервера, то будем использовать механизм виртуальных доменов и параметр virtual_alias_maps для перенаправления почты на основные адреса пользователей. В этом параметре как раз надо указать таблицу соответствия адреса пользователя адресу, на который нужно перенаправить корреспонденцию. Эта таблица будет создаваться на основании содержимого вашей основной БД пользователей специальным скриптом, о котором чуть ниже.

Пока же давайте окончательно разберёмся с необходимым опциями Postfix. Вся настройка Postfix осуществляется путём редактирования конфигурационного файла /etc/postfix/main.cf. Итак, для решения поставленной задачи будет использоваться механизм виртуальных доменов, поскольку реальным пользователям почты на сервере не от куда взяться. Поэтому необходимо полностью отключить локальную доставку. Кроме того, пользователи не должны иметь никакого доступа к вашему SMTP серверу, поэтому стоит отключить авторизацию и SSL шифрование.

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

# See /usr/share/postfix/main.cf.dist for a commented, more complete version
 
########################################################
## Основные параметры
 
smtpd_banner = $myhostname ESMTP server
biff = no
 
# Максимальный размер письма. По умолчанию всего 10Mb
message_size_limit = 204800000
 
# Основные параметры хоста
myhostname = mail.yourdomain.com
myorigin = $mydomain
mynetworks =
 127.0.0.0/8
 
mailbox_size_limit = 0
virtual_mailbox_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4 
append_dot_mydomain = no
readme_directory = no
 
##########################################################
## Настройки адресов и доставки
 
# Используем только виртуальных пользователей, поэтому всё локальное отключаем
mydestination =
local_recipient_maps =
relay_domains =
relay_recipient_maps =
transport_maps =
 
# Настройки виртуальных ящиков
virtual_mailbox_domains =
 $mydomain
# Локальных пользователей нет (если нужны - нужно ставить Dovecot)
# Однако карта обязательно должна существовать (пусть и пустая)
virtual_mailbox_maps =
 hash:/etc/postfix/mailboxes/local-mailboxes
# Собственно карты перенаправлений
virtual_alias_maps =
 hash:/etc/postfix/mailboxes/db-aliases
 hash:/etc/postfix/mailboxes/local-aliases
# Параметры локальной доставки. Если она нужна, то надо ставить Dovecot
virtual_mailbox_base = /var/mail
virtual_uid_maps = static:900
virtual_gid_maps = static:900
 
###########################################################
## Авторизация и шифрование - отключены
 
# SASL авторизация отключена
smtpd_sasl_auth_enable = no
 
# TLS отключён
smtpd_use_tls = no
 
###########################################################
## Ограничения и запреты
 
# Запретить ETRN команду
smtpd_etrn_restrictions = reject
 
# Запретить VRFY команду
disable_vrfy_command = yes
 
# Требовать наличие EHLO (HELO) команды
smtpd_helo_required = yes
 
# Всегда отклонять письма для всех неизвестных ящиков
smtpd_reject_unlisted_recipient = yes
 
# Ограничения на клиента - принимаем только если есть PTR (не жёсткий запрет)
smtpd_client_restrictions =
 permit_mynetworks
 reject_unknown_reverse_client_hostname
 permit
 
# Ограничения на HELO. Отклоняем письма от всех хостов, которые даже представиться не могут
smtpd_helo_restrictions =
 permit_mynetworks
 reject_invalid_helo_hostname
 reject_non_fqdn_helo_hostname
 reject_unknown_helo_hostname
 permit
 
# Ограничения на MAIL FROM. Отклоняем все письма, отправитель которых предоставил невалидный адрес
smtpd_sender_restrictions =
 reject_non_fqdn_sender
 reject_unknown_sender_domain
 permit
 
# Ограничения на RCPT TO. Принимаем только для известных нам адресов
smtpd_recipient_restrictions =
 reject_non_fqdn_recipient
 reject_unlisted_recipient
 permit_mynetworks
 reject_unauth_destination
 permit
 
# Ограничения на данные. Не принимаем в случае некорректной передачи
smtpd_data_restrictions =
 reject_unauth_pipelining

Подробней про настройку и различные опции Postfix можно почитать в соответствующей статье или интернете, для нашей же задачи важны три момента:

  1. Не стоит ставить слишком жёсткие ограничения с целью фильтрации спама. Оставьте эту прерогативу почтовым серверам, которые используют ваши пользователи. Ваша задача — просто переслать почту и отсеять только то, что спамом является 100%. Подробнее про правильную настройку Postfix с целью минимизации потока спама можно почитать в соответствующей статье. Обратите внимание, для нормальной пересылки вам надо не забыть корректно настроить DNS записи для вашего сервера, об этом также можно почитать в той же статье.
  2. Обязательно укажите пустую карту локальных пользователей в параметре virtual_mailbox_maps, иначе Postfix будет принимать почту для всех адресов в вашем домене и выдавать кучу ошибок о невозможности доставки. В приведённом выше примере конфигурации файл карты называется /etc/postfix/mailboxes/local-mailboxes. Это обычный пустой текстовый файл. После его создания необходимо выполнить команду

    sudo postmap /etc/postfix/mailboxes/local-mailboxes

    иначе Postfix не сможет работать с вашим файлом.

  3. Ну и наконец все правила перенаправления задаются в двух файлах, указанных в параметре virtual_alias_maps. Один будет создаваться автоматически скриптом на основании содержимого вашей базы пользователей, а второй нужен для ручного создания дополнительных вспомогательных адресов. После редактирования файла дополнительных адресов не забудьте выполнить для него команду postmap. Подробней про использование псевдонимов для перенаправления почты в Postfix можно почитать, например, в официальной документации.

Теперь, собственно, сам скрипт, который создаёт карту псевдонимов на основе содержимого базы пользователей. Приведённый ниже скрипт написан на Perl и предназначен для работы с БД движка SMF, вам потребуется модифицировать его под вашу БД, изменив способ соединения с БД и запрос на выборку нужных данных:

#!/usr/bin/perl
 
# Скрипт выбирает из SMF пользователей из определённой группы,
# и создаёт на основе выборки карты для postfix. Должен запускаться по
# cron. Предположительно отсюда  /etc/cron.d/postfix-smf-sync
#
# Author: Vadim Nevorotin aka Malamut
 
use 5.010;
use DBI;
 
#############################################################
 
# Настройки базы данных (MySQL)
$MYSQL_host = 'bd.yourdomain.com';
$MYSQL_port = '3306';
$MYSQL_user = 'postfix';
$MYSQL_pass = 'PASSW0RD';
$MYSQL_db = 'my_smf';
 
# Параметры SMF - группа пользователей с доступом к почте и префикс таблиц
$SMF_GID = '15';
$SMF_prefix = 'smf_';
 
# Обслуживаемый домен
$domain = "yourdomain.com";
 
# Файл псевдонимов
$postfix_file = "/etc/postfix/mailboxes/db-aliases";
 
#############################################################
 
$dbh = DBI->connect("DBI:mysql:$MYSQL_db:$MYSQL_host:$MYSQL_port",$MYSQL_user,$MYSQL_pass) or die "Hey guys! We've got a big error here...\n";
 
# Выполняем запрос
my $sth = $dbh->prepare("SELECT memberName, realName, emailAddress
	FROM ${SMF_prefix}members
	WHERE (ID_GROUP = $SMF_GID OR FIND_IN_SET($SMF_GID, additionalGroups))") or die "Hey guys! We've got  big error here!\n";
$sth->execute() or die "Hey guys! We've got a big error here...\n";
 
# Открываем файл псевдонимов для Postfix
open ALIASES, ">$postfix_file" or die "Can't open $postfix_file\n";
 
say ALIASES <<INTRO;
#################################################
# Карта соответствия адресов yourdomain.com основным #
# адресам пользователей.                        #
#                                               #
# Этот файл создаётся автоматически скриптом    #
# /etc/postfix/scripts/postfix-sync.pl      #
# на основе данных из БД SMF. Редактировать     #
# вручную данный файл бесполезно.               #
#################################################
INTRO
 
# Для проверки адреса на корректность:
# разрешённые буквы 
$w = '[a-zA-Z0-9]';
# разрешённые символы-разделители:
$s = '[._\-]';
 
# Анализируем ответ
while (my $row = $sth->fetchrow_hashref()) {
	# Делаем lower case, но нужно это только для красоты
	my $user = lc $row->{realName};
	# Если имя пользователя содержит неразрешённые символы - пропускаем его
	# Разрешены любые буквы, цифры и символы ".", "-" и "_"
	next unless $user =~ /^($w+$s)*$w+$/;
	# Убеждаемся, что пользователь подумал головой
	my $email = lc $row->{emailAddress};
	next if "$user\@$domain" eq $email;
	# Пишем псевдоним в файл
	say ALIASES "$user\@$domain\t$row->{emailAddress}";
}
 
# Закрываем файл псевдонимов и создаём хеш для postfix'а
close ALIASES;
`/usr/sbin/postmap hash:$postfix_file`;

В результате работы скрипта будет создан файл псевдонимов /etc/postfix/mailboxes/db-aliases, в котором будут строчки вида

someuser@yourdomain.com	usermail@anotherdomain.com

По одной строчке для каждого пользователя, состоящего в группе пользователей почты. Скрипт содержит проверку на дурака: во-первых, никакие пользователи с спецсимволами в имени не будут пропущены в файл псевдонимов Postfix. Ну и во-вторых пользователь не сможет указать в качестве основного адреса в своём профиле адрес на вашем же сайте, дабы не получился цикл почтовый системы.

Всё, что осталось сделать, это добавить запуск скрипта в планировщик, например, создать задание cron. Для этого создайте файл /etc/cron.d/postfix-sync с примерно следующим содержанием:

# Synchronize Postfix with BD
18 04 * * *      root    /etc/postfix/scripts/postfix-sync.pl

Как видно, в данном примере скрипт запускает каждый день в 04:18.

Важные замечания

Обязательно необходимо предусмотреть способ включения и отключения почтового адреса через профиль пользователя на вашем сайте. Мало того, почтовый адрес должен активировать только при ручном запросе самого пользователя. Иначе предложенную систему можно будет неплохо использовать для рассылки спама, что вряд ли понравится вашим посетителям.

Кроме того, не забудьте корректно настроить сопутствующие службы, в частности - DNS. Подробней про правильную интеграцию вашего сервера в общую почтовую систему интернета можно почитать в соответствующей статье:

Дополнительные возможности

Кроме почты примерно по такой же схеме можно подключить вашим пользователям аккаунты Jabber, этому посвящена отдельная статья:

Ссылки