Собственный домен

Безлимитные тестовые аккаунты на одном catch-all домене

Набору тестов, которому на каждый прогон нужен новый пользователь, на каждый прогон нужен и новый email-адрес, а почтовый провайдер, выдающий ящики по одному, для этого совершенно не подходит. Одна MX-запись превращает домен, которым вы владеете, в catch-all-ящик: любой адрес на нём работает, ни один не нужно создавать, и команда QA может сжигать по тысяче адресов в день, и никому не придётся ничего для этого разворачивать.

  • Средний
  • 11 мин на чтение
Десятки маленьких синих конвертов сыплются в широкую серую воронку, ведущую в серый почтовый ящик

Почему почтовый провайдер — неподходящая форма для QA

Испробованы все способы снабдить набор тестов email-адресами, и каждый течёт в своём месте:

ПодходВо что обходитсяГде ломается
Один общий ящик (qa@company.com)Настраивать нечего.Каждый тест читает почту любого другого теста. Первый же опрос нового прогона находит код из прошлого прогона. Параллельные прогоны невозможны.
Плюс-адресация (qa+run42@company.com)Настраивать нечего, если провайдер это поддерживает.Это всё равно один ящик: одна квота, один логин IMAP на всю команду, и форма регистрации, которая обрезает метку или вовсе отказывает +.
Ящик на каждого тестировщика от провайдераМесто на каждого и заявка на его создание.Никто не разворачивает ящик на каждый прогон теста. Тестировщики переиспользуют свой, и проблема общего ящика возвращается — просто по одному человеку за раз.
Catch-all-домен, направленный сюдаОдна DNS-запись, один раз.Ящик публичен для любого, кто знает адрес, а почта живёт 5 дней. Оба свойства нормальны для кода, который важен одиннадцать секунд; ни одно из них не годится для настоящей почты клиентов.

Четвёртая строка — это и есть тема этого руководства. Тот же самый механизм, на котором работают публичные одноразовые домены, — сервер, принимающий любой адрес на домене вместо списка ящиков, — применённый к имени, которым пользуетесь только вы.

Единственная DNS-запись

У вашего DNS-провайдера добавьте одну-единственную MX-запись на apex домена, которым вы владеете. Больше никаких записей, никакого TXT для доказательства чего-либо, никакого аккаунта на этом сайте:

MX-запись для домена10 smtp.grabmail.io

  1. Опубликуйте MX. Приоритет 10, указывает на smtp.grabmail.io. Удалите любые другие MX на домене — почта может доставляться только в одно место, а оставшаяся запись отправит часть писем куда-то ещё.
  2. Дождитесь DNS. Обычно минуты; иногда — TTL той записи, что стояла раньше. dig MX qa-example.com покажет, когда изменение вступило в силу.
  3. Отправьте одно письмо на любой адрес на этом домене. Именно первая доставка подключает домен: в этот момент сервер ищет MX, видит там себя и принимает письмо. С этого момента любой адрес на домене становится ящиком.
A sendermail for your domainYour DNSMX 10 smtp.grabmail.ioGrabMailchecks the MX itselfThe only thing you publishand keeps the messageNo account, no token, no verification page. The record is the proof.
Одна MX-запись — вся настройка целиком. Отправляющий сервер спрашивает у DNS, куда идёт почта для домена, и в ответ получает сервер, который принимает на нём любой адрес.

Схема именования, которая говорит, кто создал ящик

Раз любой адрес действителен, часть до @ свободна для того, чтобы нести информацию, — а в два часа ночи, с упавшим прогоном и открытым ящиком, вам захочется, чтобы она её несла. Три части, соединённые дефисами, в таком порядке:

ЧастьПримерЧто это даёт
Кто создалsignup, reset, e2e, aliceОдного взгляда достаточно, чтобы понять, какому сценарию или какому человеку принадлежит ящик.
Какой прогон1234567890 (id прогона CI), имя ветки, датаУ всех ящиков одного прогона пайплайна общий токен, по которому можно искать.
Случайность3f9a1c2eВосемь символов. Именно эта часть не даёт двум тестам, двум шардам или двум повторам делить один ящик.
Никогда: ничего настоящегоимя клиента, настоящий id пользователя, номер тикета, называющий клиентаЯщик публичен для любого, кто знает адрес. В адресе не должно быть ничего, что стоило бы знать постороннему.
tests/address.ts
// one helper, every runner: who made it, which run, and eight random characters
export const testAddress = (who: string, run = process.env.GITHUB_RUN_ID ?? 'local') =>
  `${who}-${run}-${crypto.randomUUID().slice(0, 8)}@qa-example.com`;

