Cómo configurar SMTP programáticamente
Supongamos que tenemos un sitio WP en blanco y queremos configurar los ajustes de SMTP programáticamente en nuestro plugin o tema. ¿Cuál es la forma más sencilla de hacerlo sin modificar los archivos del núcleo?

En primer lugar, si analizamos la implementación de la función wp_mail
, veremos que esta utiliza la clase PHPMailer
para enviar correos electrónicos. También podremos notar que hay una llamada de función codificada directamente $phpmailer->IsMail();
, que configura el uso de la función mail()
de PHP. Esto significa que no podemos usar configuraciones SMTP con ella. Necesitamos llamar a la función isSMTP
de la clase PHPMailer
. Además, también debemos configurar nuestros parámetros SMTP.
Para lograrlo, necesitamos acceder a la variable $phpmailer
. Es aquí donde entra en juego la acción phpmailer_init
, que se llama antes de enviar un correo electrónico. Por lo tanto, podemos hacer lo que necesitamos escribiendo nuestro manejador de acción:
add_action( 'phpmailer_init', 'wpse8170_phpmailer_init' );
function wpse8170_phpmailer_init( PHPMailer $phpmailer ) {
$phpmailer->Host = 'tu.servidor.smtp.aqui';
$phpmailer->Port = 25; // podría ser diferente
$phpmailer->Username = 'tu_usuario@ejemplo.com'; // si es requerido
$phpmailer->Password = 'tupassword'; // si es requerido
$phpmailer->SMTPAuth = true; // si es requerido
// $phpmailer->SMTPSecure = 'ssl'; // activar si es requerido, 'tls' es otro valor posible
$phpmailer->IsSMTP();
}
Y eso es todo.

¡Buen material, Eugene, gracias! Supongo que estas 10 líneas de código pueden sustituir un plugin SMTP completo...(?)

@brasofilo ¡gracias! Creo que no puede sustituir un plugin SMTP, porque el plugin te permite configurar los ajustes desde el panel de administración. Este fragmento es solo una buena práctica sobre "cómo cambiar los ajustes de correo electrónico programáticamente" sin romper los archivos del núcleo o sin reescribir la función wp_mail
.

¿Tal vez un enlace al núcleo? Acabo de descubrir que necesitamos usar esto para SSL: $phpmailer->SMTPSecure = 'ssl';
, o 'tls'
si ese es el caso. ::: De nuevo:, ¡material excelente!

@brasofilo sí, estoy de acuerdo. Siéntete libre de editar la respuesta si lo deseas. Gracias por la ayuda.

¿Dónde debería colocar este código? Quiero que todos mis temas usen los mismos servidores SMTP.

@Anjan crea tu propio plugin.

Es muy extraño que WordPress no facilite esto, ya que podrías pensar que sería común modificar este aspecto.

Funciona para mí, @JackNicholson deberías verificarlo también en tu entorno.

Usé este código pero WordPress envía mediante mail() de PHP. ¿Cómo forzar a WordPress a que envíe solo por SMTP? Cuando uso wp_mail("hossein@hashemiui.com", "test", "test"); no lo envía via SMTP

Adición a la respuesta de @EugeneManuilov.
Configuración SMTP
Por defecto, como ya respondió @EugeneManuilov, solo se pueden configurar mediante un callback adjunto a un do_action_ref_array()
. Fuente/núcleo.
<?php
defined( 'ABSPATH' ) OR exit;
/**
* Plugin Name: (WCM) Configuración SMTP de PHPMailer
* Description: Habilita servidores SMTP, autenticación SSL/TSL y configuración SMTP.
*/
add_action( 'phpmailer_init', 'phpmailerSMTP' );
function phpmailerSMTP( $phpmailer )
{
# $phpmailer->IsSMTP();
# $phpmailer->SMTPAuth = true; // Autenticación
# $phpmailer->Host = '';
# $phpmailer->Username = '';
# $phpmailer->Password = '';
# $phpmailer->SMTPSecure = 'ssl'; // Activar si es necesario - 'tls' es otro valor posible
# $phpmailer->Port = 26; // Puerto SMTP - 26 es para GMail
}
Excepciones SMTP
Por defecto WordPress no proporciona ninguna salida de depuración. En su lugar, simplemente devuelve FALSE
si ocurre un error. Aquí hay un pequeño plugin para solucionar esto:
<?php
defined( 'ABSPATH' ) OR exit;
/**
* Plugin Name: (WCM) Excepciones PHPMailer & SMTP
* Description: WordPress por defecto devuelve <code>FALSE</code> en lugar de una <code>Exception</code>. Este plugin corrige eso.
*/
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;
// Habilitar SMTP
# $phpmailer->IsSMTP();
$phpmailer->SMTPDebug = 2;
$phpmailer->debug = 1;
// Usa `var_dump( $data )` para inspeccionar datos en el último punto y ver
// si algo ha cambiado en el núcleo. Deberías considerar volcarlo durante el
// filtro `wp_mail` también, para obtener el estado original para comparación.
$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()
);
}
Repositorio
Ambos plugins están disponibles en este Gist en GitHub, así que considera descargarlos desde allí para obtener actualizaciones.

Las otras respuestas a esta publicación, aunque proporcionan una solución funcional, no abordan el problema de seguridad de almacenar tus credenciales SMTP en un archivo de plugin o functions.php. En algunos casos puede estar bien, pero las mejores prácticas indicarían almacenar esta información de forma más segura. Realmente no hay una buena razón para no seguir las mejores prácticas cuando se trata de proteger tus credenciales.
Algunos sugerirían guardarlas en la base de datos como opción, pero esto también presenta los mismos problemas de seguridad dependiendo del número de usuarios administrativos que tenga tu sitio y si esos usuarios deberían poder ver estas credenciales de acceso. Esta es también la misma razón para no usar un plugin para esto.
La mejor manera de hacer esto es definir constantes para la información de phpmailer en tu archivo wp-config.php. Esto ha sido discutido como una característica en el componente Mail, pero no ha sido aceptado como una mejora real hasta ahora. Pero puedes hacerlo tú mismo añadiendo lo siguiente a wp-config.php:
/**
* Define las siguientes constantes en wp-config.php
* Estos deben añadirse en algún lugar ANTES de que
* se defina la constante ABSPATH.
*/
define( 'SMTP_USER', 'user@example.com' ); // Nombre de usuario para autenticación SMTP
define( 'SMTP_PASS', 'smtp password' ); // Contraseña para autenticación SMTP
define( 'SMTP_HOST', 'smtp.example.com' ); // El hostname del servidor de correo
define( 'SMTP_FROM', 'website@example.com' ); // Dirección de correo remitente SMTP
define( 'SMTP_NAME', 'e.g Website Name' ); // Nombre remitente SMTP
define( 'SMTP_PORT', '25' ); // Número de puerto SMTP - normalmente 25, 465 o 587
define( 'SMTP_SECURE', 'tls' ); // Sistema de encriptación a usar - ssl o tls
define( 'SMTP_AUTH', true ); // Usar autenticación SMTP (true|false)
define( 'SMTP_DEBUG', 0 ); // Solo para depuración, establecer a 1 o 2
Una vez definidas en wp-config.php, se pueden usar en cualquier lugar mediante la constante definida. Así que podrías usarlas en un archivo de plugin o en tu functions.php. (Específicamente para el OP, usa un archivo de plugin).
/**
* Esta función conectará wp_mail a tu servidor SMTP
* autenticado. Los valores son constantes definidas en 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;
}
Hay un poco más de detalle sobre esto en esta publicación y un gist en github aquí.
