Настройка exim + cyrus-imapd + mysql

Настройка exim + cyrus-imapd + mysql на базе OpenBSD

Автор: fr33man.

Началось все как всегда банально — кто-то постучал в асю. Спрашивали, как настроить cyrus-imap. Я с ним не работал, поэтому честно ответил, что не знаю, но пообещал разобраться(благо времени немного было). Но просто разобраться было не интересно. :) Поэтому я решил настроить почтовую связку на базе OpenBSD. В принципе все довольно просто, но меня заинтересовал cyrus-imap, который, как выяснилось, хранит всю почту в своей собственной базе(db). После гугления этого вопроса я наткнулся на много различных обсуждений, в которых часто говорилось, что cyrus-imap всех рвет по скорости. Я немного подумал и решил, что нужно его настроить, а потом потестировать. )) Здесь описан процесс его настройки на чистой системе OpenBSD-4.2.
Так же хочется отдельно сказать, что большинство конфигов(exim и postfixadmin) я взял из статьи Лиса(lissyara) про связку exim + courer-imap.
Итак приступим.

Ставим mysql-сервер и mysql-клиент:

# export PKG_PATH="ftp://ftp.openbsd.org/pub/OpenBSD/4.2/packages/i386/"
# pkg_add mysql-server
mysql-client-5.0.45: complete
p5-DBD-mysql-3.0008:p5-Net-Daemon-0.39: complete
p5-DBD-mysql-3.0008:p5-PlRPC-0.2018p0: complete
p5-DBD-mysql-3.0008:p5-DBI-1.53: complete
p5-DBD-mysql-3.0008: complete
mysql-server-5.0.45: complete
--- mysql-server-5.0.45 -------------------
You can find detailed instructions on how to install a database
in /usr/local/share/doc/mysql/README.OpenBSD.
#

Установка mysql завершена. Давайте немного его настроим. Для начала создадим БД:

# /usr/local/bin/mysql_install_db
Installing MySQL system tables...
OK
Filling help tables...
OK
PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:
/usr/local/bin/mysqladmin -u root password 'new-password'
/usr/local/bin/mysqladmin -u root -h openbsd.my.domain password 'new-password'
See the manual for more instructions.
Please report any problems with the /usr/local/bin/mysqlbug script!

The latest information about MySQL is available on the web at
http://www.mysql.com
Support MySQL by buying support/licenses at http://shop.mysql.com
#

Теперь создадим свой login class для Mysql'а. Добавим в /etc/login.conf такие строки:

mysql:\
:openfiles-cur=1024:\
:openfiles-max=2048:\
:tc=daemon:

и пересоздадим бд login.conf:

# cap_mkdb /etc/login.conf

Хорошо. Теперь добавим mysql в автозапуск:

# cat >> /etc/rc.local
if [ -x /usr/local/bin/mysqld_safe ] ; then
su -c mysql root -c '/usr/local/bin/mysqld_safe >/dev/null 2>&1 &'
echo -n ' mysql'
fi

Запускаем:

# su -c mysql root -c '/usr/local/bin/mysqld_safe >/dev/null 2>&1 &'
# ps ax | grep sql
19337 p0 I 0:00.03 /bin/sh /usr/local/bin/mysqld_safe
29798 p0 I 0:00.74 /usr/local/libexec/mysqld --basedir
=/usr/local --datadir=/var/mysql --user=_mysql --pid-file=
/var/mysql/openbsd.my.domain.pid --po
4427 p0 R+ 0:00.01 grep sql
#

Как видите — все работает.
Удаляем из mysql левые БД.

# mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.45-log OpenBSD port: mysql-server-5.0.45

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| test |
+--------------------+
3 rows in set (0.00 sec)

mysql> drop database test;
Query OK, 0 rows affected (0.00 sec)

mysql> quit
bye
#

Отлично. Так как юзать мы будем postfixadmin, то я вкратце напишу, как настроить apache. Перед установкой php нужно установить xbase — Там есть необходимые библиотеки. Монтируем сидюк с Openbsd и делаем такую штуку:

# cd /
# mount -t cd9660 /dev/cd0a /mnt
# tar xzvphf /mnt/4.2/i386/xbase42.tgz

Усе — теперь ставим php5:

# pkg_add php5-core
libiconv-1.9.2p3: complete
gettext-0.14.6p0: complete
libxml-2.6.29: complete
php5-core-5.2.3: complete
--- php5-core-5.2.3 -------------------
To finish the install, enable the php5 module with:
/usr/local/sbin/phpxs -s

To enable parsing of PHP scripts, add the following to
/var/www/conf/httpd.conf:

AddType application/x-httpd-php .php

Copy the config file below into /var/www/conf/php.ini
/usr/local/share/examples/php5/php.ini-recommended

Don't forget that the default OpenBSD httpd is chrooted
into /var/www by default, so you may need to create support
directories such as /var/www/tmp for PHP to work correctly.
#

И ставим расширение php5 — mysql:

# pkg_add php5-mysql
php5-mysql-5.2.3: complete
--- php5-mysql-5.2.3 -------------------
Enable this module in php.ini using the following command:

/usr/local/sbin/phpxs -a mysql
#

Усе установилось... Теперь добавляем в Httpd.conf строчку для модуля php5:

