800 000 ₽ в год за почту: переводим юрфирму с Exchange на Postfix

Задача клиента: лицензии Exchange дороже юристов

В январе 2026 года к нам обратилась юридическая фирма «Правовой Партнёр» из Москвы. Специализация — корпоративное право и сделки M&A. В штате 90 сотрудников: 60 юристов, 15 помощников, 10 сотрудников бэк-офиса и 5 IT-специалистов. Почта — основной рабочий инструмент: договоры, юридические заключения, переписка с клиентами и контрагентами.

Фирма использовала Microsoft Exchange Server 2019 на собственном сервере. Проблемы:

  • Стоимость лицензий — Exchange Server Standard CAL + Windows Server CAL на 90 пользователей обходились в ~800 000 ₽/год с учётом Software Assurance
  • Требования к железу — Exchange 2019 требовал 128 ГБ RAM и 12 CPU cores для 90 ящиков, съедая целый сервер за 450 000 ₽
  • Зависимость от Microsoft — после ухода Microsoft с российского рынка обновления безопасности стали приходить нерегулярно
  • Нет квалифицированного Exchange-администратора в штате — поддержка обходилась в 50 000 ₽/мес на аутсорсе

Руководство поставило задачу: перейти на open-source решение без потери функциональности. Критические требования:

  1. Сохранить все письма, папки, контакты и календари
  2. Обеспечить работу ActiveSync для мобильных устройств юристов
  3. Веб-интерфейс не хуже OWA (Outlook Web App)
  4. Антиспам не хуже Exchange
  5. Полная поддержка DKIM, SPF, DMARC — репутация домена критична для юристов
  6. Миграция в выходные, максимальный простой — 4 часа

Специалисты АйТи Фреш предложили стек: Postfix + Dovecot + Rspamd + Roundcube + Z-Push на Ubuntu 22.04 LTS.

План миграции

Мы разработали поэтапный план с минимизацией простоя:

ЭтапОписаниеСрок
1. ПодготовкаУстановка и настройка нового сервера, тестирование5 дней
2. Предварительная синхронизацияКопирование почты через imapsync (фоново, без простоя)3 дня
3. DNS cutoverПереключение MX-записей + финальная дельта-синхронизация4 часа (суббота)
4. ТестированиеПроверка отправки/приёма, ActiveSync, веб-почты1 день
5. МониторингНаблюдение за доставляемостью и стабильностью2 недели

Установка и настройка Postfix

Postfix — это MTA (Mail Transfer Agent), отвечающий за приём и отправку писем по протоколу SMTP. Мы установили его на выделенном сервере с 16 ГБ RAM и 500 ГБ SSD.

Установка и базовая конфигурация

# Устанавливаем Postfix, Dovecot и вспомогательные пакеты
sudo apt update && sudo apt install -y \
  postfix postfix-mysql postfix-policyd-spf-python \
  dovecot-core dovecot-imapd dovecot-lmtpd dovecot-pop3d \
  dovecot-sieve dovecot-managesieved dovecot-mysql \
  certbot mysql-server

# При установке Postfix выбираем: Internet Site
# System mail name: pravpartner.ru

main.cf: основная конфигурация Postfix

# /etc/postfix/main.cf

# === ОСНОВНЫЕ ПАРАМЕТРЫ ===
smtpd_banner = $myhostname ESMTP
myhostname = mail.pravpartner.ru
mydomain = pravpartner.ru
myorigin = $mydomain
mydestination = localhost
relayhost =
mynetworks = 127.0.0.0/8 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4

# === TLS ===
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.pravpartner.ru/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.pravpartner.ru/privkey.pem
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_ciphers = medium
smtp_tls_security_level = may
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
tls_medium_cipherlist = AES128+EECDH:AES128+EDH

# === SASL-АУТЕНТИФИКАЦИЯ (через Dovecot) ===
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes

# === ВИРТУАЛЬНЫЕ ДОМЕНЫ (MySQL) ===
virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailboxes.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-aliases.cf

# === ОГРАНИЧЕНИЯ ===
smtpd_helo_required = yes
smtpd_helo_restrictions =
  permit_mynetworks,
  reject_non_fqdn_helo_hostname,
  reject_invalid_helo_hostname

smtpd_recipient_restrictions =
  permit_mynetworks,
  permit_sasl_authenticated,
  reject_unauth_destination,
  reject_non_fqdn_recipient,
  reject_unknown_recipient_domain,
  check_policy_service unix:private/policyd-spf

smtpd_sender_restrictions =
  permit_mynetworks,
  permit_sasl_authenticated,
  reject_non_fqdn_sender,
  reject_unknown_sender_domain

# === MILTER (Rspamd + DKIM) ===
milter_protocol = 6
milter_default_action = accept
smtpd_milters = inet:localhost:11332
non_smtpd_milters = $smtpd_milters
milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}

# === ЛИМИТЫ ===
message_size_limit = 52428800  # 50 MB
smtpd_client_message_rate_limit = 100
smtpd_client_recipient_rate_limit = 200

MySQL: виртуальные домены и ящики

# Создаём базу данных для почтового сервера
mysql -u root -p << 'SQL'
CREATE DATABASE mailserver CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mailuser'@'localhost' IDENTIFIED BY 'M@il$erver#2026!';
GRANT SELECT ON mailserver.* TO 'mailuser'@'localhost';
FLUSH PRIVILEGES;

USE mailserver;

CREATE TABLE virtual_domains (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL UNIQUE
);

CREATE TABLE virtual_users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  domain_id INT NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE,
  password VARCHAR(255) NOT NULL,
  quota BIGINT DEFAULT 2147483648,  -- 2 GB
  active TINYINT DEFAULT 1,
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
);

CREATE TABLE virtual_aliases (
  id INT AUTO_INCREMENT PRIMARY KEY,
  domain_id INT NOT NULL,
  source VARCHAR(255) NOT NULL,
  destination VARCHAR(255) NOT NULL,
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
);

INSERT INTO virtual_domains (name) VALUES ('pravpartner.ru');
SQL

# Конфигурация Postfix → MySQL
sudo tee /etc/postfix/mysql-virtual-domains.cf > /dev/null << 'EOF'
user = mailuser
password = M@il$erver#2026!
hosts = 127.0.0.1
dbname = mailserver
query = SELECT name FROM virtual_domains WHERE name='%s'
EOF

sudo tee /etc/postfix/mysql-virtual-mailboxes.cf > /dev/null << 'EOF'
user = mailuser
password = M@il$erver#2026!
hosts = 127.0.0.1
dbname = mailserver
query = SELECT email FROM virtual_users WHERE email='%s' AND active=1
EOF

sudo tee /etc/postfix/mysql-virtual-aliases.cf > /dev/null << 'EOF'
user = mailuser
password = M@il$erver#2026!
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'
EOF

sudo chmod 640 /etc/postfix/mysql-*.cf
sudo chown root:postfix /etc/postfix/mysql-*.cf

Настройка Dovecot: IMAP, LMTP, квоты

Dovecot обеспечивает хранение почты и доступ к ней по IMAP/POP3, а также локальную доставку через LMTP.

Основная конфигурация Dovecot

# /etc/dovecot/dovecot.conf
protocols = imap lmtp pop3 sieve
listen = *, ::
mail_home = /var/vmail/%d/%n
mail_location = maildir:/var/vmail/%d/%n/Maildir
mail_uid = vmail
mail_gid = vmail
first_valid_uid = 5000
last_valid_uid = 5000

# Создаём системного пользователя vmail
# sudo groupadd -g 5000 vmail
# sudo useradd -g vmail -u 5000 -d /var/vmail -s /usr/sbin/nologin vmail
# sudo mkdir -p /var/vmail && sudo chown vmail:vmail /var/vmail

Аутентификация через MySQL

# /etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = yes
auth_mechanisms = plain login
!include auth-sql.conf.ext

# /etc/dovecot/conf.d/auth-sql.conf.ext
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

# /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=M@il$erver#2026!
default_pass_scheme = BLF-CRYPT
password_query = SELECT email AS user, password FROM virtual_users \
  WHERE email='%u' AND active=1
