Функция mail() в PHP не отправляет письма: причины и решение
Основные причины неработоспособности 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), который нужно указать в настройках.