testAddress('signup');        // signup-1234567890-3f9a1c2e@qa-example.com

Чтение любого адреса — те же три вызова

Для собственного домена в API ничего не меняется. Тот же вызов списка писем, тот же вызов письма, то же удаление — без ключа на публичном уровне, и единственное, что отличается, — это домен в адресе:

получить список писем в ящике на собственном домене
$ curl -sG https://grabmail.io/api/v1/mailbox --data-urlencode "address=signup-1234567890-3f9a1c2e@qa-example.com"

А значит, любой помощник на этом сайте после изменения одной константы работает без переделок: фикстура Playwright, задача Cypress, модули Python и Node. Стоит знать три вещи, о которых на публичных доменах даже не приходится думать:

404 значит, что MX ещё не появился
Список писем отвечает 404 для домена, который здесь не обслуживается. На собственном домене это проблема DNS — запись ещё не распространилась или указывает не туда, — а не проблема API. Сначала проверьте dig MX.
Алиас работает и на вашем домене
У каждого ящика, на любом домене, есть второй адрес на отдельном домене, который доставляет в него почту, но не может её прочитать. Отдавайте его сайту, когда не хотите, чтобы тот мог открыть ящик; опрашивайте при этом собственный адрес.
Загруженный адрес читается постранично
Catch-all-адрес, собирающий возвраты или уведомления за целый день, может содержать больше одной страницы из 200. Передавайте next обратно как before, пока он не станет null.

Как сохранить тестовый домен пригодным к использованию

Собственный домен не состоит ни в одном чёрном списке одноразовой почты, и зачастую именно поэтому его и берут: тестируемое приложение отказывает grabmail.io и любому другому публичному домену — именно так, как и должно. Четыре привычки сохраняют это положение вещей:

  • Используйте выделенный доменqa-example.com, а не поддомен продакшена и не домен, на который пишут клиенты. Сервис принимает только регистрируемые домены (example.com, но никогда mail.example.com), и у тестового домена не должно быть никакой другой работы.
  • Не публикуйте его. Списки строятся из того, что появляется на публичных сайтах временной почты и в общих подборках адресов. У домена, который встречается только в вашем собственном наборе тестов, нет пути в такие списки.
  • Закройте его SPF и DMARC. Домен, который только принимает почту и не имеет SPF, — это домен, письмо от имени которого может подделать кто угодно; две записи закрывают эту дыру и ничего не стоят.
  • Не направляйте на него настоящую почту. В тот момент, когда staging-система отправляет уведомления клиентам на catch-all-адрес, публичный ящик начинает хранить данные клиентов. Тестовые домены — для тестовой почты.

Если приложение отказывает любому catch-all-домену — некоторые проверки на мошенничество так и делают, проверяя, принимается ли случайный адрес на домене, — есть платный пул ничем не примечательных доменов .com, которые держат подальше от списков, описанный на странице тарифов. В руководстве «Почему формы регистрации блокируют одноразовую почту» объясняется, что видит каждый тип проверки.

Для команды: один домен, много тестировщиков, много пайплайнов

Один catch-all-домен обслуживает всех, потому что различаться должна только часть до @, а она ничего не стоит. Команде нужна лишь договорённость о схеме именования выше и три небольших соглашения:

Префикс на каждый пайплайн и каждого человека
e2e-, nightly-, alice-. Поиск по префиксу в логе задания находит все ящики, которые оно создало; поиск по префиксу коллеги находит баг, которым он занимается.
Ничего общего, никогда
На домене нет «командного ящика» и нет фикстуры, выдающей фиксированный адрес. Если двум людям нужен один и тот же ящик, один просто присылает адрес другому.
Лимиты запросов действуют на клиента
Одно чтение в секунду на адрес, 1200 запросов в минуту на клиента — раннер CI — это один клиент, ноутбук — другой. Команда из десяти человек, одновременно запускающих наборы тестов, — это десять клиентов, а не один.

Действующие ограничения

Собственный домен получает точно такое же обслуживание, как и публичные, с теми же потолками. Ни один из них не настраивается, и ни один не представляет проблемы для набора тестов:

ОграничениеЗначениеЧто это значит для QA
Срок хранения5 дней на письмоКаждый прогон создаёт собственную почту; ничего никогда не читается из прошлой недели. Точные правила.
Вложения5 MB на письмоХватает на PDF со счётом или экспорт в CSV; письмо большего размера отклоняется ещё на этапе SMTP, так что отправитель об этом узнаёт.
Чтения1 в секунду на адрес, 1200 в минуту на клиентаДвадцать ящиков, опрашиваемых раз в секунду, с одного раннера. Сверх этого — 429 с Retry-After.
ПриватностьОтсутствует — прочитать может любой, кто знает адресСлучайная часть адреса, неопубликованный домен и никакой настоящей почты клиентов.
ОтправкаОтсутствуетДомен только принимает. Ваше приложение отправляет через собственного провайдера, как и в продакшене.

Прежде чем считать задачу закрытой

  • Выделенный регистрируемый домен с одной MX-записью: 10 smtp.grabmail.io, и никаких других MX.
  • Одно письмо отправлено на любой адрес на нём и считано обратно через API.
  • Опубликованы SPF и DMARC, чтобы никто не мог отправлять письма от имени домена.
  • Помощник для именования — кто, какой прогон, восемь случайных символов — используется в каждом наборе тестов.
  • Домен хранится в конфигурации окружения, а не в коде, скриншотах или тикетах.
  • На него не направлено ничто, что отправляет настоящую почту клиентам.

Дальше — уже написанные наборы тестов: Playwright с доменом в фикстуре, дисциплина, не привязанная к конкретному раннеру, и workflow для GitHub Actions с доменом в переменной.

Вопросы

Можно ли использовать поддомен, вроде test.company.com?

Нет — сервис принимает только регистрируемые домены (company.com или company.co.uk), потому что тот, кто контролирует домен, контролирует и любое имя под ним, а две стороны не должны иметь возможность делить пересекающиеся половины одного пространства имён. Зарегистрируйте недорогой выделенный домен для тестирования — это в любом случае более правильная практика.

Через сколько заработает MX-запись?

Как только DNS начнёт её отдавать, а это обычно минуты. Если раньше был другой MX, действует его TTL. Домен подключается первым же письмом, которое приходит после этого, — больше ничего происходить не должно, а dig MX покажет, когда запись заработала.

Это что-нибудь стоит?

Нет. Подключение домена, любой адрес на нём и API бесплатны, без аккаунта. Единственная платная вещь на этом сайте — пул доменов, которые держат подальше от чёрных списков одноразовой почты, для тех, кто не может использовать собственный домен.

Может ли кто-то ещё читать почту на моём домене?

Да, любой, кто знает адрес, — точно так же, как и на публичных доменах. Собственный домен меняет только угадываемость: его адреса стоят на имени, которым больше никто не пользуется. Случайные части адреса и неопубликованный домен делают угадывание практически невозможным; но приватным ящик от этого не становится — здесь этого не делает ничто.

Что происходит с почтой, отправленной на домен до того, как я его подключил?

Сюда ничего не доходит, пока MX не указывает сюда. Почта, отправленная, пока действовала старая запись, уходила на старый сервер либо возвращалась отправителю; почта, отправленная после переключения DNS, приходит и подключает домен.

Как отключить домен?

Удалите MX-запись. Новая почта перестаёт приходить сразу же; то, что уже лежит в ящиках, само истечёт в течение 5 дней. После этого о домене ничего не сохраняется.

Приложение отказывает и моему тестовому домену тоже. Что теперь?

Некоторые проверки на мошенничество отказывают любому домену, принимающему случайный адрес, — это catch-all-проверка, а не сверка со списком. Для таких случаев нужен домен, который ведёт себя как обычный почтовый провайдер, а именно это и даёт платный пул; в руководстве «Почему формы регистрации блокируют одноразовую почту» объясняется, с какой именно проверкой вы столкнулись.

Читать дальше

Попробуйте, пока свежо

Адрес — это один клик, без аккаунта и карты. Всё из этого руководства сразу заработает на нём.

С возвращением

Ваши ящики и ваши домены в одном месте.