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

К концу этой инструкции вы отправите первое письмо из Laravel через SMTP и увидите его во входящих (или в перехватчике вроде Mailtrap). На чистой настройке уйдёт 10–15 минут. Проверено на Laravel 11.x и Laravel 10.x — различия по почте между ними минимальны и отмечены отдельно.
Почта в Laravel устроена вокруг компонента Mail и драйверов транспорта. Вы описываете подключение в config/mail.php и .env, формируете класс письма (Mailable) и вызываете фасад Mail. Большинство проблем новичка — не в коде письма, а в настройке подключения и в кешировании.
Что нужно иметь до начала
- Установленный проект на Laravel 10.x или 11.x и доступ к терминалу в его корне (там, где лежит
artisan). - PHP 8.1+ для Laravel 10, PHP 8.2+ для Laravel 11.
- SMTP-доступ: хост, порт, логин и пароль. Для тестов удобно завести бесплатный ящик-песочницу (например, Mailtrap) — письма туда приходят, но реальным адресатам не уходят.
- Права на запись в файл
.envи на очистку кеша конфигурации.
Если реального SMTP пока нет, для самой первой проверки подойдёт драйвер log: письмо не отправится, но запишется в лог. Это отсекает вопрос «код виноват или почтовый сервер».
Шаг 1. Прописываем подключение в .env
Откройте .env в корне проекта и заполните блок почты. Значения ниже — пример для SMTP-песочницы, подставьте свои:
MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.example.com
MAIL_PORT=2525
MAIL_USERNAME=YOUR_SMTP_LOGIN
MAIL_PASSWORD=YOUR_SMTP_PASSWORD
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
Проверка: значения сохранены, вокруг адреса с пробелами или спецсимволами стоят двойные кавычки. Пустой MAIL_FROM_ADDRESS — частая причина ошибки при отправке, письмо без отправителя большинство серверов отклоняет.
Порт и шифрование должны совпадать
Здесь спотыкаются чаще всего. Порт и тип шифрования — это пара, а не два независимых параметра.
- Порт 587 — обычно
MAIL_ENCRYPTION=tls(STARTTLS). - Порт 465 — обычно
MAIL_ENCRYPTION=ssl. - Порт 25 или 2525 — часто без шифрования или tls, зависит от провайдера.
Если поставить порт 465 и tls, соединение зависнет и вывалится по таймауту. Точные требования смотрите в панели вашего почтового провайдера, а не угадывайте.
Шаг 2. Сбрасываем кеш конфигурации
Это тот шаг, из-за которого «я всё поменял, а ничего не изменилось». Если вы когда-либо запускали php artisan config:cache, Laravel читает настройки из закешированного файла, а не из .env. Правки в .env при этом игнорируются.
php artisan config:clear
Проверка: в терминале появится строка вроде Configuration cache cleared successfully. После этого Laravel снова читает .env напрямую.
Правило, которое экономит часы: правите.env— сразу выполняйтеconfig:clear. На проде подconfig:cacheлюбое изменение переменной окружения без пересборки кеша не подхватывается.
Шаг 3. Создаём класс письма
Mailable1 — это класс, описывающий одно письмо: тему, отправителя и содержимое. Сгенерируйте его командой:
php artisan make:mail WelcomeMail
Файл появится в app/Mail/WelcomeMail.php. Приведите его к такому виду (синтаксис Laravel 10.x/11.x с методами envelope и content):
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class WelcomeMail extends Mailable
{
use Queueable, SerializesModels;
// Данные, которые передаём в письмо
public function __construct(public string $userName)
{
}
public function envelope(): Envelope
{
return new Envelope(
subject: 'Добро пожаловать',
);
}
public function content(): Content
{
// Шаблон письма лежит в resources/views/emails/welcome.blade.php
return new Content(
view: 'emails.welcome',
);
}
}
Создайте шаблон resources/views/emails/welcome.blade.php:
<p>Здравствуйте, {{ $userName }}.</p>
<p>Ваш аккаунт создан.</p>
Проверка: оба файла на месте, имя view в классе (emails.welcome) через точку соответствует пути к blade-файлу.
Шаг 4. Отправляем письмо
Для теста удобно отправить прямо из tinker, не создавая маршрут:
php artisan tinker
И внутри tinker:
use App\Mail\WelcomeMail;
use Illuminate\Support\Facades\Mail;
Mail::to('test@example.com')->send(new WelcomeMail('Иван'));
Проверка: команда не выбросила исключение и вернула управление. Письмо должно появиться в вашей SMTP-песочнице через несколько секунд. Если используете драйвер log — проверьте storage/logs/laravel.log, там будет тело письма.
Ловушка с очередями
Трейт Queueable в классе письма сам по себе ничего не откладывает — письмо уходит синхронно. Но если вы вызвали Mail::to(...)->queue(...) или у вас Mailable реализует ShouldQueue, письмо кладётся в очередь. И тут новичок пишет: «tinker отработал без ошибок, а письма нет».
Причина: очередь по умолчанию (драйвер database или redis) требует запущенного воркера. Без него задание просто лежит в таблице.
- Для первых тестов держите
QUEUE_CONNECTION=syncв.env— тогда всё отправляется сразу. - Если очередь нужна, запустите воркер:
php artisan queue:work— и не закрывайте терминал.
Если не получилось
Пять ошибок, которые вы реально увидите, и что с ними делать.
| Что видите | Причина | Что делать |
|---|---|---|
Connection could not be established with host ... stream_socket_client(): Connection timed out | Неверный порт или шифрование, либо порт закрыт файрволом хостинга | Проверьте пару порт+encryption. Уточните у хостинга, открыт ли исходящий SMTP |
Expected response code "250" but got code "535" ... Authentication failed | Неверный логин или пароль SMTP | Перепроверьте MAIL_USERNAME и MAIL_PASSWORD. Для Gmail нужен пароль приложения, не обычный |
Изменил .env, ничего не поменялось | Активен кеш конфигурации | php artisan config:clear |
Address in mailbox given [] does not comply with RFC 2822 или письмо без From | Пустой MAIL_FROM_ADDRESS | Заполните адрес отправителя в .env, сбросьте кеш |
| Ошибок нет, письма нет | Письмо ушло в очередь, воркер не запущен | Поставьте QUEUE_CONNECTION=sync или запустите php artisan queue:work |
Если ничего не помогает, временно переключите MAIL_MAILER=log. Появилось письмо в логе — код и Mailable в порядке, проблема в SMTP. Не появилось — ищите ошибку в коде отправки или в кеше конфига.
Что делать дальше
Первое письмо ушло — дальше стоит:
- Вынести отправку в очередь через
ShouldQueue, чтобы медленный SMTP не тормозил HTTP-ответ пользователю, и настроить воркер под supervisor на проде. - Настроить SPF, DKIM и DMARC на домене отправителя — без них письма с реальных адресов уходят в спам. Это настройка DNS, а не Laravel.
- Посмотреть на драйвер
failoverвconfig/mail.php, если нужна отказоустойчивость между несколькими SMTP.
Локализация писем и вложения — отдельная тема, здесь мы довели дело только до первого доставленного письма.
Мотивационное письмо и эссе: Поступление, стипендии, гранты, обмен
Спросить за 25 ₽Источники: Laravel Documentation — Mail, Laravel Documentation — Queues
Частые вопросы
У меня другая версия Laravel, синтаксис Mailable отличается — что делать?
Письмо отправляется, но приходит в спам. Это баг Laravel?
Можно ли отправлять почту вообще без SMTP-сервера?
Поменял .env, но Laravel упорно использует старые настройки почты. Почему?
Gmail не пускает по логину и паролю, ошибка 535. В чём дело?
Отправка тормозит HTTP-запрос на несколько секунд. Как ускорить?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.