WordPress отказывается отправлять почту, "...ваш хостинг мог отключить функцию mail()"
Недавно я добавил раздел комментариев на свой сайт и попытался настроить отправку email-уведомлений. Похоже, что уведомления не отправляются при появлении новых комментариев.
Чтобы проверить, может ли PHP отправлять письма, я попробовал сбросить пароль (так как новый пароль должен прийти по почте), и получил сообщение:
Письмо не может быть отправлено. Возможная причина: ваш хостинг мог отключить функцию mail()
Я проверил все галочки в Настройки -> Обсуждение, и email указан верно, так что проблема не в настройках. Я попробовал создать PHP файл и отправить письмо используя mail()
, и оно успешно отправилось. Так что, должно быть, что-то странное происходит именно с WordPress.
Есть какие-нибудь идеи?

Пошагово: сначала найдите файл, в котором появляется сообщение об ошибке. Я использую Notepad++ и команду CTRL + F для поиска по файлам. Хорошая идея — искать только первые несколько слов сообщения об ошибке, так как некоторые сообщения могут быть составными.
Ваше сообщение об ошибке появляется в файле wp-login.php
и, к счастью, только там. Давайте разберёмся, почему может возникать эта ошибка.
if ( $message && !wp_mail($user_email, $title, $message) )
Здесь два условия. $message
должен быть true (не пустой строкой, не false, не null и т. д.). И wp_mail()
не должен возвращать false.
На строку выше есть фильтр $message = apply_filters('retrieve_password_message', $message, $key);
, так что возможно, что плагин (или тема) использует этот фильтр и возвращает значение, которое не является true (пустая строка, false, null и т. д.).
Но гораздо проще проверить, работает ли wp_mail()
. Напишите небольшой плагин для отправки тестового письма себе:
<?php
/**
* Plugin Name: Stackexchange Testplugin
* Plugin URI: http://yoda.neun12.de
* Description: Отправьте мне тестовое письмо
* Version: 0.1
* Author: Ralf Albert
* Author URI: http://yoda.neun12.de
* Text Domain:
* Domain Path:
* Network:
* License: GPLv3
*/
namespace WordPressStackexchange;
add_action( 'init', __NAMESPACE__ . '\plugin_init' );
function plugin_init(){
$to = 'ваш-email@ваш-домен.tld';
$subject = 'Тестовое письмо';
$message = 'FooBarBaz Тестовая почта работает';
wp_mail( $to, $subject, $message );
}
(Это код для PHP5.3. Если у вас PHP5.2, удалите пространства имён.)
Плагин должен отправить тестовое письмо сразу после активации. Если нет, попробуйте открыть какую-нибудь страницу в админке (например, консоль).
Если тестовое письмо не приходит, скорее всего, у вас проблема с wp_mail()
. Включите отладку:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', true );
@ini_set( 'display_errors',1 );
Добавьте этот код в ваш wp-config.php
и попробуйте снова отправить тестовое письмо. Теперь вы должны увидеть сообщения об ошибках, а также они будут записаны в wp-content/debug.log
(журнал отладки может сильно увеличиться, если есть другие ошибки от плагинов или тем).
На этом этапе у вас будет достаточно информации, чтобы понять, работает ли wp_mail()
, и если нет — почему. Если wp_mail()
работает корректно и тестовое письмо пришло, вернитесь к началу и выясните, почему $message
не является true.
Если у вас проблемы с wp_mail()
, учтите, что wp_mail()
не использует PHP-функцию mail()
. WordPress использует PHP-класс (PHPMailer). Возможно, вам просто нужен плагин для использования SMTP вместо sendmail. Или проблема в другом месте. Мы не знаем. Вам придётся разбираться.