user_query = SELECT CONCAT('/var/vmail/', SUBSTRING_INDEX(email,'@',-1), '/', \
  SUBSTRING_INDEX(email,'@',1)) AS home, \
  5000 AS uid, 5000 AS gid, \
  CONCAT('*:bytes=', quota) AS quota_rule \
  FROM virtual_users WHERE email='%u' AND active=1

LMTP и Sieve-фильтры

# /etc/dovecot/conf.d/20-lmtp.conf
protocol lmtp {
  mail_plugins = $mail_plugins sieve quota
  postmaster_address = postmaster@pravpartner.ru
}

# /etc/dovecot/conf.d/15-lda.conf
protocol lda {
  mail_plugins = $mail_plugins sieve quota
}

# /etc/dovecot/conf.d/90-sieve.conf
plugin {
  sieve = /var/vmail/%d/%n/.dovecot.sieve
  sieve_dir = /var/vmail/%d/%n/sieve
  sieve_before = /etc/dovecot/sieve/spam-to-junk.sieve
  sieve_max_script_size = 1M
}

# Глобальный Sieve: спам в папку Junk
sudo mkdir -p /etc/dovecot/sieve
sudo tee /etc/dovecot/sieve/spam-to-junk.sieve > /dev/null << 'EOF'
require ["fileinto", "mailbox"];
if header :contains "X-Spamd-Result" "True" {
  fileinto :create "Junk";
  stop;
}
EOF
sudo sievec /etc/dovecot/sieve/spam-to-junk.sieve
sudo chown -R vmail:vmail /etc/dovecot/sieve

# /etc/dovecot/conf.d/20-imap.conf
protocol imap {
  mail_plugins = $mail_plugins imap_sieve quota imap_quota
  mail_max_userip_connections = 20
}

# Квоты
# /etc/dovecot/conf.d/90-quota.conf
plugin {
  quota = maildir:User quota
  quota_rule = *:storage=2G
  quota_rule2 = Trash:storage=+100M
  quota_grace = 10%%
  quota_status_success = DUNNO
  quota_status_nouser = DUNNO
  quota_status_overquota = "552 5.2.2 Mailbox is full"
}

Rspamd: антиспам и DKIM-подпись

Rspamd — современная система фильтрации спама, значительно превосходящая SpamAssassin по скорости и точности. Мы настроили его для двух задач: фильтрация входящего спама и DKIM-подпись исходящих писем.

Установка Rspamd и Redis

# Добавляем репозиторий Rspamd
curl -fsSL https://rspamd.com/apt-stable/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/rspamd.gpg
echo "deb [signed-by=/etc/apt/keyrings/rspamd.gpg] https://rspamd.com/apt-stable/ $(lsb_release -cs) main" | \
  sudo tee /etc/apt/sources.list.d/rspamd.list
sudo apt update && sudo apt install -y rspamd redis-server

# Настраиваем Redis для Rspamd
sudo tee /etc/rspamd/local.d/redis.conf > /dev/null << 'EOF'
servers = "127.0.0.1";
EOF

Генерация и настройка DKIM

# Генерируем DKIM-ключ
sudo mkdir -p /var/lib/rspamd/dkim
sudo rspamadm dkim_keygen -b 2048 \
  -s 2026 \
  -d pravpartner.ru \
  -k /var/lib/rspamd/dkim/2026.pravpartner.ru.key \
  > /var/lib/rspamd/dkim/2026.pravpartner.ru.dns

