Почему форма на сайте не отправляет письмо

Когда форма на сайте перестаёт отправлять письмо, первое желание — сразу смотреть SMTP. Но на практике причина часто оказывается проще: не проходит валидация, JavaScript не отправляет запрос, письмо уходит в спам или сервер блокирует mail(). Поэтому диагностику лучше вести сверху вниз, без прыжков между гипотезами.

Сначала проверить саму форму

Откройте форму в браузере и отправьте тестовые данные. Важно смотреть не только сообщение на странице, но и вкладку Network в инструментах разработчика. Если запрос вообще не уходит, проблема не в почте.

  • кнопка отправки не заблокирована JavaScript-ошибкой;
  • форма отправляется на правильный URL;
  • метод POST соответствует обработчику;
  • сервер возвращает ожидаемый HTTP-код;
  • в ответе нет скрытой ошибки PHP или фреймворка.

Частый пример: после правки верстки у поля меняется name, а backend всё ещё ждёт старое имя. Визуально форма выглядит нормально, но обработчик получает пустые данные.

<input type="text" name="phone">

Если обработчик ожидает contact_phone, такое поле просто не попадёт в нужную переменную. Поэтому перед SMTP стоит проверить входящие данные.

Yii::info(Yii::$app->request->post(), 'contact-form');

Проверить валидацию

Форма может не отправлять письмо, потому что модель не проходит валидацию. Пользователь при этом иногда видит общее сообщение, а конкретная ошибка остаётся в логах или вообще не выводится.

if (!$model->validate()) {
    Yii::error($model->errors, 'contact-form');
    return false;
}

На этом этапе полезно временно вывести ошибки в лог. Не в браузер на рабочем сайте, а именно в лог приложения. Так можно увидеть, какое поле ломает отправку.

Проверить обработчик отправки

В Yii2 отправка письма обычно идёт через mailer. Минимальная проверка выглядит так:

$sent = Yii::$app->mailer
    ->compose()
    ->setFrom(['no-reply@example.ru' => 'Site'])
    ->setTo('manager@example.ru')
    ->setSubject('Тестовое сообщение')
    ->setTextBody('Проверка отправки формы')
    ->send();

Yii::info(['sent' => $sent], 'mail');

Если send() возвращает false, нужно смотреть конфигурацию mailer и транспорт. Если возвращает true, это ещё не значит, что письмо дошло до адресата. Это значит, что приложение передало письмо дальше.

mail() или SMTP

На старых проектах всё ещё встречается отправка через стандартную функцию mail(). Она может работать нестабильно: письмо принимается локальным сервером, но дальше теряется, попадает в спам или отклоняется из-за SPF и DKIM.

Для рабочих форм лучше использовать SMTP с авторизацией. Пример настройки для Yii2:

'mailer' => [
    'class' => 'yii\swiftmailer\Mailer',
    'useFileTransport' => false,
    'transport' => [
        'class' => 'Swift_SmtpTransport',
        'host' => 'smtp.example.ru',
        'username' => 'no-reply@example.ru',
        'password' => 'password',
        'port' => '465',
        'encryption' => 'ssl',
    ],
],

Отдельно нужно проверить useFileTransport. В dev-окружении его часто включают, чтобы письма складывались в файлы. Если такой конфиг случайно попадает на рабочий сайт, форма “отправляет” письма только в runtime/mail.

ls -la runtime/mail

Логи сервера и приложения

Если в браузере всё выглядит нормально, следующий шаг — логи. В Yii2 это runtime/logs/app.log. На сервере дополнительно смотрят error.log веб-сервера и системные почтовые логи, если есть доступ.

tail -n 150 runtime/logs/app.log
tail -n 150 /var/log/nginx/error.log
tail -n 150 /var/log/mail.log

В логах обычно видно одну из типовых причин: неверный пароль SMTP, блокировка порта, ошибка SSL, неправильный отправитель или исключение в шаблоне письма.

Проверить адрес отправителя

Письмо от формы не должно уходить с адреса пользователя. Если посетитель ввёл gmail.com, а сайт пытается отправить письмо “от него”, почтовые серверы могут отклонить такое сообщение. Лучше ставить отправителем доменный адрес, а email пользователя добавлять в Reply-To.

Yii::$app->mailer
    ->compose()
    ->setFrom(['no-reply@example.ru' => 'Форма сайта'])
    ->setReplyTo($model->email)
    ->setTo('manager@example.ru')
    ->setSubject('Заявка с сайта')
    ->setHtmlBody($body)
    ->send();

DNS: SPF, DKIM, DMARC

Когда приложение письмо отправляет, но оно не приходит, нужно проверить DNS-записи домена. Особенно это важно, если почта находится на внешнем сервисе, а сайт расположен на другом хостинге.

  • SPF разрешает серверу отправлять письма от имени домена;
  • DKIM подписывает письмо и повышает доверие к отправителю;
  • DMARC задаёт политику обработки писем, не прошедших проверку;
  • MX-записи не отвечают за отправку формы напрямую, но помогают понять общую почтовую схему.

Короткий порядок диагностики

  1. Проверить отправку запроса в браузере.
  2. Проверить входящие POST-данные.
  3. Проверить ошибки валидации.
  4. Проверить useFileTransport.
  5. Отправить простое тестовое письмо из кода.
  6. Посмотреть app.log и error.log.
  7. Проверить SMTP-доступы, порт и шифрование.
  8. Проверить SPF, DKIM и папку “Спам”.

Главное — не начинать с полной переделки формы. Обычно достаточно найти конкретное место, где цепочка обрывается: браузер, backend, mailer, SMTP или почтовый ящик получателя.

Комментарии (0)

Пока нет комментариев. Будьте первым!