Да, я попытался разобраться в ядре, и это привело меня к PHPMailer, и он действительно использует php-функцию mail()
. По крайней мере, в некоторых случаях (см. строку 732 в файле wp-includes/class-phpmailer.php
. У меня сейчас нет доступа к FTP, но я попробую ваши предложения, как только смогу. Уверен, это должно привести меня к решению. Большое спасибо!

Я протестировал wp_mail()
, и, кажется, всё работает нормально — я получил письмо, как и ожидалось. Однако WordPress всё ещё не отправлял письма с комментариями/сбросом пароля, и в лог-файле ничего не появлялось (он даже не создавался). Поэтому я попробовал установить SMTP-плагин для почты и настроил новый почтовый аккаунт для WordPress. Теперь всё работает, но я всё равно не понимаю, почему раньше отправка не работала. Спасибо!

Это очень раздражающее сообщение об ошибке, так как оно может означать множество различных проблем, и при этом не раскрывает реальную ошибку (которая часто подавляется в других частях кода).
Эта ошибка появляется, когда функция wp_mail()
возвращает false, что в свою очередь может произойти, если phpmailer->Send()
возвращает false или вызывает исключение.
Как отображать предупреждения от PHP-функции mail()
Они обычно подавляются по умолчанию, но, к сожалению, WordPress их никогда не перехватывает. Чтобы показать их, просто удалите знаки @
из строк @mail(...
в файле wp-includes/class-phpmailer.php
в функции mailPassthru()
:
if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
$rt = @mail($to, $this->encodeHeader($this->secureHeader($subject)), $body, $header);
} else {
$rt = @mail($to, $this->encodeHeader($this->secureHeader($subject)), $body, $header, $params);
}
Как выявить другие возможные причины:
Добавьте одну строку в конец функции
wp_mail()
в файле/wp-includes/pluggable.php
:// Отправка! try { return $phpmailer->Send(); } catch ( phpmailerException $e ) { //------------- Эта следующая строка — та, которую нужно добавить ------------------- if (WP_DEBUG) echo '<pre>' . esc_html(print_r($e, TRUE)) . '</pre>'; return false; }
Это выведет полные детали исключения, включая место, где оно было вызвано. К сожалению, иногда там содержится бесполезное сообщение: "Не удалось инициализировать почтовую функцию". Да, спасибо, WordPress, это действительно помогло.
Изучив исключение, вы можете найти номер строки с ошибкой и, возможно, отследить её в коде, чтобы определить реальную причину.
Удачи. Надеюсь, в будущем WordPress улучшит обработку ошибок при отправке электронной почты.

У меня была такая же проблема с сервером Ubuntu на Amazon EC2. Я столкнулся с проблемой при использовании ссылки для сброса пароля, а также другие уведомления по электронной почте не работали.
Вот решение, которое сработало у меня. WordPress использует функцию wp_mail()
для отправки почты, которой необходим класс PHPMailer
, использующий почтовый сервер PHP, расположенный в /usr/sbin/sendmail
.
Сначала используйте эту простую PHP-функцию, чтобы проверить работу почты в PHP:
<?php
$to = "example@gmail.com";
$subject = "Тестовая функция email";
$txt = "Привет, мир!";
$headers = "From: webmaster@example.com" . "\r\n" .
"CC: xyz@example.com";
mail($to,$subject,$txt,$headers);
?>
Если это не работает, то вам необходимо установить почтовый сервер PHP. Используйте эту команду для установки почтового сервера на сервер Ubuntu:
sudo apt-get install sendmail
Затем проверьте функции отправки email в WordPress.

Если другие отличные решения здесь не помогли, попробуйте следующее:
Я столкнулся с той же проблемой, и ни одно из предложенных решений для WordPress мне не помогло.
Затем я начал исследовать, не отключена ли функция mail в самой установке PHP, но и это не дало результатов. Все настройки казались правильными.
Все эти проблемы начались у меня после обновления сервера до CentOS 7, которая использует SELinux (Security Enhanced Linux). И то, что я понял за последние пару недель работы с SELinux - если что-то не работает, но все выглядит так, будто должно работать... это значит, что SELinux тихо и незаметно блокирует вас в фоновом режиме.
И вуаля.
Если вы используете операционную систему с SELinux, просто выполните следующую команду от имени root:
setsebool -P httpd_can_sendmail=1
Существует настройка безопасности, которая по умолчанию запрещает веб-серверу отправлять электронную почту. Когда вы меняете этот параметр и разрешаете SELinux отправку почты через веб-сервер, всё внезапно начинает работать.

Я столкнулся с этим сегодня; в моем случае проблема возникла из-за того, что в файле hosts сервера указано то же доменное имя, что и в адресе электронной почты, и оно направлено на localhost. MX-запись указывает на другой сервер, но файл hosts переопределяет DNS, и WordPress пытается доставить письмо локально. Удаление домена из файла hosts и перезапуск sendmail решили эту проблему.

Не знаю, актуально ли это для вас сейчас, но раз ответ не был выбран, я решил попробовать предложить своё решение.
Я столкнулся с точно такой же проблемой, когда мой хостинг на openshift внезапно перестал отправлять письма. Изучая код и документацию, я узнал о функции wp_mail(), а затем Google привёл меня сюда, где я увидел, как её можно переопределить.
Основываясь на ответе @Ralf912, я немного модифицировал скрипт, чтобы он использовал веб-API sendgrid.com для отправки писем вместо стандартного механизма WordPress (как я предполагаю):
<?php
function sendgridmail($to, $subject, $message, $headers)
{
$url = 'https://api.sendgrid.com/';
//$user = 'yourUsername';
//$pass = 'yourPassword';
$params = array(
'api_user' => $user,
'api_key' => $pass,
'to' => $to,
'subject' => $subject,
'html' => '',
'text' => $message,
'from' => 'abc@hotmail.com',
);
$request = $url.'api/mail.send.json';
// Генерируем curl-запрос
$session = curl_init($request);
// Указываем использовать POST
curl_setopt ($session, CURLOPT_POST, true);
// Указываем тело POST-запроса
curl_setopt ($session, CURLOPT_POSTFIELDS, $params);
// Не возвращаем заголовки, но возвращаем ответ
curl_setopt($session, CURLOPT_HEADER, false);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
// Получаем ответ
$response = curl_exec($session);
curl_close($session);
// Выводим всё (раскомментируйте для отладки)
//print_r($response);
}
// Только для тестирования:
/*$to = 'abc@yahoo.com';
$subject = 'Testemail';
$message = 'It works!!';
echo 'To is: ' + $to;
#wp_mail( $to, $subject, $message, array() );
sendgridmail($to, $subject, $message, $headers);
print_r('Just sent!');*/
if (!function_exists('wp_mail')) {
function wp_mail($to, $subject, $message, $headers = '', $attachments = array())
{
// Используем PHP GnuPG библиотеку для отправки почты
sendgridmail($to, $subject, $message, $headers);
}
}
function plugin_init()
{
/* $to = 'xyz@yahoo.com';
$subject = 'Testemail';
$message = 'It works Live!';
//echo 'To is: ' + $to;
wp_mail( $to, $subject, $message, array() );
//print_r('Just sent!');*/
}
И это сработало!

У меня была такая же ошибка - обе функции (mail и wp_mail) работали, но это надоедливое сообщение об ошибке не исчезало. Решение оказалось очень простым, но мне потребовалось несколько часов, чтобы найти причину. Поэтому я поделюсь здесь своим решением проблемы, которое может быть (или не быть) таким же, как у вас.
Я пробовал функцию mail(), и она работала, но при тестировании вы не указываете последний параметр под названием 'parameters' в функции mail(). А WordPress как раз его использует.
@mail("example@exmaple.com",$title,$body,$headers,"-fexample@exmaple.com");
По сути, этот параметр ("-fexample@exmaple.com") с флагом "-f" заставляет функцию mail() проверять, есть ли email-адрес "example@exmaple.com" в списке "доверенных email-адресов".
Если его там нет, функция возвращает false, что приводит к тому, что wp_mail() также возвращает false и вызывает сообщение об ошибке.
Решение - попросить хостинг-провайдера добавить email в доверенный список, либо, если вы используете cPanel, просто создать почтовый аккаунт для этого адреса, и он автоматически добавится в "доверенный список".

Это называется -Управление зарегистрированными email-адресами для отправки писем через скрипты, например (Wordpress)
- Войдите в вашу Cpanel.
- Перейдите в раздел Email > затем нажмите Registered Email IDs.
- Затем добавьте (wordpress@yourdomain.com) или где размещен ваш wordpress. Например (wordpress@blog.yourdomain.com). Затем подтвердите, это займет несколько минут для активации, подождите от 15 минут до 1 часа в зависимости от вашего хостинг-провайдера, после чего все заработает.

Я долго мучился с этой ошибкой и перепробовал множество решений, которые не работали. У меня кастомная установка WordPress на AWS EC2. Прежде всего, убедитесь, что ваша почта AWS SES включена через поддержку, они должны быть в одном (или близком) регионе в SES и EC2.
Я использовал Google Suite (G Suite) для электронной почты, чтобы получать и отправлять письма.
Убедитесь, что тестовое письмо отправляется через AWS SES и G Suite.
Установите плагин WordPress WP Mail SMTP, выберите опцию "Другой SMTP", возьмите ваши SMTP-данные из AWS SES — именно здесь я застрял.
Вы должны включить галочку "SSL" для шифрования, это изменило порт на 465 у меня. Наконец, мое тестовое письмо успешно отправилось из WordPress.

Я исправил эту проблему, изменив "From Email" (Отправитель) в локальной тестовой среде, заменив wordpress@localhost на wordpress@localhost.localdomain, например, с помощью WordPress-плагина "WP Mail SMTP", выбрав стандартный PHP mailer вместо SMTP.
Проблема возникала даже при отключенных всех остальных плагинах, и ранее у меня не было этой проблемы. Также проблема отсутствует при использовании PHP-функции mail напрямую, так что, возможно, это связано с недавними изменениями в WordPress.
Я успешно отправлял и получал письма на локальном компьютере, используя Postfix.