sudo chown -R _rspamd:_rspamd /var/lib/rspamd/dkim
sudo chmod 440 /var/lib/rspamd/dkim/*.key

# Выводим DNS-запись для добавления
cat /var/lib/rspamd/dkim/2026.pravpartner.ru.dns
# 2026._domainkey IN TXT ( "v=DKIM1; k=rsa; "
#   "p=MIIBIjANBgkqhki..." );

# Настройка DKIM-подписи
sudo tee /etc/rspamd/local.d/dkim_signing.conf > /dev/null << 'EOF'
path = "/var/lib/rspamd/dkim/$selector.$domain.key";
selector = "2026";
allow_username_mismatch = true;

# Подпись для домена
domain {
  pravpartner.ru {
    path = "/var/lib/rspamd/dkim/2026.pravpartner.ru.key";
    selector = "2026";
  }
}
EOF

# Настройка ARC-подписи (для форвардов)
sudo tee /etc/rspamd/local.d/arc.conf > /dev/null << 'EOF'
path = "/var/lib/rspamd/dkim/$selector.$domain.key";
selector = "2026";
domain {
  pravpartner.ru {
    path = "/var/lib/rspamd/dkim/2026.pravpartner.ru.key";
    selector = "2026";
  }
}
EOF

SPF, DMARC и DNS-записи

# DNS-записи, которые мы добавили у регистратора:

# MX-запись
pravpartner.ru.   IN  MX  10  mail.pravpartner.ru.

# A-запись почтового сервера
mail.pravpartner.ru.  IN  A  185.XX.XX.XX

# PTR (обратная запись) — через хостинг-провайдера
# 185.XX.XX.XX → mail.pravpartner.ru

# SPF
pravpartner.ru.  IN  TXT  "v=spf1 mx a:mail.pravpartner.ru -all"

# DKIM (из вывода rspamadm)
2026._domainkey.pravpartner.ru.  IN  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBg..."

# DMARC
_dmarc.pravpartner.ru.  IN  TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@pravpartner.ru; ruf=mailto:dmarc@pravpartner.ru; fo=1; adkim=r; aspf=r; pct=100"

Мы начали с p=quarantine, чтобы в первые недели не терять письма из-за возможных проблем с DKIM/SPF. После двух недель мониторинга DMARC-отчётов и подтверждения 100% pass rate перешли на p=reject.

Roundcube и Z-Push: веб-почта и ActiveSync

Юристы фирмы привыкли к OWA (Outlook Web App) и ActiveSync на мобильных устройствах. Нам нужно было обеспечить аналогичный опыт.

Установка Roundcube

# Устанавливаем PHP и Roundcube
sudo apt install -y php8.1-fpm php8.1-mysql php8.1-xml php8.1-mbstring \
  php8.1-intl php8.1-zip php8.1-gd php8.1-curl php8.1-ldap \
  nginx

# Скачиваем последнюю версию Roundcube
cd /tmp
wget https://github.com/roundcube/roundcubemail/releases/download/1.6.6/roundcubemail-1.6.6-complete.tar.gz
tar xzf roundcubemail-1.6.6-complete.tar.gz
sudo mv roundcubemail-1.6.6 /var/www/roundcube
sudo chown -R www-data:www-data /var/www/roundcube

# Создаём базу данных для Roundcube
mysql -u root -p << 'SQL'
CREATE DATABASE roundcube CHARACTER SET utf8mb4;
CREATE USER 'roundcube'@'localhost' IDENTIFIED BY 'Rc#2026$ecure';
GRANT ALL ON roundcube.* TO 'roundcube'@'localhost';
FLUSH PRIVILEGES;
SQL

# Импортируем схему
mysql -u roundcube -p'Rc#2026$ecure' roundcube < /var/www/roundcube/SQL/mysql.initial.sql

Конфигурация Roundcube

# /var/www/roundcube/config/config.inc.php
<?php
$config['db_dsnw'] = 'mysql://roundcube:Rc#2026$ecure@localhost/roundcube';
$config['imap_host'] = 'ssl://mail.pravpartner.ru:993';
$config['smtp_host'] = 'tls://mail.pravpartner.ru:587';
$config['smtp_user'] = '%u';
$config['smtp_pass'] = '%p';
$config['support_url'] = 'mailto:it@pravpartner.ru';
$config['product_name'] = 'Почта Правовой Партнёр';
$config['des_key'] = 'rcmail-!24BytesSecretKey!';
$config['plugins'] = [
  'archive',
  'zipdownload',
  'managesieve',
  'password',
  'markasjunk',
  'newmail_notifier',
  'emoticons',
  'vcard_attachments',
  'identity_select',
];
$config['language'] = 'ru_RU';
$config['default_charset'] = 'UTF-8';
$config['mail_pagesize'] = 50;
$config['draft_autosave'] = 120;
$config['mime_types'] = '/etc/mime.types';
$config['upload_max_filesize'] = '50M';
$config['skin'] = 'elastic';
$config['identity_select_headers'] = ['To', 'Cc', 'Delivered-To'];

Z-Push: ActiveSync для мобильных устройств

# Устанавливаем Z-Push
sudo apt install -y z-push z-push-backend-imap z-push-ipc-sharedmemory

# Конфигурация Z-Push
sudo tee /etc/z-push/z-push.conf.php > /dev/null << 'ZEOF'
<?php
define('TIMEZONE', 'Europe/Moscow');
define('BACKEND_PROVIDER', 'BackendIMAP');
define('IMAP_SERVER', 'mail.pravpartner.ru');
define('IMAP_PORT', 993);
define('IMAP_OPTIONS', '/ssl/novalidate-cert');
define('IMAP_SMTP_METHOD', 'smtp');
define('SMTP_SERVER', 'mail.pravpartner.ru');
define('SMTP_PORT', 587);
define('SMTP_AUTH', true);
define('USE_FULLEMAIL_FOR_LOGIN', true);
define('AUTODISCOVER_LOGIN_TYPE', 'AUTODISCOVER_LOGIN_EMAIL');
define('STATE_DIR', '/var/lib/z-push/');
define('LOGFILE', '/var/log/z-push/z-push.log');
define('LOGLEVEL', LOGLEVEL_INFO);
ZEOF

# Nginx конфиг для ActiveSync (autodiscover + Z-Push)
sudo tee /etc/nginx/sites-available/activesync.conf > /dev/null << 'EOF'
server {
    listen 443 ssl;
    server_name mail.pravpartner.ru;

    ssl_certificate /etc/letsencrypt/live/mail.pravpartner.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mail.pravpartner.ru/privkey.pem;

    # Z-Push ActiveSync
    location /Microsoft-Server-ActiveSync {
        alias /usr/share/z-push/index.php;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME /usr/share/z-push/index.php;
        fastcgi_read_timeout 3600;
    }

    # Autodiscover
    location /autodiscover/autodiscover.xml {
        alias /usr/share/z-push/autodiscover/autodiscover.php;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME /usr/share/z-push/autodiscover/autodiscover.php;
    }
    location /Autodiscover/Autodiscover.xml {
        alias /usr/share/z-push/autodiscover/autodiscover.php;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME /usr/share/z-push/autodiscover/autodiscover.php;
    }

    # Roundcube
    location / {
        root /var/www/roundcube;
        index index.php;
        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_pass unix:/run/php/php8.1-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/activesync.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Миграция почты через imapsync

Ключевой этап — перенос всех писем, папок и структуры с Exchange на Dovecot без потери данных.

Подготовка и тестовый прогон

# Устанавливаем imapsync
sudo apt install -y imapsync

# Создаём файл с учётными данными пользователей
# Формат: exchange_email;exchange_password;new_email;new_password
# Этот файл генерировался скриптом из AD-экспорта
sudo tee /root/migration/users.csv > /dev/null << 'EOF'
ivanov@pravpartner.ru;OldP@ss1;ivanov@pravpartner.ru;NewP@ss!2026#a
petrov@pravpartner.ru;OldP@ss2;petrov@pravpartner.ru;NewP@ss!2026#b
# ... 90 строк
EOF

# Тестовый прогон для одного ящика (--dry)
imapsync \
  --host1 exchange.pravpartner.ru --port1 993 --ssl1 \
  --user1 "ivanov@pravpartner.ru" --password1 "OldP@ss1" \
  --host2 mail.pravpartner.ru --port2 993 --ssl2 \
  --user2 "ivanov@pravpartner.ru" --password2 "NewP@ss!2026#a" \
  --automap \
  --regextrans2 's/Sent Items/Sent/' \
  --regextrans2 's/Deleted Items/Trash/' \
  --regextrans2 's/Drafts/Drafts/' \
  --regextrans2 's/Junk Email/Junk/' \
  --exclude "Calendar|Contacts|Tasks|Journal|Notes" \
  --dry

Параметр --automap автоматически маппит стандартные папки Exchange на папки Dovecot. Дополнительные --regextrans2 обрабатывают нестандартные имена.

Массовая миграция: скрипт параллельного переноса

#!/bin/bash
# /root/migration/migrate-all.sh

CSV_FILE="/root/migration/users.csv"
LOG_DIR="/root/migration/logs"
PARALLEL=5  # 5 одновременных миграций

mkdir -p "$LOG_DIR"

migrate_user() {
  IFS=';' read -r user1 pass1 user2 pass2 <<< "$1"
  local logfile="$LOG_DIR/$(echo $user2 | tr '@' '_').log"

  echo "[$(date)] Starting migration: $user1 → $user2"

  imapsync \
    --host1 exchange.pravpartner.ru --port1 993 --ssl1 \
    --user1 "$user1" --password1 "$pass1" \
    --host2 mail.pravpartner.ru --port2 993 --ssl2 \
    --user2 "$user2" --password2 "$pass2" \
    --automap \
    --regextrans2 's/Sent Items/Sent/' \
    --regextrans2 's/Deleted Items/Trash/' \
    --regextrans2 's/Junk Email/Junk/' \
    --exclude "Calendar|Contacts|Tasks|Journal|Notes" \
    --maxsize 52428800 \
    --nofoldersizes \
    --skipemptyfolders \
    --addheader \
    --logfile "$logfile" \
    2>&1

  echo "[$(date)] Finished migration: $user2 (exit code: $?)"
}

export -f migrate_user
export LOG_DIR

# Запускаем параллельно через GNU parallel
cat "$CSV_FILE" | parallel -j $PARALLEL migrate_user {}

# Итоговый отчёт
echo "=== Migration Summary ==="
for log in $LOG_DIR/*.log; do
  user=$(basename "$log" .log | tr '_' '@')
  msgs=$(grep -c 'Flags' "$log" 2>/dev/null || echo 0)
  errors=$(grep -c 'ERR' "$log" 2>/dev/null || echo 0)
  echo "$user: $msgs messages, $errors errors"
done

Предварительная синхронизация запускалась за 3 дня до cutover, пока Exchange ещё работал. В день переключения запускалась дельта-синхронизация — imapsync переносил только новые письма, что занимало 15–20 минут вместо нескольких часов.

DNS cutover и финальное тестирование

Переключение DNS — самый ответственный момент. Мы выполнили его в субботу утром, когда почтовая активность минимальна.

Порядок переключения

# 08:00 — Останавливаем приём почты на Exchange
# (на Exchange через EMS)
Set-TransportServer EXCHANGE01 -MaxInboundConnections 0

# 08:05 — Финальная дельта-синхронизация
bash /root/migration/migrate-all.sh
# Заняла 22 минуты (только новые письма за ночь)

# 08:30 — Переключаем MX-записи
# Старое: pravpartner.ru MX 10 exchange.pravpartner.ru
# Новое: pravpartner.ru MX 10 mail.pravpartner.ru
# TTL был заранее снижен до 300 секунд за 2 дня до миграции

# 08:35 — Проверяем DNS-пропагацию
dig MX pravpartner.ru +short @8.8.8.8
# 10 mail.pravpartner.ru.

dig MX pravpartner.ru +short @77.88.8.8
# 10 mail.pravpartner.ru.

# 08:40 — Тестируем приём почты
echo "Test migration" | mail -s "Migration test" test@pravpartner.ru

# 08:45 — Проверяем в Roundcube: письмо доставлено
# 08:50 — Тестируем отправку
# 09:00 — Проверяем DKIM/SPF/DMARC
curl -s https://www.mail-tester.com/test-xxxxx | grep -E 'SPF|DKIM|DMARC'
# SPF: pass, DKIM: pass, DMARC: pass

# 09:15 — Тестируем ActiveSync (iPhone + Android)
# 09:30 — Миграция завершена. Простой: 1 час 30 минут

Проверка доставляемости

# Проверяем PTR-запись
dig -x 185.XX.XX.XX +short
# mail.pravpartner.ru.

# Проверяем наличие в чёрных списках
for bl in zen.spamhaus.org bl.spamcop.net b.barracudacentral.org \
  dnsbl.sorbs.net; do
  echo -n "$bl: "
  dig +short 185.XX.XX.XX.$bl | grep -q '127' && echo "LISTED!" || echo "clean"
done
# Все clean

# Тестовые отправки на крупные почтовые сервисы
for dest in test@gmail.com test@yandex.ru test@mail.ru test@outlook.com; do
  swaks --to $dest --from admin@pravpartner.ru \
    --server mail.pravpartner.ru:587 \
    --auth --auth-user admin@pravpartner.ru --auth-password 'P@ss' \
    --tls --header "Subject: Delivery test" \
    --body "Testing deliverability from new mail server"
  echo "Sent to $dest"
done

Результаты внедрения

Миграция была выполнена за 8 рабочих дней подготовки + 1,5 часа простоя в субботу. Результаты после первого месяца работы:

  • Экономия — 800 000 ₽/год на лицензиях Exchange + 50 000 ₽/мес на специализированной поддержке = 1 400 000 ₽/год
  • Перенесено — 90 почтовых ящиков, 1 200 000 писем, 340 ГБ данных без потерь
  • Простой — 1,5 часа вместо запланированных 4
  • Доставляемость — 100% DKIM/SPF/DMARC pass rate, mail-tester.com score 10/10
  • ActiveSync — 45 мобильных устройств (iPhone и Android) подключены через Z-Push
  • Производительность — новый сервер использует 4 ГБ RAM из 16 (Exchange требовал 128 ГБ)
  • 0 жалоб на спам — Rspamd с Bayes-обучением показал даже лучшую фильтрацию, чем Exchange
«Честно, я боялся. Переезд с Exchange — это как переезд офиса. Но команда АйТи Фреш сделала всё настолько гладко, что в понедельник сотрудники даже не все заметили, что почта на новом сервере» — IT-директор «Правового Партнёра».

Специалисты АйТи Фреш продолжают сопровождать почтовый сервер на абонентском обслуживании: обновления безопасности, обучение Rspamd на новых спам-паттернах, мониторинг доставляемости и репутации домена.

Часто задаваемые вопросы

Postfix/Dovecot — это MTA/MDA и они не поддерживают календари нативно. Для полной замены Exchange с календарями мы рекомендуем SOGo или Nextcloud Groupware в дополнение к Dovecot. В данном кейсе юристы использовали календари Google Workspace, поэтому перенос CalDAV не требовался.

Да. Outlook подключается к Dovecot по IMAP/SMTP и работает полноценно: письма, папки, правила (через Sieve). Единственное ограничение — Exchange-специфичные функции (shared mailboxes, public folders) работают иначе. Для shared mailboxes мы настраиваем ACL в Dovecot.

При правильной настройке — не менее безопасна. Postfix имеет отличную историю безопасности (меньше CVE, чем у Exchange за последние 5 лет). Rspamd обеспечивает антиспам, DKIM/SPF/DMARC защищают от подделки, TLS шифрует соединения. Дополнительно мы настраиваем fail2ban для защиты от brute-force атак.

Зависит от объёма почты и количества ящиков. Для 90 ящиков и 340 ГБ данных подготовка заняла 5 дней, предварительная синхронизация — 3 дня (фоново), переключение — 1,5 часа. При меньшем объёме (20–30 ящиков) весь проект укладывается в 3–4 дня.

Нужна помощь с настройкой?

Специалисты АйТи Фреш помогут с внедрением и настройкой — 15+ лет опыта, обслуживание от 15 000 ₽/мес

📞 Связаться с нами
#миграция Exchange на Postfix#Postfix Dovecot настройка#замена Exchange бесплатная почта#imapsync миграция почты#DKIM SPF DMARC настройка#Roundcube веб-почта#Z-Push ActiveSync#Rspamd антиспам