Как программно настроить SMTP
Предположим, у нас есть чистый сайт WordPress, и мы хотим программно настроить параметры SMTP в нашем плагине или теме. Какой самый простой способ сделать это без изменения основных файлов?

Прежде всего, если мы посмотрим на реализацию функции wp_mail
, то увидим, что она использует класс PHPMailer
для отправки электронных писем. Также можно заметить жестко прописанный вызов функции $phpmailer->IsMail();
, который указывает использовать PHP-функцию mail()
. Это означает, что мы не можем использовать настройки SMTP с этим вызовом. Нам нужно вызвать функцию isSMTP
класса PHPMailer
. И также нам необходимо установить наши SMTP-настройки.
Для этого нам нужно получить доступ к переменной $phpmailer
. И здесь мы обращаемся к действию phpmailer_init
, которое вызывается перед отправкой письма. Таким образом, мы можем сделать то, что нам нужно, написав наш обработчик действия:
add_action( 'phpmailer_init', 'wpse8170_phpmailer_init' );
function wpse8170_phpmailer_init( PHPMailer $phpmailer ) {
$phpmailer->Host = 'your.smtp.server.here'; // ваш SMTP-сервер
$phpmailer->Port = 25; // может быть другим
$phpmailer->Username = 'your_username@example.com'; // если требуется
$phpmailer->Password = 'yourpassword'; // если требуется
$phpmailer->SMTPAuth = true; // если требуется
// $phpmailer->SMTPSecure = 'ssl'; // включить, если требуется, 'tls' - другое возможное значение
$phpmailer->IsSMTP();
}
И это всё.

Отличная работа, Eugene, спасибо! Полагаю, эти 10 строк кода могут заменить целый SMTP-плагин...(?)

@brasofilo спасибо! Думаю, это не может заменить SMTP-плагин, потому что плагин позволяет настраивать параметры в админ-панели. Этот сниппет — просто лучшая практика о том, "как изменить настройки email программно", без изменения файлов ядра или переопределения функции wp_mail
.

Может быть, ссылка на ядро? Только что обнаружил, что для SSL нужно использовать это: $phpmailer->SMTPSecure = 'ssl';
, или 'tls'
, если это необходимо. ::: Еще раз: отличная работа!

@brasofilo да, согласен. Не стесняйтесь редактировать ответ, если хотите. Спасибо за помощь.

Куда следует поместить этот код? Я хочу, чтобы все мои темы использовали одни и те же SMTP-серверы.

@Anjan создайте собственный плагин.

Очень странно, что WordPress не делает это проще, ведь казалось бы, это распространённая задача — изменять подобное.

У меня это работает, @JackNicholson, тебе тоже стоит проверить на своей стороне.

Я использовал этот код, но WordPress отправляет через php mail(). Как заставить WordPress отправлять только через SMTP? Когда я использую wp_mail("hossein@hashemiui.com", "test", "test"); он не отправляет через SMTP

Дополнение к ответу @EugeneManuilov.
Настройки SMTP
По умолчанию их можно установить - как уже ответил @EugeneManuilov - только через колбэк, прикреплённый к do_action_ref_array()
. Источник/ядро.
<?php
defined( 'ABSPATH' ) OR exit;
/**
* Plugin Name: (WCM) PHPMailer SMTP Settings
* Description: Включает SMTP серверы, SSL/TSL аутентификацию и настройки SMTP.
*/
add_action( 'phpmailer_init', 'phpmailerSMTP' );
function phpmailerSMTP( $phpmailer )
{
# $phpmailer->IsSMTP();
# $phpmailer->SMTPAuth = true; // Аутентификация
# $phpmailer->Host = '';
# $phpmailer->Username = '';
# $phpmailer->Password = '';
# $phpmailer->SMTPSecure = 'ssl'; // Включить если требуется - 'tls' другое возможное значение
# $phpmailer->Port = 26; // SMTP порт - 26 для GMail
}
Исключения SMTP
По умолчанию WordPress не выводит отладочную информацию. Вместо этого он просто возвращает FALSE
при возникновении ошибки. Вот небольшой плагин для исправления этого:
<?php
defined( 'ABSPATH' ) OR exit;
/**
* Plugin Name: (WCM) PHPMailer Exceptions & SMTP
* Description: WordPress по умолчанию возвращает <code>FALSE</code> вместо <code>Exception</code>. Этот плагин исправляет это.
*/
add_action( 'phpmailer_init', 'WCMphpmailerException' );
function WCMphpmailerException( $phpmailer )
{
if ( ! defined( 'WP_DEBUG' ) OR ! WP_DEBUG )
{
$phpmailer->SMTPDebug = 0;
$phpmailer->debug = 0;
return;
}
if ( ! current_user_can( 'manage_options' ) )
return;
// Включить SMTP
# $phpmailer->IsSMTP();
$phpmailer->SMTPDebug = 2;
$phpmailer->debug = 1;
// Используйте `var_dump( $data )` для проверки данных в последний момент и
// посмотреть, были ли изменения в ядре. Стоит также выводить данные во время
// фильтра `wp_mail`, чтобы получить исходное состояние для сравнения.
$data = apply_filters(
'wp_mail',
compact( 'to', 'subject', 'message', 'headers', 'attachments' )
);
current_user_can( 'manage_options' )
AND print htmlspecialchars( var_export( $phpmailer, true ) );
$error = null;
try
{
$sent = $phpmailer->Send();
! $sent AND $error = new WP_Error( 'phpmailerError', $sent->ErrorInfo );
}
catch ( phpmailerException $e )
{
$error = new WP_Error( 'phpmailerException', $e->errorMessage() );
}
catch ( Exception $e )
{
$error = new WP_Error( 'defaultException', $e->getMessage() );
}
if ( is_wp_error( $error ) )
return printf(
"%s: %s",
$error->get_error_code(),
$error->get_error_message()
);
}
Репозиторий
Оба плагина доступны в этом Gist на GitHub, поэтому проверяйте их там, чтобы получать обновления.