# /usr/local/sbin/phpxs -s
[activating module `php5' in /var/www/conf/httpd.conf]
cp /usr/local/lib/php/libphp5.so /usr/lib/apache/modules/libphp5.so
chmod 755 /usr/lib/apache/modules/libphp5.so
cp /var/www/conf/httpd.conf /var/www/conf/httpd.conf.bak
cp /var/www/conf/httpd.conf.new /var/www/conf/httpd.conf
rm /var/www/conf/httpd.conf.new

You should copy the sample configuration files from
/usr/local/share/examples/php5 to /var/www/conf/php.ini
#

И включаем модуль mysql:

# cp /usr/local/share/examples/php5/php.ini-dist /var/www/conf/php.ini
# /usr/local/sbin/phpxs -a mysql
Activating extension : mysql
#

Добавляем две строки в /var/www/conf/httpd.conf:

DirectoryIndex index.php index.html
AddType application/x-httpd-php .php

Добавляем httpd в автозапуск:

# cat >> /etc/rc.conf.local
httpd_flags=""

Запускаем apache:

# apachectl start
/usr/sbin/apachectl start: httpd started
# ps ax | grep httpd
17814 ?? Is 0:00.12 httpd: parent [chroot /var/www] (httpd)
16596 ?? I 0:00.02 httpd: child (httpd)
28908 ?? I 0:00.01 httpd: child (httpd)
6870 ?? I 0:00.02 httpd: child (httpd)
19022 ?? I 0:00.03 httpd: child (httpd)
29760 ?? I 0:00.03 httpd: child (httpd)
21614 p0 I+ 0:00.01 grep httpd
#

Вгоняем в Mysql такой dump:

# cd /root
# cat > dump.sql

--
-- БД: `exim`
--
USE mysql;
INSERT INTO `user` (`Host`, `User`, `Password`)
VALUES ('localhost','exim',password('exim'));
INSERT INTO `db` (`Host`, `Db`, `User`, `Select_priv`)
VALUES ('localhost','exim','exim','Y');
FLUSH PRIVILEGES;
GRANT USAGE ON exim.* TO exim@localhost;
GRANT SELECT, INSERT, DELETE, UPDATE ON exim.* TO exim@localhost;
CREATE DATABASE `exim`;
USE `exim`;

-- --------------------------------------------------------

--
-- Структура таблицы `admin`
--

CREATE TABLE `admin` (
`username` varchar(255) NOT NULL default '',
`password` varchar(255) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`username`),
KEY `username` (`username`)
) TYPE=MyISAM COMMENT='Exim and cyrus-imap Admin - Virtual Admins';

-- --------------------------------------------------------

--
-- Структура таблицы `alias`
--

CREATE TABLE `alias` (
`address` varchar(255) NOT NULL default '',
`goto` text NOT NULL,
`domain` varchar(255) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL default '1',
`copy_mail` int(1) NOT NULL default '1',
PRIMARY KEY (`address`),
KEY `address` (`address`)
) TYPE=MyISAM COMMENT='Exim and cyrus-imap Admin - Virtual Aliases';

-- --------------------------------------------------------

--
-- Структура таблицы `domain`
--

CREATE TABLE `domain` (
`domain` varchar(255) NOT NULL default '',
`description` varchar(255) NOT NULL default '',
`aliases` int(10) NOT NULL default '0',
`mailboxes` int(10) NOT NULL default '0',
`maxquota` int(10) NOT NULL default '0',
`transport` varchar(255) default NULL,
`backupmx` tinyint(1) NOT NULL default '0',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`domain`),
KEY `domain` (`domain`)
) TYPE=MyISAM COMMENT='Exim and cyrus-imap Admin - Virtual Domains';

-- --------------------------------------------------------

--
-- Структура таблицы `domain_admins`
--

CREATE TABLE `domain_admins` (
`username` varchar(255) NOT NULL default '',
`domain` varchar(255) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL default '1',
KEY `username` (`username`)
) TYPE=MyISAM COMMENT='Exim and cyrus-imap Admin - Domain Admins';

-- --------------------------------------------------------

--
-- Структура таблицы `log`
--

CREATE TABLE `log` (
`timestamp` datetime NOT NULL default '0000-00-00 00:00:00',
`username` varchar(255) NOT NULL default '',
`domain` varchar(255) NOT NULL default '',
`action` varchar(255) NOT NULL default '',
`data` varchar(255) NOT NULL default '',
KEY `timestamp` (`timestamp`)
) TYPE=MyISAM COMMENT='Exim and cyrus-imap Admin - Log';

-- --------------------------------------------------------

--
-- Структура таблицы `mailbox`
--

CREATE TABLE `mailbox` (
`username` varchar(255) NOT NULL default '',
`password` varchar(255) NOT NULL default '',
`name` varchar(255) NOT NULL default '',
`maildir` varchar(255) NOT NULL default '',
`quota` int(10) NOT NULL default '0',
`domain` varchar(255) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`username`),
KEY `username` (`username`)
) TYPE=MyISAM COMMENT='Exim and cyrus-imap Admin - Virtual Mailboxes';

-- --------------------------------------------------------

--
-- Структура таблицы `vacation`
--

CREATE TABLE `vacation` (
`email` varchar(255) NOT NULL default '',
`subject` varchar(255) NOT NULL default '',
`body` text NOT NULL,
`cache` text NOT NULL,
`domain` varchar(255) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`email`),
KEY `email` (`email`)
) TYPE=MyISAM COMMENT='Exim and cyrus-imap Admin - Virtual Vacation';

# mysql -u root < dump.sql

Ставим postfix-admin:

# cd /var/www/htdocs/
# ftp \
> http://optusnet.dl.sourceforge.net/sourceforge/postfixadmin/postfixadmin...
Trying 211.29.132.142...
Requesting
http://optusnet.dl.sourceforge.net/sourceforge/postfixadmin/postfixadmin...
100% |***************************************| 156 KB 00:04
Successfully retrieved file.
#

Устанавливаем:

# tar zxf postfixadmin-2.1.0.tgz
# mv postfixadmin-2.1.0 mailadmin
# chown -R www:www /var/www/htdocs/mailadmin/

Теперь редактируем конфиг postfixadmin'а:

# cd mailadmin
# cp config.inc.php.sample config.inc.php

Редактируем config.inc.php:

$CONF['database_type'] = 'mysql';
$CONF['database_host'] = '127.0.0.1';
$CONF['database_user'] = 'exim';
$CONF['database_password'] = 'exim';
$CONF['database_name'] = 'exim';
$CONF['database_prefix'] = '';
$CONF['encrypt'] = 'cleartext';
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';
$CONF['smtp_server'] = '127.0.0.1';
$PALANG['charset'] = 'cp1251';

И последний штрих:

# cat config.inc.php | \
> sed 's/change-this-to-your.domain.tld/local.ru/' > \
> tmp && mv tmp config.inc.php

Если будете использовать русский язык, то файл: /var/www/htdocs/mailadmin/templates/admin_menu.tpl — тут после строки содержащий backup воткните 4-е <br>.
Так же не забудьте запаролить админку.

Все. Можете заходить по адресу: http://ваш_серв/mailadmin/admin/.

Осталось осилить exim и cyrus-imap..

Ставим exim:

# cd /usr/ports/mail/exim/

Добавляем в Makefile, перед строкой

FLAVORS=no_exiscan no_x11 mysql postgresql sqlite3 ldap iconv sasl

такую вещь:

EXIM_MAKECAT+= "TRANSPORT_LMTP=yes\n"

Это необходимо для того, что подрубить в exim'е транспорт lmtp. Собираем пакет:

# env FLAVOR="no_x11 mysql" make package

... skipped ...
===> Building package for exim-4.67-no_x11-mysql
Create /usr/ports/packages/i386/all/exim-4.67-no_x11-mysql.tgz
Link to /usr/ports/packages/i386/ftp/exim-4.67-no_x11-mysql.tgz
Link to /usr/ports/packages/i386/cdrom/exim-4.67-no_x11-mysql.tgz
#

Устанавливаем:

# pkg_add /usr/ports/packages/i386/all/exim-4.67-no_x11-mysql.tgz
useradd: Warning: home directory `/var/spool/exim'
doesn't exist, and -m was not specified
exim-4.67-no_x11-mysql: complete
--- exim-4.67-no_x11-mysql -------------------
If you intend replacing sendmail with exim, then don't
forget to modify /etc/mailer.conf accordingly; see
mailwrapper(8).

A perl script may help converting from exim-3.xx config
files and has been installed in
/usr/local/share/examples/exim/convert4r4
you have mail in /var/mail/root
#

Составляем конфиг /etc/exim/configure:

#!/bin/sh
# Файл конфигурации: /usr/local/etc/exim/configure

# моя конфига экзма. Будь проклят тот день,
# когда мне пришла в голову мысль подписать
# русские поясния ко всем пунктам! :) Хоть и
# делал я это в первую очередь для себя -
# чтоб лучше понять его, но работа эта оказалась
# слишком масштабная и неблагодарная...

# Имя хоста. Используется в EHLO.
# Фигурирует в других пунктах, если они не заданы -
# типа qualify_domain и прочих..
# Если тут ничё не установлено (строка закомметрована)
# то используется то, что вернёт функция uname()
primary_hostname = local.ru

# Вводим данные для подключения к MySQL серверу.
# словечко `hide`, вначале, означает, что при
# вызове проверки конфига командой
# exim -bV config_file эти данные не будут отображаться.
# Если без него - то будут показаны... Формат записи:
# хост/имя_бд/пользователь/пароль
hide mysql_servers = localhost/exim/exim/exim

 

# Делаем список локальных доменов. Далее этот
# список будет фигурировать в виде +local_domains
# В данном случае домены выбираются из БД MySQL. Также
# можно их просто перечислить через двоеточие. Есть интересная
# возможность, можно указать юзер@[хост] - lissyara@[222.222.4.5]
domainlist local_domains = ${lookup mysql{SELECT `domain` \
FROM `domain` WHERE \
`domain`='${domain}' AND \
`active`='1'}}

# делаем список доменов с которых разрешены релеи.
# Далее этот список будет в виде +relay_to_domains
# Можно использовать символы подстановки, типа:
# .... = *.my.domen.su : !spam.my.domen.su : first.su
# тогда пропускается всё, что похоже на *.my.domen.su, но
# от spam.my.domen.su релеится почта не будет.
domainlist relay_to_domains = ${lookup mysql{SELECT `domain` \
FROM `domain` WHERE \
`domain`='${domain}' AND \
`active`='1'}}

# Составляем список хостов с которых разрешён неавторизованый
# релей. Обычно в нём находятся локальные сети, и локалхост...
# ЛокалХост в двух видах был внесён сознательно - пару раз
# сталкивался с кривым файлом /etc/hosts - результатом было
# непонимание `localhost` но пониманием 127.0.0.1/8
hostlist relay_from_hosts = localhost:127.0.0.0/8:192.168.0.0/16

# Вводим названия acl`ов для проверки почты. (В общем-то, это
# необязательно, если вы делаете открытый релей, или хотите
# принимать вообще всю почту с любого хоста для любых
# получателей... Тока потом не жалуйтесь что у Вас спам
# и провайдер выкатывает немеряный счёт :))
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data

# Имя домена добавляемое для локальных отправителей (реальных
# юзеров системы) т.е. почта отправляемая от root, будет от
# root@домен_указанный_здесь. Если пункт незадан, то используется
# имя хоста из `primary_hostname`. Логичней было бы написать здесь
# local.ru, но мне удобней иначе:
qualify_domain = local.ru

# Имя хоста для ситуации, обратной предыдущей, - это имя домена
# добавляемое к почте для системных юзеров, ну и вообще для почты
# пришедшей на адрес типа `root`, `lissyara`, & etc... Если этот
# пункт незадан то используется значение полученное из
# предыдущего пункта - `qualify_domain`
qualify_recipient = local.ru

# А это как раз кусок вышеописанного анахронизма - про почту в
# виде user@[222.222.222.222] - принимать её или нет. По дефолту
# (когда строка закомментирована) значение - false. Если захотите
# поставить true то надо будет добавить в список доменов
# комбинацию @[] - она означает `все локальные адреса`
allow_domain_literals = false

# Пользователь от которого работает exim
exim_user = _exim

# группа в кторой работает exim
exim_group = _exim

# запрещаем работу доставки под юзером root - в целях безопасности
never_users = root

# Тоже анахронизм (на самом деле, не такой уж анахронизм, но все давно
# забили на ident и закрыли файрволлом tcp:113...) Это проверка - Ваш
# хост спрашивает у удалённого, с которого было подключение, а кто
# собстно ко мне подключился на такой-то порт? Если на удалённом хосте
# работает identd - он может ответить (а может и не ответить - как
# настроить), скажет UID пользователя от которого установлено
# соединение, тип ОС, и имя пользователя. Теперь, понимаете, почему
# у всех оно зарублено и файрволлами позакрыто? :) Это же палево :)
# Тока на мой взгляд, если на сервере всё настроено правильно -
# то вовсе это и не страшно.
# Короче - если хостс поставить * то будет проверять все. Таймаут -
# если поставить 0 то не будет ждать ответа ни от кого. По
# вышеописанным причинам - отключаем
#rfc1413_hosts = *
rfc1413_query_timeout = 0s

# Если сообщение было недоставлено, то генерится соощение
# об ошибке. Если сообщение об ошибке не удалось доставить
# то оно замораживается на указанный в этом пункте срок,
# после чего снова попытка доставить его. При очередной
# неудаче - сообщение удаляется.
ignore_bounce_errors_after = 45m

# Замороженные сообщения, находящиеся в очереди, дольше
# указанного времени удаляются и генерится сообщение
# об ошибке (при условии, что это не было недоставленное
# сообщение об ошибке :))
timeout_frozen_after = 15d

# собсно на этом штатный конфиг кончился, но
# меня-то это не устраивает... Поэтому пошли пункты,
# почёрпнутые из других источников.

# список адресов, через запятую, на которые засылаются
# сообщения о замороженных сообщениях (о замороженых
# уведомлениях о заморозке, сообщения не генерятся. - я
# надеюсь эта строка понятна :))
freeze_tell = admin@local.ru

# Список хостов, почта от которых принимается, несмотря
# на ошибки в HELO/EHLO
helo_accept_junk_hosts = 192.168.0.0/16

# Через какое время повторять попытку доставки
# замороженного сообщения
auto_thaw = 1h

# Приветствие сервера
smtp_banner = "$primary_hostname, ESMTP EXIM $version_number"

# Максимальное число одновременных подключений по
# SMTP. Рассчитывать надо исходя из нагрузки на сервер
smtp_accept_max = 50

# максимальное число сообщений принимаемое за одно соединение
# от удалённого сервера (или пользователя). C числом 25
# я имел проблемы тока один раз - когда у меня три дня лежал
# инет и после его подъёма попёрли мессаги. Но у меня не так
# много почты - всего 30 пользователей.
smtp_accept_max_per_connection = 25

# чё-то про логи и борьбу с флудом - я так понимаю -
# максимальное число сообщений записываемых в логи
smtp_connect_backlog = 30

# максимальное число коннектов с одного хоста
smtp_accept_max_per_host = 20

# Ход ладьёй - для увеличения производительности,
# директория `spool` внутри, разбивается на
# директории - это ускоряет обработку
split_spool_directory = true

# Если у сообщения много адресатов на удалённых хостах,
# то запускатеся до указанного числа максимально число
# параллельных процессов доставки
remote_max_parallel = 15

# при генерации сообщения об ошибке прикладывать
# не всё сообщение, а кусок (от начала) указанного
# размера (иногда полезно и целиком - в таком случае
# просто закомментируйте эту строку)
return_size_limit = 70k

# размер сообщения. У меня стоит относительно большой
# размер (`относительно` - потому, что на большинстве
# хостов оно ограничено 2-5-10мб, либо стоит анлим.)
message_size_limit = 24M

# разрешаем неположенные символы в HELO (столкнулся
# с этим случайно - имя фирмы состояло из двух слов
# и какой-то раздолбай домен обозвал my_firme_name
# прям с подчёркиваниями... Виндовые клиенты при
# соединении радостно рапортовали о себе
# `vasya.my_firme_name` ну а экзим их футболил :))
helo_allow_chars = _

# Принудительная синхронизация. Если отправитель
# торопится подавать команды, не дождавшись ответа,
# то он посылается далеко и надолго :) Немного,
# спам режется.
smtp_enforce_sync = false

# Выбираем, что мы будем логировать
# + - писать в логи,
# - - Не писать в логи.
# +all_parents - все входящие?
# +connection_reject - разорваные соединения
# +incoming_interface - интерфейс (реально - IP)
# +lost_incoming_connections - потеряные входящие
# соединения
# +received_sender - отправитель
# +received_recipients - получатель
# +smtp_confirmation - подтверждения SMTP?
# +smtp_syntax_error - ошибки синтаксиса SMTP
# +smtp_protocol_error - ошибки протокола SMTP
# -queue_run - работа очереди (замороженные мессаги)
log_selector = \
+all_parents \
+connection_reject \
+incoming_interface \
+lost_incoming_connection \
+received_sender \
+received_recipients \
+smtp_confirmation \
+smtp_syntax_error \
+smtp_protocol_error \
-queue_run

# Убираем собственную временную метку exim`a из логов, её ставит
# сам syslogd - нефига дублировать
syslog_timestamp = no

begin acl

# Эти правила срабатывают для каждого получателя
acl_check_rcpt:

# принимать сообщения которые пришли с локалхоста,
# не по TCP/IP
accept hosts = :
accept hosts = localhost : 127.0.0.1

# Запрещаем письма содержащие в локальной части
# символы @; %; !; /; |. Учтите, если у вас было
# `percent_hack_domains` то % надо убрать.
# Проверяются локальные домены
deny message = "Unknown symbols in address"
domains = +local_domains
local_parts = ^[.] : ^.*[@%!/|]

# Проверяем недопустимые символы для
# нелокальных получателей:
deny message = "Unknown symbols in address"
domains = !+local_domains
local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./

# Принимаем почту для постмастеров локальных доменов без
# проверки отправителя (я закомментировал, т.к. это -
# основной источник спама с мой ящик).

accept local_parts = postmaster
domains = +local_domains

# Запрещщаем, если невозможно проверить отправителя
# (отсутствует в списке локальных пользователей)
# У себя я это закоментил, по причине, что некоторые
# железяки (принтеры, & etc) и программы (Касперский, DrWEB)
# умеют слать почту, в случае проблем но не умеют ставить
# нужного отправителя. Такие письма эта проверка не пускает.
# require verify = sender

# Запрещщаем тех, кто не обменивается приветственными
# сообщениями (HELO/EHLO)
deny message = "You must send HELO/EHLO"
condition = ${if eq{$sender_helo_name}{}{yes}{no}}

# Принимаем сообщения от тех, кто аутентифицировался:
# Вообще, большинство конфигов в рунете - это один и тот же
# конфиг написанный Ginger, в котором этот пункт расположен
# внизу. Но при таком расположении рубятся клиенты с adsl,
# ppp, и прочие зарезанные на последующих проверках. Но это
# жа неправильно! Этом мои пользователи из дома! Потому
# я это правило расположил до проверок.
accept authenticated = *

# Рубаем нах, тех, кто подставляет свой IP в HELO
deny message = "Dont enter my ip in helo"
hosts = *:!+relay_from_hosts
condition = ${if eq{$sender_helo_name}\
{$sender_host_address}{true}{false}}

# Рубаем тех, кто в HELO пихает мой IP (2500 за месяц!)
deny condition = ${if eq{$sender_helo_name}\
{$interface_address}{yes}{no}}
hosts = !127.0.0.1 : !localhost : *
message = "Its my ip address. Go away"

# Рубаем тех, кто в HELO пихает только цифры
# (не бывает хостов ТОЛЬКО из цифр)
deny condition = ${if match{$sender_helo_name}\
{\N^\d+$\N}{yes}{no}}
hosts = !127.0.0.1:!localhost:*
message = "hmm... I dont understand your helo"

# Рубаем хосты типа *adsl*; *dialup*; *pool*;....
# Нормальные люди с таких не пишут. Если будут
# проблемы - уберёте проблемный пункт (у меня клиенты
# имеют запись типа asdl-1233.zone.su - я ADSL убрал...)
deny message = "I dont like your host"
condition = ${if match{$sender_host_name} \
{adsl|dialup|pool|peer|dhcp} \
{yes}{no}}

# Задержка. (это такой метод борьбы со спамом,
# основанный на принципе его рассылки) На этом рубается
# почти весь спам. Единственно - метод неприменим на
# реально загруженных MTA - т.к. в результате ему
# приходится держать много открытых соединений.
# но на офисе в сотню-две человек - шикарный метод.
#
# более сложный вариант, смотрите в статье по exim и
# курьер имап. Т.к. там метод боле умный (просто правил
# больше :), то можно и на более загруженные сервера ставить)
warn
# ставим дефолтовую задержку в 20 секунд
set acl_m0 = 20s
warn
# ставим задержку в 0 секунд своим хостам и
# дружественным сетям (соседняя контора :))
hosts = +relay_from_hosts : 213.234.195.226/28
set acl_m0 = 0s
warn
# пишем в логи задержку (если оно вам надо)
logwrite = Delay $acl_m0 for $sender_host_name \
[$sender_host_address] with HELO=$sender_helo_name. Mail \
from $sender_address to $local_part@$domain.
delay = $acl_m0

 

 

 

# Проверка получателя в локальных доменах.
# Если не проходит, то проверяется следующий ACL,
# и если непрошёл и там - deny
accept domains = +local_domains
endpass
message = "I dont know this user"
verify = recipient

# Проверяем получателя в релейных доменах
# Опять-таки если не проходит -> следующий ACL,
# и если непрошёл и там - deny
accept domains = +relay_to_domains
endpass
message = "I dont know route to this host"
verify = recipient

# Разрешаем почту от доменов в списке relay_from_hosts
accept hosts = +relay_from_hosts

# Если неподошло ни одно правило - чувак явно ищет
# открытый релей. Пшёл прочь. :)
deny message = "Its not openrelay ))"

# Тут идут ACL проверяющие содержимое (тело) письма.
# Без них будут пропускаться все сообщения.

acl_check_data:

accept

 

# чё делаем с почтой
begin routers

# Поиск маршрута к хосту в DNS. Если маршрут не найден в DNS -
# то это `унроутабле аддресс`. Не проверяются локальные
# домены, 0.0.0.0 и 127.0.0.0/8
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
no_more

system_aliases:
driver = redirect
allow_fail
allow_defer
data = ${lookup mysql{SELECT `goto` FROM `alias` WHERE \
`address`='${quote_mysql:$local_part@$domain}' OR \
`address`='${quote_mysql:@$domain}'}}

mysqluser:
driver = accept
condition = ${if eq{}{${lookup mysql{SELECT `maildir` FROM `mailbox` \
WHERE `username`='${quote_mysql:$local_part@$domain}'}}}{no}{yes}}
transport = cyrus_delivery

# начинаются транспорты - как доставляем почту
begin transports

# Доставка на удалённые хосты - по SMTP
remote_smtp:
driver = smtp

# Транспорт для доставки почты локальным пользователям.
cyrus_delivery:
driver = lmtp
socket = /var/imap/socket/lmtp
batch_max = 100
user = _cyrus

address_file:
driver = appendfile
delivery_date_add
envelope_to_add
return_path_add

# Имя программы
address_pipe:
driver = pipe
return_output

# Транспорт для автоответов
address_reply:
driver = autoreply

 

# Начинаются повторы недоставленных писем.
begin retry

# Этот кусок я не трогал. Думаю разработчики лучше знают,
# какие тут должны быть цифирьки. Если же вы это знаете
# лучше их - меняйте. Хотя... А какого, если Вы такой
# умный, читаете этот мануал? Может ну, их, цифирьки, а? :)
# Address or Domain Error Retries
# ----------------- ----- -------
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h

# преобразование адресов. У меня такого нету.
begin rewrite

# Секция авторизации при отправке писем. Ввиду того,
# что почтовых клиентов много, и все всё делают
# по-своему, то и механизмов авторизации три...
begin authenticators

# А вот по какому методу авторизуется оутглюк - я уже и
# не помню... Хотя в своё время долго ковырялся,
# пока настроил... Толь plain, толь login...
auth_plain:
driver = plaintext
public_name = PLAIN
server_condition = ${lookup mysql{SELECT `username` FROM \
`mailbox` WHERE `username` = \
'${quote_mysql:$1}' AND `password` = \
'${quote_mysql:$2}'}{yes}{no}}
server_prompts = :
server_set_id = $2

# Вроде по этому оутглюк, а по предыдущему нетскейп.
auth_login:
driver = plaintext
public_name = LOGIN
server_condition = ${lookup mysql{SELECT `username` FROM \
`mailbox` WHERE `username` = \
'${quote_mysql:$1}' AND `password` = \
'${quote_mysql:$2}'}{yes}{no}}
server_prompts = Username:: : Password::
server_set_id = $1

# А так авторизуется "Летучая Мышь" - TheBat!
auth_cram_md5:
driver = cram_md5
public_name = CRAM-MD5
server_secret = ${lookup mysql{SELECT `password` FROM \
`mailbox` WHERE `username` \
= '${quote_mysql:$1}'}{$value}fail}
server_set_id = $1

# Фсё. Конфиг кончился. Два дня убил.
# &copy; lissyara 2006-02-25, 01:19

Меняем sendmail на exim:

# cat > /etc/mailer.conf
sendmail /usr/local/bin/exim
send-mail /usr/local/bin/exim
mailq /usr/local/bin/exim -bp
newaliases /usr/local/bin/exim -bi
hoststat /usr/local/bin/exim
purgestat /usr/local/bin/exim
#

Добавляем в /etc/rc.local, для отключения sendmail'а:

# cat >> /etc/rc.conf.local
sendmail_flags="NO"
#

Добавляем exim в автозагрузку(/etc/rc.local):

if [ -x /usr/local/bin/exim ] ; then
/usr/local/bin/exim -bd -q30m >/dev/null 2>&1
echo -n ' exim'
fi

Вырубаем sendmail:

# kill `cat /var/run/sendmail.pid`

Врубить сейчас exim не получится — мы пока не поставили cyrus-imap:
1) У нас нет пользователя _cyrus
2) У нас нет доставщика почты(мы используем cyrus-imap для доставки почты в ящики)

Так что перейдем к настройке cyrus-imap.

Перед тем, как ставить cyrus-imap необходимо установить cyrus-sasl — он потребуется для аутентификации:

# pkg_add cyrus-sasl-2.1.22p1-mysql
cyrus-sasl-2.1.22p1-mysql: complete
#

Для начала нам придется налажить пару патчей, для того, чтобы почтовые ящики пользователей(INBOX) создавались автоматически...

/* ссылки нужно писать одной строкой. Тут просто не влезло. */
# cd /root
# ftp http://email.uoa.gr/download/cyrus/
cyrus-imapd-2.3.8/cyrus-imapd-2.3.8-autocreate-0.10-0.diff
Trying 195.134.100.120...
Requesting http://email.uoa.gr/download/cyrus/
cyrus-imapd-2.3.8/cyrus-imapd-2.3.8-autocreate-0.10-0.diff
100% |**************************************************| 84571 00:00
Successfully retrieved file.
# ftp http://email.uoa.gr/download/cyrus/
cyrus-imapd-2.3.8/cyrus-imapd-2.3.8-autosieve-0.6.0.diff
Trying 195.134.100.120...
Requesting http://email.uoa.gr/download/cyrus/
cyrus-imapd-2.3.8/cyrus-imapd-2.3.8-autosieve-0.6.0.diff
100% |**************************************************| 7906 00:00
Successfully retrieved file.
# ftp http://email.uoa.gr/download/cyrus/
cyrus-imapd-2.3.8/cyrus-imapd-2.3.8-rmquota+deletemailbox-0.2-1.diff
Trying 195.134.100.120...
Requesting http://email.uoa.gr/download/cyrus/
cyrus-imapd-2.3.8/cyrus-imapd-2.3.8-rmquota+deletemailbox-0.2-1.diff
100% |**************************************************| 19775 00:00
Successfully retrieved file.
#

