Диагноз: сервер молчит, письма не уходят, клиент уже пишет
Настроил рассылку. Или форму обратной связи. Или переехал на новый VPS. И тишина. В логах — «deferred», «relay access denied», «connection refused». Клиент пишет что не получил письмо. Дедлайн через час.
Знакомо. Видел это раз триста. И каждый раз причина одна из пяти — просто не всегда очевидно, которая именно.
Вот что получишь после прочтения: понимание почему вообще это ломается, пошаговую диагностику с командами copy-paste, отдельные разделы для Postfix и Exim, разбор SMTP-кодов ошибок, диагностику TLS/STARTTLS, настройку relay через внешние сервисы и скрипт автодиагностики. Времени: 15 минут если проблема типовая, 40 — если всё плохо.
Что нужно: root или sudo на сервере, пара утилит и нежелание гуглить каждую ошибку отдельно.
# Установить всё нужное сразу:
# Debian/Ubuntu:
apt-get install -y telnet openssl mailutils dnsutils curl swaks
# CentOS/RHEL/Rocky:
yum install -y telnet openssl mailx bind-utils curl
# swaks отдельно (нет в базовых репах):
curl -L https://jetmore.org/john/code/swaks/files/swaks -o /usr/local/bin/swaks
chmod +x /usr/local/bin/swaks
Пять причин — и одна из них твоя
Перед тем как лезть в конфиги — обозначим врага. Проблемы с отправкой почты с Linux-сервера делятся ровно на пять групп. Почти всегда это одна из них.
1. Заблокирован порт 25 провайдером. Самая частая причина на новых VPS. AWS, Hetzner, DigitalOcean, Selectel — все по умолчанию режут исходящий порт 25 против спама. Твой Postfix исправно пытается отправить, а на уровне сети его уже нет. Решение: либо тикет провайдеру, либо SMTP relay через порт 587.
2. MTA не запущен или сломан конфиг. Postfix упал тихо ночью. Exim не слушает нужный интерфейс. Конфиг сломался после apt upgrade. Очередь переполнена и заморожена. Смешно, но 20% случаев — именно это.
3. DNS: SPF, DKIM, DMARC, PTR. Письмо уходит с сервера, но Gmail его отбивает или кидает в спам. IP не включён в SPF. DKIM-подписи нет. PTR-записи нет — сервер «анонимный», и это красный флаг для всех серьёзных почтовых систем.
4. IP в чёрном списке. Предыдущий арендатор VPS с этого IP рассылал спам. Или ты сам случайно отправил тысячу писем в цикле. Теперь IP в DNSBL — письма молча отбиваются без объяснений.
5. Проблема аутентификации SMTP. SASL auth не настроен. TLS не работает. Приложение пытается подключиться без авторизации, а relay запрещён. Итог: «relay access denied» или «authentication required».
Как работает путь письма: схема
Прежде чем диагностировать — пойми где именно рвётся цепочка. Каждый узел может быть точкой отказа.
Схема 1: Путь письма от приложения до входящих. Каждый узел — потенциальная точка отказа. Диагностику начинай с MTA и PORT — там рвётся чаще всего.
Шаг 1 — Проверить запущен ли MTA
Смешно, но с этого надо начинать. Postfix падает тихо. После apt upgrade конфиг может не загрузиться. После перезагрузки сервера — не запуститься автоматически, если кто-то забыл enable.
Postfix
# Статус:
systemctl status postfix
# Ищи: Active: active (running)
# Если нет:
systemctl start postfix
systemctl enable postfix
# Проверить конфиг перед запуском:
postfix check
# Тихо = конфиг ок. Ошибки — будут выведены.
# Посмотреть на каком порту и интерфейсе слушает:
ss -tlnp | grep -E ':(25|587|465)'
# Должно быть: LISTEN 0 100 0.0.0.0:25 ...
Exim
# Статус (Debian/Ubuntu — exim4, CentOS — exim):
systemctl status exim4
systemctl status exim
# Запустить если не работает:
systemctl start exim4
systemctl enable exim4
# Проверить конфиг Exim:
exim -bV
# Покажет версию и список встроенных модулей
# Синтаксис конфига:
exim -C /etc/exim4/exim4.conf.template -bV 2>&1 | grep -i error
Если ss -tlnp | grep ':25' возвращает пустоту — MTA не слушает порт. Либо не запущен, либо в конфиге inet_interfaces настроен не так.
Шаг 2 — Проверить порты
Порт 25 — классика, которую режут все подряд. AWS, Hetzner, DigitalOcean блокируют исходящий 25 по умолчанию. Узнать это можно только попробовав.
# Проверить исходящий порт 25 с сервера (к MX Google):
telnet aspmx.l.google.com 25
# "Connected to aspmx.l.google.com" + баннер "220" = порт открыт
# Timeout или "Connection refused" = провайдер режет
# Без интерактива:
timeout 10 bash -c 'echo QUIT | telnet aspmx.l.google.com 25 2>&1' | grep -E "220|refused|timeout"
# Альтернатива через curl:
curl -v telnet://aspmx.l.google.com:25 2>&1 | head -15
# Проверить порт 587 (submission):
telnet localhost 587
telnet smtp.gmail.com 587
# Проверить порт 465 (SMTPS):
openssl s_client -connect localhost:465
# Посмотреть файрвол на сервере:
# UFW:
ufw status verbose
# iptables:
iptables -L -n | grep -E "smtp|25|587|465"
# firewalld:
firewall-cmd --list-all
Шаг 3 — Диагностика Postfix: очередь и логи
Просмотр очереди
# Вся очередь:
mailq
# или:
postqueue -p
# Сколько писем застряло:
postqueue -p | tail -1
# Детали конкретного письма по ID из mailq:
postcat -q ABCDEF1234
# Принудительно отправить всё из очереди:
postqueue -f
# Удалить все письма (осторожно — необратимо):
postsuper -d ALL
# Удалить только deferred:
postsuper -d ALL deferred
# Удалить письма конкретного отправителя:
mailq | grep "^[A-F0-9]" | awk '{print $1}' | \
xargs -I{} postcat -q {} | grep -l "sender@example.com" | \
xargs postsuper -d
Логи Postfix
# Последние 100 строк:
tail -100 /var/log/mail.log
# На CentOS/Rocky:
tail -100 /var/log/maillog
# Только ошибки:
grep -iE "error|reject|deferred|bounced|failed|refused" /var/log/mail.log | tail -50
# Следить в реальном времени (пока тестируешь):
tail -f /var/log/mail.log
# Что происходило с конкретным письмом (по адресу получателя):
grep "recipient@gmail.com" /var/log/mail.log | tail -20
# Все попытки отправки за последний час:
grep "$(date '+%b %e %H')" /var/log/mail.log | grep "status="
Минимальный рабочий конфиг Postfix
Если хочешь начать с чистого листа — вот конфиг, который работает на большинстве серверов без сюрпризов:
# /etc/postfix/main.cf
myhostname = mail.yourdomain.com
mydomain = yourdomain.com
myorigin = $mydomain
inet_interfaces = all
inet_protocols = ipv4
# Локальная доставка — убери домен если не принимаешь почту на этот сервер:
mydestination = $myhostname, localhost.$mydomain, localhost
# Только локальные клиенты без авторизации:
mynetworks = 127.0.0.0/8
# Размер письма 50MB:
message_size_limit = 52428800
# TLS:
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_security_level = may
smtp_tls_security_level = may
# SASL auth:
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous
# Ограничения:
smtpd_recipient_restrictions =
permit_sasl_authenticated,
permit_mynetworks,
reject_unauth_destination
# Применить конфиг:
postfix check && systemctl reload postfix
Шаг 4 — Диагностика Exim: очередь, логи, конфиг
Exim стоит по умолчанию на Debian и многих хостингах. Логика та же — очередь, логи, конфиг — но команды другие. Смешивать с Postfix не надо: либо одно, либо другое.
Очередь Exim
# Список писем в очереди:
exim -bp
# Количество писем:
exim -bpc
# Принудительно отправить все (включая frozen):
exim -qff
# Детали конкретного письма по ID:
exim -Mvl ИДЕНТИФИКАТОР
# Заголовки:
exim -Mvh ИДЕНТИФИКАТОР
# Тело:
exim -Mvb ИДЕНТИФИКАТОР
# Удалить конкретное письмо:
exim -Mrm ИДЕНТИФИКАТОР
# Удалить все замороженные (frozen):
exiqgrep -iz | xargs exim -Mrm
# Удалить всё из очереди:
exiqgrep -i | xargs exim -Mrm
Логи Exim
# Основной лог:
tail -100 /var/log/exim4/mainlog
# Только ошибки:
grep -iE "fail|reject|error|frozen|bounce" /var/log/exim4/mainlog | tail -50
# Следить в реальном времени:
tail -f /var/log/exim4/mainlog
# Найти письмо по получателю:
grep "recipient@gmail.com" /var/log/exim4/mainlog | tail -20
# Панический лог (серьёзные ошибки конфига):
cat /var/log/exim4/paniclog
# Если этот файл не пустой — это первое что надо читать
Тест отправки через Exim напрямую
# Тест доставки конкретному адресу (без реальной отправки):
exim -bt recipient@gmail.com
# Покажет как Exim маршрутизирует письмо к этому адресу
# Отправить тестовое письмо из командной строки:
echo "Test body" | exim -v recipient@gmail.com
# Проверить статус конфигурации:
exim -bV 2>&1 | grep -E "version|support|Lookups"
# Проверить что Exim слушает нужные порты:
ss -tlnp | grep exim
Шаг 5 — DNS: SPF, DKIM, DMARC, PTR
Это раздел который все пропускают. А потом удивляются, почему письма летят в спам или не доходят вообще. PTR нет — сервер анонимный, Gmail не любит анонимов. SPF не включает IP — письма от «самозванца». DKIM нет — подпись не верифицируется. DMARC нет — Microsoft начинает хмуриться.
PTR-запись
# Получить свой внешний IP:
curl -s https://api.ipify.org && echo
# Проверить PTR (замени 1.2.3.4 на свой IP):
dig -x 1.2.3.4 +short
# Должно вернуть: mail.yourdomain.com.
# Пусто = PTR не настроен = иди в панель провайдера и настраивай
# Или через nslookup:
nslookup 1.2.3.4
SPF
# Проверить SPF-запись:
dig TXT yourdomain.com +short | grep spf
# Должно быть: "v=spf1 ip4:1.2.3.4 include:... ~all"
# Если IP сервера не в SPF — Gmail и Outlook будут отбивать письма.
# Минимальная SPF-запись (добавь TXT в DNS):
# v=spf1 ip4:ТУТ_IP_ТВОЕГО_СЕРВЕРА mx ~all
DKIM
# Проверить DKIM-запись (селектор 'mail'):
dig TXT mail._domainkey.yourdomain.com +short
# Должна быть длинная строка с "p=" — это публичный ключ
# Если нет — ставим opendkim:
apt-get install -y opendkim opendkim-tools
# Генерируем ключи:
mkdir -p /etc/opendkim/keys/yourdomain.com
opendkim-genkey -b 2048 -d yourdomain.com \
-D /etc/opendkim/keys/yourdomain.com -s mail -v
# Смотрим что добавить в DNS:
cat /etc/opendkim/keys/yourdomain.com/mail.txt
# Права на приватный ключ:
chown opendkim:opendkim /etc/opendkim/keys/yourdomain.com/mail.private
chmod 600 /etc/opendkim/keys/yourdomain.com/mail.private
# /etc/opendkim.conf — минимальный конфиг:
Domain yourdomain.com
KeyFile /etc/opendkim/keys/yourdomain.com/mail.private
Selector mail
Socket inet:12301@localhost
Mode sv
# /etc/postfix/main.cf — подключить milter:
milter_protocol = 6
milter_default_action = accept
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301
systemctl restart opendkim postfix
DMARC
# Проверить DMARC:
dig TXT _dmarc.yourdomain.com +short
# Ожидаем: "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"
# Минимальная запись (TXT на _dmarc.yourdomain.com):
# v=DMARC1; p=none; rua=mailto:postmaster@yourdomain.com
# p=none — только мониторинг. p=quarantine — спам. p=reject — жёсткий отказ.
# Начни с none, потом ужесточай.
| Инструмент | Что проверяет | URL |
|---|---|---|
| MXToolbox | SPF, DKIM, DMARC, Blacklist, MX | mxtoolbox.com |
| Mail-tester.com | Полный скоринг письма | mail-tester.com |
| DKIM Validator | DKIM-подпись | dkimvalidator.com |
| Google Postmaster | Репутация домена у Gmail | postmaster.google.com |
Шаг 6 — Проверка IP на blacklist
# Быстрая проверка вручную (замени 1.2.3.4 на свой IP):
# Для Spamhaus:
dig 4.3.2.1.zen.spamhaus.org
# Для Spamcop:
dig 4.3.2.1.bl.spamcop.net
# 127.0.0.x в ответе = ты в списке. NXDOMAIN = чист.
#!/bin/bash
# Скрипт проверки по 6 blacklist-ам сразу:
IP="1.2.3.4" # Замени на свой IP
REVERSED=$(echo $IP | awk -F. '{print $4"."$3"."$2"."$1}')
LISTS=(
"zen.spamhaus.org"
"bl.spamcop.net"
"dnsbl.sorbs.net"
"b.barracudacentral.org"
"dnsbl-1.uceprotect.net"
"psbl.surriel.com"
)
echo "Проверка IP: $IP"
echo "-----------------------------"
for LIST in "${LISTS[@]}"; do
RESULT=$(dig +short "${REVERSED}.${LIST}" 2>/dev/null)
if [ -n "$RESULT" ]; then
echo "НАЙДЕН в: $LIST ($RESULT)"
else
echo "Чист: $LIST"
fi
done
IP в blacklist — подаёшь заявку на делистинг на сайте конкретного листа. Spamhaus: spamhaus.org/removal. Barracuda: lookup.barracudacentral.org. Spamcop: не делистирует сам, ждёшь 24 часа после прекращения жалоб.
Шаг 7 — Тест SMTP вручную: telnet и openssl
Это самый надёжный способ убедиться что SMTP вообще работает. Руками, без обёрток.
Telnet на порт 25
telnet localhost 25
# После подключения — вводишь команды вручную:
EHLO test.yourdomain.com
MAIL FROM:<test@yourdomain.com>
RCPT TO:<recipient@gmail.com>
DATA
Subject: Manual SMTP test
Test body — если это дошло, значит работает.
.
QUIT
STARTTLS через openssl на порт 587
# Подключиться с STARTTLS:
openssl s_client -starttls smtp -connect localhost:587
# К внешнему серверу:
openssl s_client -starttls smtp -connect smtp.gmail.com:587
# После подключения вводишь:
# EHLO yourdomain.com
# AUTH LOGIN
# (потом base64-логин и пароль отдельными строками)
# Закодировать логин/пароль в base64:
echo -n "user@yourdomain.com" | base64
echo -n "yourpassword" | base64
SMTPS через openssl на порт 465
openssl s_client -connect localhost:465
# Порт 465 — сразу SSL/TLS, без STARTTLS
# После подключения видишь баннер сервера
swaks — лучший тестировщик SMTP
Одна команда вместо двадцати. Тестирует всё включая аутентификацию и TLS.
# Тест с аутентификацией через порт 587:
swaks \
--to recipient@gmail.com \
--from sender@yourdomain.com \
--server localhost \
--port 587 \
--auth LOGIN \
--auth-user sender@yourdomain.com \
--auth-password "yourpassword" \
--tls \
--header "Subject: SMTP Test via swaks" \
--body "Если это дошло — сервер работает. Можно идти спать."
# Тест без авторизации (порт 25, локально):
swaks --to recipient@gmail.com --from sender@yourdomain.com --server localhost
# Тест с подробным выводом (для отладки):
swaks --to recipient@gmail.com --server localhost --port 587 -tlso --tls -v
Шаг 8 — Диагностика TLS/STARTTLS
TLS не работает — и ты об этом не знаешь. Письма уходят или нет, но с ошибками в логах типа «STARTTLS not available» или «certificate verify failed». Разбираем отдельно.
Проверить TLS на своём сервере
# Проверить что Postfix поддерживает TLS:
postconf -a | grep -i tls
# или:
postconf smtpd_tls_security_level smtp_tls_security_level
# Посмотреть TLS-параметры в конфиге:
postconf | grep -E "tls|ssl" | grep -v "^#"
# Проверить сертификат:
openssl s_client -starttls smtp -connect localhost:587 2>/dev/null | \
openssl x509 -noout -dates -subject
# Смотрим: notBefore, notAfter (срок действия), subject (домен)
# Проверить срок сертификата — не истёк ли:
openssl s_client -starttls smtp -connect localhost:587 2>/dev/null | \
openssl x509 -noout -enddate
# Если дата в прошлом — сертификат истёк. Обнови.
# Для Let's Encrypt — проверить автообновление:
certbot renew --dry-run
# или:
systemctl status certbot.timer
Настройка TLS в Postfix
# /etc/postfix/main.cf — параметры TLS:
# Входящие соединения (smtpd = сервер):
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.yourdomain.com/privkey.pem
smtpd_tls_security_level = may
# may = предлагать TLS, не требовать.
# encrypt = требовать TLS. Осторожно — может сломать старых клиентов.
# Исходящие соединения (smtp = клиент):
smtp_tls_security_level = may
smtp_tls_loglevel = 1
# loglevel=1 — логировать TLS-соединения. Помогает при отладке.
# Кэш TLS-сессий:
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# Применить:
postfix check && systemctl reload postfix
# Проверить в логах что TLS поднимается:
grep -i "tls" /var/log/mail.log | tail -20
# Ищем: "TLS connection established" — хорошо.
# "STARTTLS not available" — TLS не поднялся, смотри конфиг.
# "certificate verify failed" — проблема с сертификатом.
TLS в Exim
# Проверить что Exim поддерживает TLS:
exim -bV | grep -i tls
# Ищем: Support for: ... TLS
# Проверить TLS-соединение к своему Exim:
openssl s_client -starttls smtp -connect localhost:587
# Логи TLS в Exim (включить если нет):
# В /etc/exim4/exim4.conf добавь в секцию main:
# log_selector = +tls_peerdn +tls_certificate_verified
# Применить:
systemctl reload exim4
grep -i tls /var/log/exim4/mainlog | tail -20
Шаг 9 — SMTP relay: SendGrid, Mailgun, Amazon SES
Если порт 25 заблокирован провайдером и они не открывают — relay через внешний сервис. Это вообще правильнее для серьёзных рассылок: репутация IP у SendGrid уже наработана, доставляемость выше, blacklist не твоя проблема.
Схема 2: SMTP relay — Postfix отправляет через внешний сервис. Твой IP не важен, важна репутация relay-провайдера.
# /etc/postfix/main.cf — relay через SendGrid:
relayhost = [smtp.sendgrid.net]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
header_size_limit = 4096000
# Создать файл с паролями:
echo "[smtp.sendgrid.net]:587 apikey:ТУТ_ТВОЙ_API_KEY" > /etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd
chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
# Применить:
systemctl reload postfix
# Тест через swaks:
swaks --to test@gmail.com --from sender@yourdomain.com \
--server smtp.sendgrid.net --port 587 \
--auth-user apikey --auth-password "ТУТ_ТВОЙ_API_KEY" --tls
Для Mailgun — замени хост на smtp.mailgun.org и используй SMTP credentials из панели. Для Amazon SES — email-smtp.us-east-1.amazonaws.com:587, credentials из IAM. Логика та же.
Коды ошибок SMTP: расшифровка
В логах есть числа. Они не случайные. Вот что значат.
| Код | Что означает | Первый шаг |
|---|---|---|
| 220 | Сервер готов | Норма, соединение установлено |
| 250 | Команда принята | Норма |
| 421 | Сервис временно недоступен | Принимающий сервер перегружен — deferred, попробует позже |
| 450 | Ящик временно недоступен | Временная ошибка, будет retry |
| 451 | Ошибка обработки на сервере | Проверь /etc/resolv.conf, DNS-резолвер |
| 452 | Недостаточно места | df -h — проверь диск на сервере |
| 500 | Синтаксическая ошибка команды | Неверная команда в SMTP-сессии |
| 501 | Неверные параметры команды | Проверь формат MAIL FROM / RCPT TO |
| 550 | Ящик не найден / отказ доставки | Адрес не существует или заблокирован |
| 550 5.7.1 | SPF check failed | Добавь ip4:IP в SPF-запись домена |
| 550 5.7.26 | DMARC policy violation | Проверь SPF+DKIM, оба должны пройти |
| 553 | Неверный адрес отправителя | Проверь myhostname и myorigin в main.cf |
| 554 | Transaction failed | IP в blacklist или письмо содержит спам-контент |
| 535 | Authentication failed | Неверный логин/пароль — проверь sasl_passwd |
| 534 | Authentication mechanism too weak | Включи STARTTLS — сервер не принимает пароли без шифрования |
Типовые сообщения из логов
| Ошибка в логах | Причина | Решение |
|---|---|---|
| relay access denied | Postfix не пускает как relay без авторизации | Настрой SASL auth, проверь mynetworks |
| Connection refused (port 25) | MTA не слушает или провайдер режет | systemctl status postfix, тикет провайдеру |
| Connection timed out | Файрвол режет исходящие соединения | Проверь iptables/ufw, попробуй relay |
| SASL authentication failed | Неверный логин/пароль для relay | Проверь sasl_passwd, пересоздай postmap |
| mail for X loops back to myself | Неверный mydestination или myhostname | Убери домен из mydestination |
| STARTTLS not available | TLS не настроен или сертификат недействителен | Проверь cert_file/key_file в main.cf |
| certificate verify failed | Сертификат истёк или самоподписанный | certbot renew, проверь дату сертификата |
| deferred (host or domain not found) | DNS не резолвит MX получателя | Проверь /etc/resolv.conf, смени DNS на 8.8.8.8 |
| fatal: open /etc/postfix/main.cf: Permission denied | Права на конфиг сломаны | chown root:root /etc/postfix/main.cf, chmod 644 |
| warning: SASL: Connect to private/auth failed | Dovecot не запущен или сокет не там | systemctl status dovecot, проверь smtpd_sasl_path |
Скрипт автодиагностики SMTP
Хватит делать всё по одному. Скрипт пробегается по всем ключевым точкам и выдаёт отчёт за 30 секунд. Скопируй, сохрани, запусти.
#!/bin/bash
# ================================================
# smtp_diag.sh — Диагностика SMTP-сервера Linux
# Использование: sudo bash smtp_diag.sh yourdomain.com 1.2.3.4
# ================================================
DOMAIN="${1:-yourdomain.com}"
SERVER_IP="${2:-$(curl -s https://api.ipify.org 2>/dev/null)}"
REVERSED_IP=$(echo "$SERVER_IP" | awk -F. '{print $4"."$3"."$2"."$1}')
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
ok() { echo -e "${GREEN}OK ${NC} $1"; }
fail() { echo -e "${RED}FAIL ${NC} $1"; }
warn() { echo -e "${YELLOW}WARN ${NC} $1"; }
echo "========================================"
echo " SMTP Диагностика | IT-Apteka.com"
echo " Домен: $DOMAIN | IP: $SERVER_IP"
echo "========================================"
# 1. MTA
echo; echo "[ 1/8 ] Почтовый агент (MTA)"
MTA_FOUND=0
for MTA in postfix exim4 exim sendmail; do
if systemctl is-active --quiet "$MTA" 2>/dev/null; then
ok "$MTA запущен"
MTA_FOUND=1; break
fi
done
[ $MTA_FOUND -eq 0 ] && fail "Ни один MTA не запущен (postfix/exim/sendmail)"
# 2. Порты
echo; echo "[ 2/8 ] Порты SMTP (локально)"
for PORT in 25 587 465; do
if ss -tlnp | grep -q ":$PORT "; then
ok "Порт $PORT слушает"
else
warn "Порт $PORT не слушает"
fi
done
# 3. Исходящий порт 25
echo; echo "[ 3/8 ] Исходящий порт 25 (к Google MX)"
if timeout 8 bash -c 'echo QUIT | telnet aspmx.l.google.com 25 2>&1' | grep -q "220"; then
ok "Исходящий порт 25 открыт"
else
fail "Исходящий порт 25 заблокирован — провайдер или файрвол"
fi
# 4. PTR
echo; echo "[ 4/8 ] PTR-запись (обратный DNS)"
PTR=$(dig -x "$SERVER_IP" +short 2>/dev/null | head -1)
if [ -n "$PTR" ]; then
ok "PTR настроен: $PTR"
else
fail "PTR-запись отсутствует для IP $SERVER_IP"
fi
# 5. SPF
echo; echo "[ 5/8 ] SPF-запись"
SPF=$(dig TXT "$DOMAIN" +short 2>/dev/null | grep -i "v=spf1")
if [ -n "$SPF" ]; then
ok "SPF найден: $SPF"
echo "$SPF" | grep -q "$SERVER_IP" && \
ok "IP сервера включён в SPF" || \
warn "IP $SERVER_IP может не быть в SPF — проверь вручную"
else
fail "SPF-запись отсутствует для $DOMAIN"
fi
# 6. DKIM
echo; echo "[ 6/8 ] DKIM (селектор 'mail')"
DKIM=$(dig TXT "mail._domainkey.$DOMAIN" +short 2>/dev/null)
if [ -n "$DKIM" ]; then
ok "DKIM-запись найдена"
else
fail "DKIM не найден (mail._domainkey.$DOMAIN)"
fi
# 7. DMARC
echo; echo "[ 7/8 ] DMARC"
DMARC=$(dig TXT "_dmarc.$DOMAIN" +short 2>/dev/null | grep -i "v=DMARC1")
if [ -n "$DMARC" ]; then
ok "DMARC найден: $DMARC"
else
warn "DMARC-запись отсутствует (не критично, но желательно)"
fi
# 8. Blacklist
echo; echo "[ 8/8 ] Blacklist"
LISTS=("zen.spamhaus.org" "bl.spamcop.net" "dnsbl.sorbs.net" "b.barracudacentral.org")
for LIST in "${LISTS[@]}"; do
RESULT=$(dig +short "${REVERSED_IP}.${LIST}" 2>/dev/null)
[ -n "$RESULT" ] && fail "IP найден в $LIST ($RESULT)" || ok "Чист: $LIST"
done
echo; echo "========================================"
echo " Готово. Домен: $DOMAIN | IP: $SERVER_IP"
echo " $(date)"
echo "========================================"
# Сохранить и запустить:
chmod +x smtp_diag.sh
sudo bash smtp_diag.sh yourdomain.com 1.2.3.4
Осложнения: чек-лист последней надежды
Прошёл все шаги, всё зелёное, а письма всё равно не уходят. Одна капля никотина убивает лошадь. Одна строчка в main.cf без перезагрузки — всю диагностику.
Проверить hostname. Должен совпадать с PTR-записью, быть FQDN.
hostname -f
# Должно быть: mail.yourdomain.com
# Не так — исправь в /etc/hostname и /etc/hosts, потом hostname -F /etc/hostname
Проверить диск. Postfix молча падает при 100% заполнении.
df -h
# /var или / под завязку — чисти
du -sh /var/spool/postfix/deferred/
du -sh /var/log/
# Ротировать логи:
logrotate -f /etc/logrotate.d/rsyslog
SELinux / AppArmor на пути.
# SELinux:
getenforce
# Enforcing — попробуй временно:
setenforce 0
# Смотреть что блокирует:
grep postfix /var/log/audit/audit.log | grep denied | tail -20
# AppArmor:
aa-status | grep postfix
Права на директории Postfix.
postfix set-permissions
ls -la /var/spool/postfix/
Конфиг прошёл check, но не перезагружен.
postfix check && systemctl reload postfix
# reload — применяет main.cf без разрыва соединений
# restart — полный перезапуск, если reload не помог
Gmail отбивает конкретно твой домен. Зарегистрируй домен в Google Postmaster Tools — там видна репутация и причины блокировок: postmaster.google.com
Outlook / Microsoft блокирует. Подай заявку через Sender Support: sendersupport.olc.protection.outlook.com
Профилактика: как не получить это в следующий раз
Скрипт мониторинга очереди — добавь в cron, он пришлёт алерт если что-то пошло не так:
#!/bin/bash
# /usr/local/bin/check_mailq.sh
# Crontab: */15 * * * * /usr/local/bin/check_mailq.sh
THRESHOLD=100
ADMIN_EMAIL="admin@yourdomain.com"
QUEUE_SIZE=$(postqueue -p 2>/dev/null | tail -1 | grep -oP '^\d+')
if [ -n "$QUEUE_SIZE" ] && [ "$QUEUE_SIZE" -gt "$THRESHOLD" ]; then
echo "ALERT: В очереди Postfix $QUEUE_SIZE писем на $(hostname) в $(date)" \
| mail -s "Postfix queue alert" "$ADMIN_EMAIL"
fi
chmod +x /usr/local/bin/check_mailq.sh
(crontab -l 2>/dev/null; echo "*/15 * * * * /usr/local/bin/check_mailq.sh") | crontab -
Три правила которые избавят от большинства проблем: мониторинг очереди раз в 15 минут, проверка blacklist раз в неделю через MXToolbox, и никогда не запускать массовые рассылки прямо с боевого сервера. Для рассылок — отдельный IP или внешний сервис. Репутация IP нарабатывается месяцами, сжигается за час.
FAQ: вопросы про диагностику SMTP на Linux
Почему письма уходят в спам а не во входящие?
Почти всегда одна из трёх причин: IP в blacklist, SPF не включает IP сервера, или DKIM не настроен. Проверяй в таком порядке: скрипт blacklist-проверки → dig TXT домен +short | grep spf → dig TXT mail._domainkey.домен +short. Если всё три ок — проверь mail-tester.com, он покажет скоринг и конкретные причины.
Как понять что именно Postfix пишет в deferred и почему не отправляет?
# Посмотреть причину deferred для каждого письма:
postqueue -p | grep "^[A-F0-9]" | while read id rest; do
echo "=== $id ==="
postcat -q "$id" 2>/dev/null | grep -E "reason|error|host|status"
done
# Или прямо из логов — причина всегда рядом с "deferred":
grep "deferred" /var/log/mail.log | tail -20
Что делать если провайдер не открывает порт 25?
Переходи на SMTP relay через порт 587. SendGrid даёт 100 писем в день бесплатно, Mailgun — 1000 в месяц, Amazon SES — 62000 в месяц если сервер на EC2. Настройка занимает 20 минут по инструкции выше. Это вообще правильнее для боевого сервера: не надо следить за репутацией IP, доставляемость выше.
Как проверить что DKIM-подпись валидна?
# Отправить письмо на check-auth@verifier.port25.com:
echo "Test" | mail -s "DKIM test" check-auth@verifier.port25.com
# Через минуту придёт автоответ с результатами проверки SPF/DKIM/DMARC
# Или через swaks и потом проверить заголовки полученного письма:
swaks --to check-auth@verifier.port25.com --from test@yourdomain.com --server localhost
Exim или Postfix — что выбрать для нового сервера?
На новом сервере — Postfix. Проще конфиг, лучше документация, большинство туториалов под него. Exim стоит по умолчанию на Debian и на хостингах с cPanel — там не выбираешь. Если уже стоит Exim и работает — не трогай без причины.
Итог
Диагностика SMTP-сервера на Linux — это последовательность из восьми проверок, не гадание на кофейной гуще. MTA запущен, порт открыт, DNS настроен, IP чист, TLS работает. Каждый пункт — одна команда, результат — сразу.
Если после всего этого письма всё равно не уходят — переходи на SMTP relay. Это не поражение, это правильное решение для большинства VPS где провайдер режет 25-й порт и не собирается его открывать.
Оставайтесь на связи
Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.
Подписаться на IT-Аптеку →



