Avatar ·

Функция mail() в PHP не отправляет письма: причины и решение

Всем привет! Я начинающий PHP-разработчик, и у меня возникла серьёзная проблема с отправкой email через функцию mail(). На локальном сервере (OpenServer) всё работало отлично — письма приходили моментально. Но когда я залил проект на реальный хостинг, функция перестала работать: она возвращает false, и никаких ошибок в логах нет. Вот мой код: ```php ``` Письмо не доходит ни на один почтовый ящик — ни на Gmail, ни на Яндекс. При этом на локальном сервере всё работало идеально. Я проверил: 1. Права на файлы — выставлены 755. 2. PHP-код без синтаксических ошибок. 3. В php.ini параметр SMTP настроен на localhost. Подскажите, пожалуйста, в чём может быть проблема? Может быть, нужно что-то дополнительно настраивать на хостинге? Или есть какие-то подводные камни с кодировкой? Заранее спасибо за помощь! <<>>

Основные причины неработоспособности mail() на реальном хостинге

Проблема, с которой вы столкнулись, — одна из самых частых среди начинающих PHP-разработчиков. Функция mail() на реальном сервере ведёт себя иначе, чем на локальном, из-за различий в настройках почтовой системы. Давайте разберём основные причины и их решения.

1. Проверьте, установлен ли почтовый сервер (MTA)

На локальном сервере (OpenServer, XAMPP) часто используется встроенный эмулятор почты (например, sendmail.exe). На реальном хостинге PHP просто вызывает системную команду sendmail, но сам почтовый сервер может быть не установлен или отключён. Решение: обратитесь в поддержку хостинга — обычно они предоставляют готовый SMTP-сервер (например, mail.example.com).

2. Используйте SMTP-авторизацию вместо mail()

Функция mail() не поддерживает SMTP-авторизацию (логин/пароль). На современных хостингах это обязательное требование. Лучшее решение: используйте библиотеку PHPMailer или SwiftMailer.

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';

$mail = new PHPMailer(true);

try {
    // Настройки SMTP
    $mail->isSMTP();
    $mail->Host       = 'smtp.yandex.ru';        // SMTP сервер
    $mail->SMTPAuth   = true;
    $mail->Username   = 'user@yandex.ru';        // Логин
    $mail->Password   = 'password';              // Пароль
    $mail->SMTPSecure = 'ssl';                   // или 'tls'
    $mail->Port       = 465;                     // 587 для TLS

    // Отправитель и получатель
    $mail->setFrom('user@yandex.ru', 'Администратор');
    $mail->addAddress('user@example.com', 'Получатель');

    // Контент
    $mail->isHTML(true);
    $mail->Subject = 'Тестовое письмо';
    $mail->Body    = '<h1>Привет!</h1><p>Это тест.</p>';
    $mail->AltBody = 'Привет! Это тест.';

    $mail->send();
    echo 'Письмо отправлено!';
} catch (Exception $e) {
    echo "Ошибка: {$mail->ErrorInfo}";
}
?>

3. Проверьте заголовки и кодировку

Даже если вы используете mail(), заголовки должны быть корректными. Добавьте обязательные заголовки MIME-Version и Content-Transfer-Encoding:

$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/plain; charset=utf-8\r\n";
$headers .= "From: admin@mysite.com\r\n";
$headers .= "Reply-To: admin@mysite.com\r\n";

4. Проверьте логи ошибок PHP

Добавьте в начало скрипта:

ini_set('display_errors', 1);
error_reporting(E_ALL);

И проверьте файл error_log в корне сайта. Там могут быть сообщения вида: "Mail delivery failed: connection to localhost:25 refused".

5. Альтернативное решение: используйте SMTP через встроенные функции

Если библиотеки недоступны, можно настроить отправку через fsockopen() или stream_socket_client(), но это сложнее и менее надёжно. Рекомендую всё же использовать PHPMailer.

Итог

  • Не используйте mail() на продакшене — это устаревший и ненадёжный метод.
  • Установите PHPMailer через Composer: composer require phpmailer/phpmailer.
  • Настройте SMTP через данные от хостинга или внешнего почтового сервиса (Yandex, Gmail, Mail.ru).
  • Всегда проверяйте ошибки через $mail->ErrorInfo.
<<>>

Дополнительный подход: использование встроенного SMTP через ini-настройки

Если вы не можете установить PHPMailer (например, на дешёвом хостинге без Composer), попробуйте настроить mail() через директивы php.ini или .htaccess. Однако это работает не на всех хостингах.

Настройка через .htaccess

php_value SMTP smtp.yandex.ru
php_value smtp_port 465
php_value sendmail_from admin@mysite.com

Настройка через php.ini (если есть доступ)

SMTP = smtp.yandex.ru
smtp_port = 465
sendmail_from = admin@mysite.com

Важные замечания

  • Этот метод не поддерживает авторизацию — многие SMTP-серверы требуют логин/пароль.
  • На хостингах с SELinux может быть заблокировано сетевое соединение из PHP.
  • Рекомендую всё же перейти на PHPMailer — это сэкономит часы отладки в будущем.

Если ни один из методов не работает, обратитесь в техподдержку хостинга — возможно, у них есть собственный SMTP-релей (например, mail.hosting.com), который нужно указать в настройках.