Проверка SPF-записи: по домену или текстом
Введите домен, и мы покажем его SPF-запись, раскроем всю цепочку include и посчитаем DNS-запросы. Запись, которую ещё не опубликовали, вставьте во вкладке «Текст записи»: разбор будет тот же. Если запись выходит за лимит RFC или разрешает отправку кому угодно, скажем об этом прямо и подскажем, что менять.
Что делает SPF-запись
SPF (Sender Policy Framework, RFC 7208) — это список серверов, которым вы разрешили отправлять почту от имени своего домена. Список публикуется TXT-записью в DNS. Когда письмо приходит на почтовый сервер получателя, тот смотрит, с какого IP-адреса пришло соединение, читает вашу SPF-запись и решает, есть ли этот адрес в списке.
Сверяется при этом не адрес из поля From, который видит человек, а домен из конверта письма, из команды MAIL FROM (он же Return-Path). У уведомлений о недоставке конверт пустой, и тогда проверяется имя сервера из приветствия HELO. За совпадение From с проверенным доменом отвечает уже DMARC.
Проверять запись стоит и после первой настройки: со временем она ломается. Подключили новый сервис рассылок, добавили ещё один include и перевалили за лимит. Или провайдер сменил диапазон адресов, или кто-то создал вторую TXT-запись, не заметив первую. В панели DNS всё нормально, а у получателя проверка падает.
Проверить опубликованную запись или черновик
Во вкладке «Домен» мы идём в DNS и разбираем то, что опубликовано там сейчас. Во вкладке «Текст записи» разбираем строку, которую вы вставили, и в DNS её может ещё не быть. Первый режим отвечает на вопрос «что сейчас у домена», второй на вопрос «взлетит ли то, что я собираюсь опубликовать». Разбор у них общий. include в обоих случаях раскрывается настоящими DNS-запросами: чтобы посчитать лимит, нужно знать, что лежит внутри чужих записей сегодня.
Текстом удобно проверять черновик перед публикацией, запись из инструкции нового сервиса (влезет ли ещё один include в оставшийся запас) и вариант, который прислал подрядчик. Вставлять нужно только значение, строку с v=spf1 в начале. Имя, тип и TTL из панели DNS не нужны, внешние кавычки мы уберём сами. Поле «Домен» во второй вкладке заполняют, только если в записи есть механизмы a или mx без явного имени: иначе непонятно, чьи A- и MX-записи имеются в виду.
Раскрытая цепочка и счётчик запросов
Кроме самой записи вы увидите раскрытую цепочку. За каждым include стоит SPF-запись другого домена, внутри неё могут быть свои include, и всё это считается в один общий лимит. Счётчик показывает, сколько из десяти разрешённых запросов уже потрачено, а таблица механизмов отмечает, какие из них тратят запрос.
Главное здесь общее число запросов. Чем ближе оно к десяти, тем выше риск, что очередной сервис допишет include в свою запись и ваша сломается без вашего участия. Ещё стоит пробежать глазами домены в цепочке: если какой-то вы не узнаёте, это, скорее всего, остаток сервиса, от которого отказались год назад, и у него до сих пор есть право слать письма от вашего имени.
Механизмы и квалификаторы в SPF-записи
Запись начинается с v=spf1, дальше через пробел идут механизмы, а в конце обычно стоит all. Получатель читает их слева направо и останавливается на первом совпадении, так что всё написанное после all не действует.
v=spf1 ip4:203.0.113.5 include:_spf.google.com ~allЗдесь разрешены адрес 203.0.113.5 и всё, что перечислено в SPF-записи Google Workspace. Остальным отправителям достаётся softfail.
ip4иip6задают адрес или сеть. Вip4допустим только IPv4 с маской до /32, вip6только IPv6 с маской до /128, одиночный адрес пишется без маски. DNS-запросов эти механизмы не тратят.aиmxразрешают адреса из A- и MX-записей домена. Удобно, но каждый стоит запроса из лимита, а после смены хостинга запись молча начнёт разрешать отправку уже другой машине.includeподключает запись другого домена, обычно сервиса рассылок. Если у того домена SPF-записи нет, проверка заканчивается permerror целиком, а не теряет один сервис.existsвстречается редко, аptrRFC 7208 просит не публиковать вовсе: механизм медленный и при сбоях DNS ненадёжен.redirect=иexp=называются модификаторами. Первый передаёт проверку записи другого домена, если ни один механизм не сработал, второй задаёт текст объяснения при отказе. Незнакомый модификатор получатель пропустит, а вот незнакомый механизм ломает запись.
Перед механизмом может стоять квалификатор: + разрешает (его подразумевают, если знака нет), - запрещает, ~ запрещает мягко, ? ничего не утверждает.
Лимит в 10 DNS-запросов
RFC 7208 разрешает не больше десяти запросов на одну проверку. Их тратят include, a, mx, ptr, exists и модификатор redirect, причём вложенные записи идут в тот же счёт. ip4, ip6 и all лимит не расходуют. Когда запросов больше десяти, проверка заканчивается permerror, и SPF для письма не срабатывает, хотя сама запись выглядит правильной.
Обычно лимит набегает после подключения третьего-четвёртого сервиса: рассылки, CRM и служба поддержки приносят по нескольку вложенных include. Мы советуем держать запас в два-три запроса. Восемь или девять формально проходят, но запись сломается, как только любой из подключённых сервисов расширит инфраструктуру, и предупреждать об этом никто не будет.
Когда запаса нет, сначала удаляют include сервисов, которыми уже не пользуются. Если этого мало, оставшиеся разворачивают в конкретные ip4 и ip6, как описано в статье про SPF-flattening. Только за развёрнутыми адресами потом придётся следить: сменит сервис свои IP, и запись об этом не узнает.
Третий путь: развести отправку по поддоменам, чтобы в конверте у рассылок стоял, скажем, news.example.com, а у поддержки help.example.com. У каждого поддомена своя SPF-запись и свой лимит в десять запросов.
Что означает финальный механизм
-all, fail. Письмо с постороннего сервера можно отклонить. Это правильная цель (с одной оговоркой ниже), но переходить к ней стоит, когда отчёты DMARC подтвердят, что все свои отправители учтены.~all, softfail. Письмо принимают с пометкой. Разумное значение на время настройки.?all, neutral. Получатель не узнаёт ничего полезного.+allразрешает отправку всем. Это хуже, чем отсутствие записи: домен выглядит настроенным и при этом открыт для подделки.- Механизма нет вовсе. Если нет и
redirect, результат будет neutral, как при?all.
У -all есть оговорка, записанная в RFC 9989. Часть получателей проверяет SPF раньше DMARC и отказывает ещё во время SMTP-сессии. Такое письмо не спасёт даже правильная подпись DKIM, с которой DMARC бы его пропустил, и в агрегированные отчёты DMARC оно тоже не попадёт.
Pass, fail, softfail и ещё четыре результата проверки SPF
RFC 7208 называет семь исходов. Сервер получателя записывает их в заголовки Received-SPF и Authentication-Results, и в заголовках конкретного письма видно, чем закончилась проверка.
- pass: IP-адрес есть в записи.
- fail: домен прямо запретил отправку с этого адреса.
- softfail: скорее запрещено, но без жёсткого отказа.
- neutral: домен ничего не утверждает.
- none: SPF-записи нет, или из сессии не удалось извлечь домен.
- temperror: временный сбой DNS, повторная проверка может пройти.
- permerror: запись не удалось разобрать. Исправить это можно только правкой DNS.
Типовые ошибки
- Две записи v=spf1. Подробнее в следующем разделе.
- Больше десяти DNS-запросов. Чаще всего после подключения очередного сервиса.
- include на домен без SPF-записи. Обычно это опечатка в имени. Такой механизм ломает разбор целиком.
- Пример из документации вместе с чужим доменом. Строка вроде
include:_spf.example.com, скопированная как есть, синтаксически безупречна и проходит проверку, но разрешает отправку чужой инфраструктуре. Значения для include берите из документации своего сервиса, а не из статей: они меняются. - Ошибка в адресе. Маска
/33вip4, IPv6-адрес вip4, адрес без последнего октета. Получатель вернёт permerror. - include сервиса, которым вы больше не пользуетесь. Тратит лимит и оставляет право отправки тому, у кого его быть не должно.
- Механизм ptr или запись без all. Первый устарел, а без второго запись почти ничего не запрещает.
- Длинная запись одной строкой. Одна строка TXT вмещает 255 символов. Запись длиннее делят на несколько строк в кавычках, и получатель склеивает их без пробелов, поэтому пробел между механизмами должен остаться внутри одной из строк.
Две SPF-записи на одном домене
Это самая частая поломка, и синтаксис тут ни при чём. Стандарт разрешает домену ровно одну запись, начинающуюся с v=spf1. Если их две, проверка возвращает permerror, и SPF перестаёт работать полностью.
Обычно появляются они так. Настроили почту через хостинг, тот добавил запись. Потом подключили сервис рассылок, в его инструкции написано «добавьте TXT-запись», и вторая ложится рядом с первой. По отдельности обе выглядят правильными.
Лечится объединением в одну строку: все include из обеих записей переносятся в одну, дубли убираются, all остаётся один. Результат перед публикацией можно вставить во вкладку «Текст записи» и убедиться, что лимит запросов соблюдён.
Как выглядит правильная запись
Для домена, который отправляет почту только через собственный сервер:
v=spf1 mx -allДля Google Workspace вместе с сервисом рассылок:
v=spf1 include:_spf.google.com include:spf.example-esp.com ~allЗапись публикуется TXT-записью на корне домена (имя @). Поддомены её не наследуют. Если рассылки уходят с mail.example.com, для него нужна отдельная запись.
Отправитель не прошёл проверку SPF: что это значит
Формулировку «не прошёл проверку SPF» отдают почтовые сервисы, когда IP-адрес, с которого пришло письмо, не перечислен в SPF-записи домена отправителя. Получатель сделал ровно то, что ему велели: сверил адрес со списком и не нашёл совпадения.
С легитимной почтой так бывает по трём причинам.
Чаще всего подключили новый сервис рассылок, CRM или биллинг, а в SPF-запись его не внесли. Сервис отправляет со своих серверов, домен их не авторизовал, и проверка падает.
Бывает, что превышен лимит в десять DNS-запросов. Тогда проверка возвращает permerror, и это тоже засчитывается как непрохождение.
И наконец, письмо могли переслать. Пересылка ломает SPF по устройству протокола: конверт остаётся вашим, а отправляет уже чужой сервер. Здесь ничего не сломано и чинить нечего, выручает подпись DKIM, которая обычно переживает пересылку.
Различить эти случаи можно за минуту. Вставьте домен в форму выше: она раскроет цепочку include и посчитает запросы. Если сервиса, которым вы пользуетесь, в цепочке нет, это первый случай. Если счётчик у десяти или выше, второй.
Отдельно про «для домена не настроена SPF-запись». Это другая ошибка: там записи нет вовсе, а здесь она есть и не сошлась. Собрать запись с нуля можно в генераторе SPF-записи.
SPF, DKIM и DMARC
От подделки SPF в одиночку не защищает. Злоумышленник проходит SPF со своим доменом в конверте, а в поле From пишет ваш, и получатель видит ваш адрес. DMARC закрывает этот разрыв выравниванием: домен из From должен совпасть с доменом, прошедшим SPF или подпись DKIM. Поэтому три записи настраивают вместе, по шагам это разобрано в инструкции по SPF, DKIM и DMARC. Подпись проверяется в проверке DKIM, политика в проверке DMARC.
Чего проверка не покажет
Синтаксически правильная запись бывает неверной по сути. Мы не знаем, какими сервисами вы пользуетесь, и не заметим ни лишнего include от брошенного сервиса, ни отсутствующего от только что подключённого. Это видно только по агрегированным отчётам DMARC: в них перечислены реальные источники, отправлявшие почту от вашего домена, с результатом SPF для каждого. Расхождение между этим списком и записью и есть настоящая ошибка конфигурации.
Поэтому запись стоит перепроверять после каждого изменения и раз в несколько месяцев без всякого повода. Содержимое чужих include меняется, когда провайдер добавляет серверы, и запись, которая вчера укладывалась в лимит, сегодня может его превысить.
Источники
Частые вопросы про SPF
Что почитать дальше
Домен настроен, а письма всё равно не доходят?
Половина проблем с доставляемостью живёт не в DNS, а в самой базе: несуществующие адреса, спам-ловушки, одноразовые ящики. uChecker проверяет базу до отправки, первые 100 адресов бесплатно.
Проверить базу