Разархивируем cyrus-imap:

/* На данном шаге система установит все
зависимости для cyrus-imapd... так что придется подождать... )) */
# make extract
===> Checking files for cyrus-imapd-2.3.8
>> cyrus-imapd-2.3.8.tar.gz doesn't seem to exist on this system.
>> Fetch ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/cyrus-imapd-2.3.8.tar.gz.
100% |*******************************************| 2155 KB 00:27
>> Size matches for /usr/ports/distfiles/cyrus-imapd-2.3.8.tar.gz
>> (SHA256) cyrus-imapd-2.3.8.tar.gz: OK
===> cyrus-imapd-2.3.8p0 depends on: cyrus-sasl-* - found
===> cyrus-imapd-2.3.8p0 depends on: db-4.* - not found

... skipped ...

===> Extracting for cyrus-imapd-2.3.8
#

Теперь патчим:

# cd w-cyrus-imapd-2.3.8/cyrus-imapd-2.3.8/
# patch -p1 < /root/cyrus-imapd-2.3.8-autocreate-0.10-0.diff
Hmm... Looks like a unified diff to me...
The text leading up to this was:

... skipped ...

done
# patch -p1 < /root/cyrus-imapd-2.3.8-autosieve-0.6.0.diff
Hmm... Looks like a unified diff to me...
The text leading up to this was:

... skipped ...

done
# patch -p1 < /root/cyrus-imapd-2.3.8-rmquota+deletemailbox-0.2-1.diff
Hmm... Looks like a unified diff to me...
The text leading up to this was:

... skipped ...

done
#

Собираем пакет для cyrus-imapd и устанавливаем его:

# cd /usr/ports/mail/cyrus-imapd/
# make package
===> Patching for cyrus-imapd-2.3.8
===> Configuring for cyrus-imapd-2.3.8

... skipped ...

===> Building package for cyrus-imapd-2.3.8p0
Create /usr/ports/packages/i386/all/cyrus-imapd-2.3.8p0.tgz
Link to /usr/ports/packages/i386/ftp/cyrus-imapd-2.3.8p0.tgz
Link to /usr/ports/packages/i386/cdrom/cyrus-imapd-2.3.8p0.tgz
`/usr/ports/mail/cyrus-imapd/w-cyrus-imapd-2.3.8/fake-i386/.fake_done' is up to date.
===> Building package for cyrus-imapd-perl-2.3.8
Create /usr/ports/packages/i386/all/cyrus-imapd-perl-2.3.8.tgz
Link to /usr/ports/packages/i386/ftp/cyrus-imapd-perl-2.3.8.tgz
Link to /usr/ports/packages/i386/cdrom/cyrus-imapd-perl-2.3.8.tgz
# pkg_add /usr/ports/packages/i386/all/cyrus-imapd-2.3.8p0.tgz
cyrus-imapd-2.3.8p0: complete
--- cyrus-imapd-2.3.8p0 -------------------
Don't forget to edit /etc/services to include missing network services
if needed.
# pkg_add /usr/ports/packages/i386/all/cyrus-imapd-perl-2.3.8.tgz
cyrus-imapd-perl-2.3.8: complete
#

Установилось. ) Теперь составляем конфиг для imap'а:

# cat > /etc/imapd.conf
# Автоматом создавать квоту для пользователя.
# на самом деле нужно только для автоматического
# создания юзерских хомяков
autocreatequota: 10485760
# Создаем почтовые ящики при попытке отправить
# им письмо
createonpost: yes
# Директория с БД и тд.
configdirectory: /var/imap
# Настройки безопасности sasl
sasl_minimum_layer: 0
# Где храним почту
partition-default: /var/spool/imap
# Какие пользователи являются админами
admins: admin
# Директория со скриптами
sievedir: /var/imap/sieve
# sendmail прога
sendmail: /usr/sbin/sendmail
# как проверяем пасс
sasl_pwcheck_method: auxprop
# расположение сокетов
lmtpsocket: /var/imap/socket/lmtp
idlesocket: /var/imap/socket/idle
notifysocket: /var/imap/socket/notify
# сама проверка пароля...
# все параметры очевидны. )
sasl_auxprop_plugin: sql
sasl_sql_engine: mysql
sasl_sql_user: exim
sasl_sql_passwd: exim
sasl_sql_database: exim
sasl_sql_hostnames: 127.0.0.1
sasl_sql_select: SELECT password FROM mailbox WHERE username='%u@%r' AND active='1'
sasl_sql_verbose: yes
sasl_mech_list: PLAIN LOGIN
sasl_password_format: plaintext
# разрешаем не криптованные пароли
allowplaintext: yes
altnamespace: yes
# имя сервера
servername: local.ru
# используем виртуальные домены
virtdomains: userid
# домен по умолчанию
defaultdomain: local.ru
#

Теперь создаем необходимые файлы и папки для работы imap'а.

# /usr/local/share/examples/cyrus-imapd/tools/mkimap
reading configure file /etc/imapd.conf...
i will configure directory /var/imap.
i saw partition /var/spool/imap.
done
configuring /var/imap...
creating /var/spool/imap...
done
#

Добавим cyrus-imap в автозагрузку:

# cat >> /etc/rc.local
if [ -x /usr/local/libexec/cyrus-imapd/master ] ; then
/usr/local/libexec/cyrus-imapd/master \
-C /etc/imapd.conf -M /etc/cyrus.conf -d
echo -n ' cyrus-imap'
fi

Отлично! ) Теперь можно запускать cyrus-imap и exim:

# /usr/local/libexec/cyrus-imapd/master \
> -C /etc/imapd.conf -M /etc/cyrus.conf -d
# ps ax | grep master
29110 ?? Is 0:00.02 /usr/local/libexec/cyrus-imapd/master
-C /etc/imapd.conf -M /etc/cyrus.conf -d
27057 p0 I+ 0:00.01 grep master
# /usr/local/bin/exim -bd -q30m
# ps ax | grep exim
27271 ?? Is 0:00.01 /usr/local/bin/exim -bd -q30m (exim-4.66)
#

Можно проверять!

Заходим в postfixadmin и создаем какой-нить домен. И создаем пользователя двух пользователей: admin@local.ru — будет администратором для cyrus-imapd, прошу обратить внимание, что этот админ не должен получать почту. Его необходимо использовать только для администрирования cyrus-imapd. И второго пользователя: test@local.ru и смотрим логи:

2008-04-03 02:51:49 1JhBo5-0007cT-Ci <= postmaster@local.ru H=(127.0.0.1) [127.0.0.1] I=[127.0.0.1]:25 P=esmtp S=298 from <postmaster@local.ru> for test@local.ru
2008-04-03 02:51:49 1JhBo5-0007cT-Ci => test <test@local.ru> R=mysqluser T=cyrus_delivery
2008-04-03 02:51:49 1JhBo5-0007cT-Ci Completed

Как видите — ящик test успешно был создан, а ящик админа не создался, потому что ему не надо. ))

Теперь можете настраивать свой любимый почтовый клиент(я юзаю thunderbird) на использование нашего сервера.

P.S. По скорости работы cyrus-imap рулит. )
P.S.2 В отличии от courier'а — можно папки создавать в корне, а не во "Входящие". Это радует.
P.S.3 Если Вам нужны логи от cyrus-imap'а, то в /etc/syslogd.conf пропишите следующее:

local6.debug /var/log/imapd.log
auth.debug /var/log/auth.log

И перезапустите syslog:

# kill -HUP `cat /var/run/syslog.pid`

P.S.4 В следующей статье попытаюсь рассказать про такие вкусности, как sieve. )

Смотрите далее по теме "Linux + Линукс + exim + cyrus + imapd + mysql + техническая информация"

Распиновка RJ45 Ethernet 10/100 BaseT (cross over) | автор: Mascher

Давно у меня валяется сия картинка, когда у меня спрашивают как сделать патчкорд, я обычно даю эту картинку, и красиво и понятно :)     Этот тип патчкорда используется для...

Как я искал драйвер для геймпада Xbox 360 для PC - Windows | автор: Mascher

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

Восстановление жесткого диска Seagate Barracuda ES.2 ST500320NS | автор: Mascher

Случилось так что у моего знакомого сломался жесткий диск Seagate Barracuda ES.2 модель ST500320NS, это линейка жестких дисков повышенной надежности от фирмы Seagate... Как оказалось позже,...