Диагностика SMTP-сервера Linux: письма не уходят — чиним за 15 минут

Диагностика SMTP-сервера Linux: Postfix и Exim отдельно, коды ошибок с расшифровкой, TLS/STARTTLS, SPF/DKIM/DMARC, blacklist, relay и скрипт автодиагностики.
Быстрый ответ
Письма не уходят с Linux-сервера в 80% случаев по одной из трёх причин: провайдер заблокировал порт 25, IP не в SPF-записи, или MTA вообще не запущен. Проверяй в таком порядке: systemctl status postfixtelnet aspmx.l.google.com 25dig TXT домен +short | grep spf. Если всё три ок — читай дальше, там глубже.

Диагноз: сервер молчит, письма не уходят, клиент уже пишет

Настроил рассылку. Или форму обратной связи. Или переехал на новый 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».

Правило экономии времени
В 80% случаев виноваты пункты 1 и 3. Начни с них — сэкономишь час жизни.

Как работает путь письма: схема

Прежде чем диагностировать — пойми где именно рвётся цепочка. Каждый узел может быть точкой отказа.

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#ffffff',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'lineColor': '#64748b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'flowchart': {'curve': 'linear', 'nodeSpacing': 45, 'rankSpacing': 50}
}}%%
flowchart TD
    APP["Приложение / PHP mail()\nSendmail / CLI"]
    MTA["MTA (Postfix / Exim)\nОчередь отправки"]
    PORT["Порт 25 / 587\nФайрвол / Провайдер"]
    DNS_LOOKUP["DNS lookup\nMX-запись получателя"]
    REMOTE["Принимающий SMTP\nGmail / Outlook / etc"]
    SPAM_CHK["Проверки на приёмной стороне\nSPF / DKIM / DMARC / Blacklist"]
    INBOX["Входящие получателя"]
    SPAM["Спам / Отказ\n550 / 421 / deferred"]

    APP -->|"sendmail() / SMTP"| MTA
    MTA -->|"Очередь → отправка"| PORT
    PORT -->|"TCP соединение"| DNS_LOOKUP
    DNS_LOOKUP -->|"Резолв MX"| REMOTE
    REMOTE -->|"Проверка отправителя"| SPAM_CHK
    SPAM_CHK -->|"Прошёл"| INBOX
    SPAM_CHK -->|"Не прошёл"| SPAM

    style APP fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style MTA fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
    style PORT fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#b91c1c
    style DNS_LOOKUP fill:#f8fafc,stroke:#94a3b8,stroke-width:2px,color:#1e293b
    style REMOTE fill:#f8fafc,stroke:#94a3b8,stroke-width:2px,color:#1e293b
    style SPAM_CHK fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
    style INBOX fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style SPAM fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#b91c1c

Схема 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
Порт 25 заблокирован провайдером — что делать
Открой тикет провайдеру — объясни что ты легальный отправитель. Или сразу переходи на SMTP relay через порт 587. Для большинства задач это правильнее: не надо следить за репутацией IP, не надо бороться с blacklist-ами.

Шаг 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 не твоя проблема.

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#ffffff',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'lineColor': '#64748b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart LR
    APP["Postfix\nна твоём VPS"]
    RELAY["SMTP Relay\nSendGrid / Mailgun / SES\nПорт 587"]
    DEST["Получатель\nGmail / Outlook"]

    APP -->|"Аутентификация\nAPI key / SASL"| RELAY
    RELAY -->|"Проверенный IP\nВысокая репутация"| DEST

    style APP fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style RELAY fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
    style DEST fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d

Схема 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 SESemail-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 spfdig 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-Apteka — туда выходят новые рецепты без воды.
Андрей Анатольевич
Author: Андрей Анатольевич

Руководитель ИТ / Кризис-менеджер 25 лет в IT: от инженера в МегаФоне до руководителя отдела. Знаю, как выглядит бардак: нестабильные сети, устаревшая инфраструктура, конфликты в команде, раздутые сроки. Помогаю бизнесу выходить из кризиса: навожу порядок в легаси, стабилизирую то, что разваливается, выстраиваю прогнозируемые процессы. Не раз возвращал к жизни ИТ-структуры — знаю цену хаосу. 📍 Ищу проект для полной реорганизации / стабилизации. 📬 Telegram: @over_dude ✉️ mail@it-apteka.com

Оставайтесь на связи

Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.

Подписаться на IT-Аптеку →

Мы ВКонтакте

IT-Аптека — советы, новости и помощь рядом.

Вступить в группу ВКонтакте →
Поделитесь:

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх