SMTP Яндекса в Laravel и подтверждение подписки: подводные камни

0

Почта ♡

SMTP Яндекса в Laravel и подтверждение подписки: подводные камни
Письмо ушло —
и слава богу ♡

Для рассылки мне нужна была почта, которая не уходит в спам и не требует отдельного сервиса за деньги. Проще всего было взять обычный ящик Яндекса. Настройка заняла пять минут, а потом ещё час ушёл на ошибку "535 5.7.8", при которой пароль вроде бы верный, а доступа нет. Складываю всё в одну статью, чтобы ты этот час не потеряла.

Настройки в .env

Для Яндекса нужен SMTP-сервер на порту 465 с шифрованием. В свежем Laravel это задаётся схемой "smtps":

MAIL_MAILER=smtp
MAIL_HOST=smtp.yandex.ru
MAIL_PORT=465
MAIL_SCHEME=smtps
MAIL_USERNAME=ваш-ящик@yandex.ru
MAIL_PASSWORD=пароль-приложения
MAIL_FROM_ADDRESS="ваш-ящик@yandex.ru"

Адрес отправителя должен совпадать с логином, иначе Яндекс письмо не примет. И обрати внимание: "MAIL_PASSWORD" это не пароль от почты, а специальный пароль приложения. Если вписать обычный, будет та самая ошибка, о которой ниже.

Ошибка 535: у пользователя нет доступа

Проверять отправку лучше одной командой, без форм и очередей, чтобы не гадать, что из них сломалось:

php artisan tinker --execute 'Mail::raw("Проверка почты", fn ($m) => $m->to("me@example.com")->subject("Тест"));'

Получаю в ответ:

535 5.7.8 Error: authentication failed: This user does not have access rights to this service

Пароль правильный, логин правильный, а почта не пускает. Начинается любимая игра «что я сделала не так». Причина оказалась в самом ящике Яндекса: доступ сторонних программ там по умолчанию отключён. Лечится в настройках почты: «Почтовые программы», включить доступ по протоколу IMAP и отметить «Пароли приложений и OAuth-токены». Сам пароль приложения создаётся отдельно в Яндекс ID, в разделе «Безопасность», для типа «Почта».

Как устроено подтверждение подписки

Подписчик получает письмо со ссылкой, а адрес становится активным только после клика. У каждого свой токен. Повторное письмо с подтверждением я не отправляю чаще чем раз в 10 минут, чтобы форму нельзя было использовать для рассылки спама другим людям. А если адрес уже подтверждён, ответ не меняется, чтобы по нему нельзя было вычислить, кто подписан.

Про сам путь «письмо, ссылка, страница» и про то, как тест нашёл в нём дыру, читай в статье про подписку.

Рассылка новых записей без очередей

Отправлять письма о новых записях можно без сложных очередей и Redis. В планировщике стоит команда раз в пять минут:

Schedule::command('subscribers:notify')->everyFiveMinutes()->withoutOverlapping();

Чтобы одна запись не разошлась дважды (представь, как это выглядит для подписчика), она «занимается» одним обновлением поля в базе:

$claimed = DiaryPost::query()->whereKey($post->id)->whereNull('notified_at')->update(['notified_at' => now()]);

if ($claimed === 0) {
    continue;
}

Если два процесса возьмут одну запись, обновление сработает только у первого, а второй получит ноль и пойдёт дальше. Записи с датой в будущем дожидаются своего времени сами: планировщик проверяет, вышла ли запись, и только тогда рассылает письма. Именно так у меня работают отложенные публикации.

Лимиты Яндекса

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

Что стоит запомнить

Ошибка 535 почти всегда про настройки самого ящика, а не про твой код. Проверяй отправку отдельной командой, до того как в дело вступят формы и очереди. И держи пароль приложения только в ".env", а не в репозитории: гитхаб такое не прощает. Как проект выкладывается на сервер и где хранится ".env", я описала в статье про деплой Laravel.

Комментарии

Буду рада вашим мыслям, идеям и вопросам!
Давайте обсуждать ♡

Пока никто не написал.
Станьте первым! ♡

Поддержать проект

Угостить кофе по СБП

Перевод через Систему быстрых платежей, сумма любая. Спасибо, что вы здесь ♡

QR-код для перевода по СБП
Или другим способом
Дневник на почте

Подписаться на блог

Когда выйдет новая запись, я пришлю письмо со ссылкой. Без рассылок «просто так» и без спама. Отписаться можно одним нажатием.

Или следить в Telegram