Отправка почты из Laravel: что нужно знать до начала
Разбираемся, как настроить отправку писем в Laravel 11 через SMTP, где хранить пароли, чем отличается queue от синхронной отправки и почему письма уходят в спам.

За полчаса вы соберёте рабочую отправку писем из Laravel 11: настроите SMTP-подключение, создадите класс письма, отправите первое сообщение и увидите его в почтовом ящике. Разберём и то, обо что новичок спотыкается сразу — почему письмо «отправилось», но не пришло, и куда вписывать пароль, чтобы он не утёк в git.
Что нужно иметь до начала
Прежде чем писать код, проверьте, что у вас есть.
- Laravel 11.x — команды и структура config-файлов ниже написаны под неё. В Laravel 9–10 всё близко, но с 9-й версии драйвер почты переехал с SwiftMailer на Symfony Mailer, поэтому старые примеры из интернета могут не подойти.
- PHP 8.2+ — минимум для Laravel 11.
- Доступ к SMTP-серверу. Это либо почтовый сервис (Mailgun, Postmark, Amazon SES, Яндекс 360, Mail.ru для бизнеса), либо ваш собственный сервер. Нужны хост, порт, логин и пароль.
- Для локальной разработки — Mailpit или MailHog*, чтобы ловить письма локально и не спамить реальные адреса.
* Mailpit — локальная «ловушка» для писем: приложение отправляет письмо на localhost, а Mailpit показывает его в веб-интерфейсе вместо реальной доставки. В Laravel Sail Mailpit уже включён в docker-compose.
Шаг 1. Настройте .env
Настройки почты Laravel читает из переменных окружения. Откройте файл .env в корне проекта и заполните блок MAIL_*:
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=YOUR_SMTP_LOGIN
MAIL_PASSWORD=YOUR_SMTP_PASSWORD
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="noreply@example.com"
MAIL_FROM_NAME="${APP_NAME}"
Порт и шифрование зависят от провайдера: 587 обычно идёт с tls, 465 — с ssl. Точные значения смотрите в документации вашего почтового сервиса, не подставляйте наугад.
Проверка: файл .env должен быть в .gitignore (в стандартном Laravel он там уже есть). Пароль от почты не должен попадать в репозиторий никогда.
Почему не стоит хардкодить пароль в config/mail.php
Файлы в config/ попадают в git. Все значения там читаются через env() именно для того, чтобы секреты жили в .env, а не в коде. Если вписать пароль прямо в конфиг, он окажется в истории репозитория, откуда его уже не вычистить одним коммитом.
Шаг 2. Создайте класс письма
Laravel описывает письма отдельными классами (Mailable). Сгенерируйте заготовку командой:
php artisan make:mail WelcomeMail
Появится файл app/Mail/WelcomeMail.php. Приведите его к такому виду:
<?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
{
return new Content(
view: 'emails.welcome',
);
}
}
Обратите внимание: методы envelope() и content() — это синтаксис Laravel 9+. Если вы читаете старый гайд, где всё делается в методе build(), — это версия 8 и раньше, в 11-й такой подход считается устаревшим.
Проверка: файл создан, класс наследует Mailable, ошибок в редакторе нет.
Шаг 3. Создайте шаблон письма
В content() мы указали emails.welcome — значит, Laravel ищет файл resources/views/emails/welcome.blade.php. Создайте его:
<h1>Здравствуйте, {{ $userName }}</h1>
<p>Спасибо, что зарегистрировались.</p>
Переменная $userName — это публичное свойство из конструктора Mailable. Laravel автоматически прокидывает публичные свойства класса в шаблон.
Проверка: файл лежит по пути resources/views/emails/welcome.blade.php.
Шаг 4. Отправьте письмо
Отправка идёт через фасад Mail. Проще всего проверить в маршруте или командой. Например, в routes/web.php:
use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeMail;
Route::get('/test-mail', function () {
Mail::to('recipient@example.com')->send(new WelcomeMail('Иван'));
return 'Письмо отправлено';
});
Откройте /test-mail в браузере.
Проверка: при локальной разработке с Mailpit письмо появится в его веб-интерфейсе (по умолчанию http://localhost:8025). На реальном SMTP письмо придёт на указанный адрес в течение минуты. Если страница вернула «Письмо отправлено», но письма нет — переходите к разделу об ошибках.
«Письмо отправилось» в Laravel означает, что фреймворк без ошибок передал сообщение SMTP-серверу. Дошло ли оно до ящика получателя — это уже зона ответственности почтового сервера и антиспам-фильтров, о которой Laravel ничего не знает.
Синхронная отправка или очередь
По умолчанию Mail::send() отправляет письмо прямо в текущем запросе. Пользователь ждёт, пока SMTP-сервер ответит — а это может быть и полсекунды, и несколько секунд. На форме регистрации это заметно.
Решение — очередь. Если Mailable использует трейт Queueable (он уже подключён в заготовке), достаточно заменить send на queue:
Mail::to('recipient@example.com')->queue(new WelcomeMail('Иван'));
Тогда письмо попадёт в очередь, а отправкой займётся воркер в фоне. Но для этого нужен настроенный драйвер очередей (QUEUE_CONNECTION в .env) и запущенный php artisan queue:work. Настройка очередей — отдельная тема, здесь важно знать, что выбор есть и когда он нужен.
| Способ | Когда подходит | Цена |
|---|---|---|
send() | Разовые письма, консольные команды, отладка | Пользователь ждёт ответа SMTP в рамках запроса |
queue() | Письма в ответ на действия пользователя (регистрация, заказ) | Нужен запущенный воркер и драйвер очередей; письмо уходит с задержкой |
Если не получилось
Пять частых сценариев, с которыми сталкиваются в первый день.
- Connection could not be established with host / Connection timed out. Laravel не достучался до SMTP: неверный хост, порт закрыт файрволом или провайдер хостинга блокирует исходящие соединения на 25/587. Проверьте
MAIL_HOSTиMAIL_PORT, уточните у хостинга, открыт ли порт. - Expected response code "250" but got code "535" (Authentication failed). Неверный логин или пароль. У Gmail и ряда сервисов обычный пароль не подойдёт — нужен пароль приложения, который создаётся отдельно в настройках безопасности аккаунта.
- Изменил .env, а ничего не поменялось. Laravel кеширует конфиг. Выполните
php artisan config:clear(а если раньше делалиconfig:cache— зановоconfig:cache). Без этого приложение читает старые значения. - View [emails.welcome] not found. Опечатка в пути шаблона или файл лежит не в
resources/views/emails/. Имя вcontent()использует точку как разделитель папок:emails.welcome=emails/welcome.blade.php. - Письмо ушло без ошибок, но не пришло. Проверьте папку «Спам». Часто причина — отсутствие SPF, DKIM и DMARC для домена отправителя или отправка с адреса на чужом домене. Об этом ниже.
Почему письма уходят в спам
Это не проблема Laravel — это правила почтовых провайдеров, но новичка она бьёт первой. Три вещи, без которых письма с большой вероятностью попадут в спам или не дойдут:
- SPF — DNS-запись, которая говорит, какие серверы вправе слать почту от имени вашего домена.
- DKIM — цифровая подпись писем, подтверждающая, что письмо не подделано.
- DMARC — политика, что делать с письмами, не прошедшими SPF и DKIM.
Если вы отправляете через готовый сервис (Mailgun, Postmark, SES, Яндекс 360), они дают точные значения этих DNS-записей и инструкцию по их добавлению. Настраиваются они на стороне DNS домена, а не в коде Laravel. Отправка с адреса вроде noreply@gmail.com через сторонний SMTP почти гарантированно уйдёт в спам — используйте адрес на своём домене, для которого настроены записи.
Что делать дальше
Базовая отправка работает — теперь стоит:
- подключить очереди, чтобы письма не тормозили запросы: раздел Queues в документации Laravel;
- перейти с локального Mailpit на реальный транзакционный сервис и настроить SPF/DKIM/DMARC для домена;
- в проде следить за долей писем, уходящих в спам, и за bounce-уведомлениями — многие сервисы показывают это в своей панели;
- вынести адреса и темы писем в отдельные Mailable-классы, не собирая HTML прямо в контроллере.
Мотивационное письмо и эссе: Поступление, стипендии, гранты, обмен
Спросить за 25 ₽Источники: Laravel 11 — Mail (официальная документация), Mailpit — репозиторий на GitHub
Частые вопросы
Как отправить письмо без реальной доставки во время разработки?
У меня Laravel 10, примеры с envelope() и content() подойдут?
Изменил настройки в .env, но письма всё равно уходят со старыми — почему?
Письмо отправилось без ошибок, но не пришло. Что проверять?
Обязательно ли использовать очередь для отправки писем?
Можно ли отправлять письма через Gmail обычным паролем от аккаунта?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.