Exim4 + Dovecot2 + MySql + Roundcube
Установка Exim
- apt-get install exim4 exim4-daemon-heavy
- dpkg-reconfigure exim4-config
- internet site; mail is sent and received directly using SMTP
- System mail name: server name
- IP-addresses to listen on for incoming SMTP connections: 127.0.0.1 ; ::1; [IP сервера]
- Other destinations for which mail is accepted: server name
- Keep number of DNS-queries minimal (Dial-on-Demand)? No
- Delivery method for local mail: mbox format in /var/mail/
- Split configuration into small files? No
Конфигурация
primary_hostname = mail.ztc #hide mysql_servers = localhost/mail/admin/my4sitecms hide mysql_servers = 127.0.0.1/postfix/postfix/postfixadmin domainlist local_domains = ${lookup mysql{SELECT `domain` \ FROM `domain` WHERE \ `domain`='${domain}' AND \ `active`='1'}} domainlist relay_to_domains = ${lookup mysql{SELECT `domain` \ FROM `domain` WHERE \ `domain`='${domain}' AND \ `active`='1'}} #domainlist local_domains = *.mail.ztc #domainlist relay_to_domains = *.mail.ztc hostlist relay_from_hosts = localhost:127.0.0.0/8:192.168.1.0/24 #av_scanner = clamd:/var/lib/clamav/clamd-socket acl_smtp_rcpt = acl_check_rcpt #acl_smtp_data = acl_check_virus qualify_domain = mail.ztc qualify_recipient = mail.ztc allow_domain_literals = false # Пользователь от которого работает exim exim_user = mail # группа в кторой работает exim exim_group = mail # запрещаем работу доставки под юзером root - в целях безопасности never_users = root rfc1413_query_timeout = 0s sender_unqualified_hosts = +relay_from_hosts recipient_unqualified_hosts = +relay_from_hosts ignore_bounce_errors_after = 45m timeout_frozen_after = 15d helo_accept_junk_hosts = 192.168.100.0/24 auto_thaw = 1h smtp_banner = "$primary_hostname, ESMTP EXIM $version_number" smtp_accept_max = 50 smtp_accept_max_per_connection = 100 smtp_connect_backlog = 30 smtp_accept_max_per_host = 20 split_spool_directory = true remote_max_parallel = 15 return_size_limit = 70k message_size_limit = 64M helo_allow_chars = _ smtp_enforce_sync = true 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 syslog_timestamp = no #hide mysql_servers = 127.0.0.1/mail/admin/my4sitecms # # ACL # ### конфигурация ACL для входящей почты begin acl acl_check_rcpt: # принимать сообщения которые пришли с локалхоста, # не по TCP/IP accept hosts = : # Запрещаем письма содержащие в локальной части # символы @; %; !; /; |. Учтите, если у вас было # `percent_hack_domains` то % надо убрать. # Проверяются локальные домены deny message = "incorrect symbol in address" domains = +local_domains local_parts = ^[.] : ^.*[@%!/|] # Проверяем недопустимые символы для # нелокальных получателей: deny message = "incorrect symbol in address" domains = !+local_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ # Принимаем почту для постмастеров локальных доменов без # проверки отправителя (я закомментировал, т.к. это - # основной источник спама с мой ящик). accept local_parts = postmaster domains = +local_domains # Запрещщаем тех, кто не обменивается приветственными # сообщениями (HELO/EHLO) deny message = "HELO/EHLO require by SMTP RFC" condition = ${if eq{$sender_helo_name}{}{yes}{no}} # Принимаем сообщения от тех, кто аутентифицировался: accept authenticated = * # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Рубаем нах, тех, кто подставляет свой IP в HELO # deny message = "Your IP in HELO - access denied!" # hosts = * : !+relay_from_hosts : !81-196.lissyara.su # 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 = "main IP in your HELO! Access denied!" # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Рубаем тех, кто в HELO пихает только цифры # (не бывает хостов ТОЛЬКО из цифр) deny condition = ${if match{$sender_helo_name}\ {\N^\d+$\N}{yes}{no}} hosts = !127.0.0.1 : !localhost : * message = "can not be only number in HELO!" # Рубаем тех, кто не пишет отправителя # deny condition = ${if eq{$sender_address}{}{yes}{no}} # hosts = !127.0.0.1 : !localhost : * # message = "А какого HELO пустое?! Не по RFC..." # Рубаем тех, кто не пишет отправителя (пробел) # deny condition = ${if match{$sender_address}{\N^\s+$\N}{yes}{no}} # hosts = !127.0.0.1 : !localhost : * # message = "А какого HELO пустое (тока пробелы)?! Не по RFC..." # Рубаем тех, кто не пишет отправителя # deny condition = ${if eq{$sender_address}{}{yes}{no}} # hosts = !127.0.0.1 : !localhost : * # message = "Where sender of this mail?!" # Рубаем хосты типа *adsl*; *dialup*; *pool*;.... # Нормальные люди с таких не пишут. Если будут # проблемы - уберёте проблемный пункт (у меня клиенты # имеют запись типа asdl-1233.zone.su - я ADSL убрал...) deny message = "your hostname is bad (adsl, poll, ppp & etc)." condition = ${if match{$sender_host_name} \ {adsl|dialup|pool|peer|dhcp} \ {yes}{no}} warn # ставим дефолтовую задержку в 0 секунд set acl_m0 = 30s warn # ставим задержку в 0 секунд своим хостам и # дружественным сетям (соседняя контора :)) hosts = +relay_from_hosts:192.168.1.0/29 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 = "In my mailserver not stored this user" verify = recipient # Рубаем тех, кто в блэк-листах. Серваки перебираются # сверху вниз, если не хост не найден на первом, то # запрашивается второй, и т.д. Если не найден ни в одном # из списка - то почта пропускается. deny message = "you in blacklist - $dnslist_domain \n $dnslist_text" dnslists = opm.blitzed.org : \ cbl.abuseat.org : \ bl.csma.biz : \ dynablock.njabl.org # Разрешаем почту от доменов в списке relay_from_hosts accept hosts = +relay_from_hosts # Если неподошло ни одно правило - чувак явно ищет # открытый релей. Пшёл прочь. :) deny message = "Homo hominus lupus est" # ACL проверяющие содержимое (тело) письма. acl_check_data: # Проверяем письмо на вирусы deny malware = * message = "In e-mail found VIRUS - $malware_name" # Если есть необходимость - тут проверки на спам # Пропускаем остальное 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 : 195.151.216.193 #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}'}} # Доставляем почту в dovecot dovecot_user: driver = accept condition = ${lookup mysql{SELECT `goto` FROM \ `alias` WHERE \ `address`='${quote_mysql:$local_part@$domain}' OR \ `address`='${quote_mysql:@$domain}'}{yes}{no}} transport = dovecot_delivery # начинаются транспорты - как доставляем почту begin transports # Доставка на удалённые хосты - по SMTP remote_smtp: driver = smtp # Доставка локальным адресатам - в dovecot. dovecot_delivery: driver = pipe command = /usr/lib/dovecot/deliver -d $local_part@$domain message_prefix = message_suffix = delivery_date_add envelope_to_add return_path_add log_output user = mail # Имя программы address_pipe: driver = pipe return_output # Транспорт для автоответов address_reply: driver = autoreply # Начинаются повторы недоставленных писем. begin retry * * F,2h,15m; G,16h,1h,1.5; F,4d,6h # преобразование адресов. У меня такого нету. begin rewrite # Секция авторизации при отправке писем. begin authenticators # Oутглюк auth_plain: driver = plaintext public_name = PLAIN server_condition = ${lookup mysql{SELECT `username` FROM \ `mailbox` WHERE `username` = \ '${quote_mysql:$2}' AND `password` = \ '${quote_mysql:$3}'}{yes}{no}} server_prompts = : server_set_id = $auth2 # Вроде по этому оутглюк, а по предыдущему нетскейп. auth_login: driver = plaintext public_name = LOGIN server_condition = ${lookup mysql{SELECT `username` FROM \ `mailbox` WHERE `username` = \ '${quote_mysql:$auth1}' AND `password` = \ '${quote_mysql:$auth2}'}{yes}{no}} server_prompts = Username:: : Password:: server_set_id = $auth1 # А так авторизуется "Летучая Мышь" - TheBat! auth_cram_md5: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${lookup mysql{SELECT `password` FROM \ `mailbox` WHERE `username` \ = '${quote_mysql:$auth1}'}{$value}fail} server_set_id = $auth2!
Установка Dovecot2
- apt-get install dovecot-common dovecot-imapd dovecot-mysql dovecot-pop3d
dovecot.conf
nano /etc/dovecot/dovecot.conf
nano /etc/dovecot/dovecot-mysql.conf
# Database driver: mysql, pgsql, sqlite driver = mysql # Database connection string. This is driver-specific setting. connect = host=localhost dbname=users user=dovecot password=password # Default password scheme. default_pass_scheme = MD5 # passdb query to retrieve the password. It can return fields: password_query = \ SELECT username, domain, password \ FROM users WHERE username = '%n' AND domain = '%d' # userdb query to retrieve the user information. It can return fields: user_query = \ SELECT home, uid, gid \ FROM users WHERE username = '%n' AND domain = '%d' # If you wish to avoid two SQL lookups (passdb + userdb), you can use # userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll # also have to return userdb fields in password_query prefixed with "userdb_" # string. For example: password_query = \ SELECT userid AS user, password, \ home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \ FROM users WHERE userid = '%u' # Query to get a list of all usernames.
SQL
CREATE TABLE users ( username VARCHAR(128) NOT NULL, DOMAIN VARCHAR(128) NOT NULL, PASSWORD VARCHAR(64) NOT NULL, home VARCHAR(255) NOT NULL, uid INTEGER NOT NULL, gid INTEGER NOT NULL, active CHAR(1) DEFAULT 'Y' NOT NULL );
Проверка
- exim -bd -d+all