Другие ответы на этот пост, хотя и предлагают рабочее решение, не затрагивают проблему безопасности хранения учетных данных SMTP в файле плагина или functions.php. В некоторых случаях это может быть допустимо, но лучшие практики рекомендуют хранить эту информацию более безопасным способом. Нет веских причин не следовать лучшим практикам, когда речь идет о защите ваших учетных данных.
Некоторые могут предложить сохранить их в базе данных в качестве альтернативы, но это также создает те же проблемы безопасности, в зависимости от количества администраторов вашего сайта и того, должны ли эти пользователи видеть эти учетные данные. По этой же причине не стоит использовать плагин для этой цели.
Лучший способ сделать это — определить константы для информации phpmailer в файле wp-config.php. Это уже обсуждалось как функция в компоненте Mail, но пока не было принято в качестве официального улучшения. Однако вы можете сделать это самостоятельно, добавив следующее в wp-config.php:
/**
* Установите следующие константы в wp-config.php
* Их следует добавить где-нибудь ДО
* определения константы ABSPATH.
*/
define( 'SMTP_USER', 'user@example.com' ); // Имя пользователя для аутентификации SMTP
define( 'SMTP_PASS', 'smtp password' ); // Пароль для аутентификации SMTP
define( 'SMTP_HOST', 'smtp.example.com' ); // Имя хоста почтового сервера
define( 'SMTP_FROM', 'website@example.com' ); // Адрес отправителя SMTP
define( 'SMTP_NAME', 'e.g Website Name' ); // Имя отправителя SMTP
define( 'SMTP_PORT', '25' ); // Номер порта SMTP — вероятно, 25, 465 или 587
define( 'SMTP_SECURE', 'tls' ); // Используемая система шифрования — ssl или tls
define( 'SMTP_AUTH', true ); // Использовать аутентификацию SMTP (true|false)
define( 'SMTP_DEBUG', 0 ); // Только для отладки: установите 1 или 2
После того как эти константы определены в wp-config.php, их можно использовать где угодно, обращаясь к определенным константам. Таким образом, вы можете использовать их в файле плагина или в functions.php. (Для конкретного вопроса автора лучше использовать файл плагина.)
/**
* Эта функция подключит wp_mail к аутентифицированному
* SMTP-серверу. Значения берутся из констант, определенных в wp-config.php
*/
add_action( 'phpmailer_init', 'send_smtp_email' );
function send_smtp_email( $phpmailer ) {
$phpmailer->isSMTP();
$phpmailer->Host = SMTP_HOST;
$phpmailer->SMTPAuth = SMTP_AUTH;
$phpmailer->Port = SMTP_PORT;
$phpmailer->Username = SMTP_USER;
$phpmailer->Password = SMTP_PASS;
$phpmailer->SMTPSecure = SMTP_SECURE;
$phpmailer->From = SMTP_FROM;
$phpmailer->FromName = SMTP_NAME;
}
Подробнее об этом можно узнать в этом посте и в гисте на GitHub здесь.

Небольшое дополнение: Само собой разумеется, не храните учетные данные в системе контроля версий. Вместо этого используйте файл .env
, добавленный в .gitignore
. Впрочем, те, кто помещают что-то важное в wp-config.php
, скорее всего вообще не используют контроль версий...
