Cómo configurar SMTP mediante programación

18

Supongamos que tenemos un sitio WP en blanco y queremos establecer la configuración SMTP mediante programación en nuestro complemento o tema. ¿Cuál es la forma más fácil de hacerlo sin cambiar los archivos principales?

Eugene Manuilov
fuente

Respuestas:

31

En primer lugar, si echamos un vistazo a la implementación de la wp_mailfunción, veremos que esta función utiliza la PHPMailerclase para enviar correos electrónicos. También podríamos notar que hay una función de llamada codificada $phpmailer->IsMail();, que establece el uso de la mail()función PHP . Significa que no podemos usar la configuración SMTP con él. Necesitamos llamar a la isSMTPfunción de PHPMailerclase. Y también necesitamos establecer nuestra configuración SMTP también.

Para lograrlo necesitamos obtener acceso a la $phpmailervariable. Y aquí llegamos a la phpmailer_initacción que se llama antes de enviar un correo electrónico. Entonces podemos hacer lo que necesitamos escribiendo nuestro manejador de acciones:

add_action( 'phpmailer_init', 'wpse8170_phpmailer_init' );
function wpse8170_phpmailer_init( PHPMailer $phpmailer ) {
    $phpmailer->Host = 'your.smtp.server.here';
    $phpmailer->Port = 25; // could be different
    $phpmailer->Username = '[email protected]'; // if required
    $phpmailer->Password = 'yourpassword'; // if required
    $phpmailer->SMTPAuth = true; // if required
    // $phpmailer->SMTPSecure = 'ssl'; // enable if required, 'tls' is another possible value

    $phpmailer->IsSMTP();
}

Y eso es todo.

Eugene Manuilov
fuente
Buenas cosas, Eugene, gracias! Supongo que estas 10 líneas de código pueden sustituir un complemento SMTP completo ... (?)
brasofilo
@brasofilo thx! Creo que no puede sustituir un complemento SMTP, porque el complemento le permite configurar los ajustes en el panel de administración. Este fragmento es la mejor práctica sobre "cómo cambiar la configuración del correo electrónico mediante programación" sin romper los archivos principales o sin la wp_mailfunción de reescritura .
Eugene Manuilov
2
¿Dónde se debe colocar este código? Quiero hacer que todos mis temas utilicen los mismos servidores SMTP.
Anjan
1
WP muy extraño no hace esto más fácil ya que pensarías que sería común modificar esto.
Carson Reinke
1
a mí me funciona, @JackNicholson, deberías comprobarlo también por tu parte.
Eugene Manuilov
7

Además de la respuesta @EugeneManuilov.

Configuraciones SMTP

De forma predeterminada, estos solo pueden establecerse, como @EugeneManuilov ya respondió, durante una devolución de llamada adjunta a un do_action_ref_array().Fuente / núcleo .

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (WCM) PHPMailer SMTP Settings
 * Description: Enables SMTP servers, SSL/TSL authentication and SMTP settings.
 */

add_action( 'phpmailer_init', 'phpmailerSMTP' );
function phpmailerSMTP( $phpmailer )
{
    # $phpmailer->IsSMTP();
    # $phpmailer->SMTPAuth   = true;  // Authentication
    # $phpmailer->Host       = '';
    # $phpmailer->Username   = '';
    # $phpmailer->Password   = '';
    # $phpmailer->SMTPSecure = 'ssl'; // Enable if required - 'tls' is another possible value
    # $phpmailer->Port       = 26;    // SMTP Port - 26 is for GMail
}

Excepciones SMTP

Por defecto, WordPress no le da ninguna salida de depuración. En cambio, solo regresaFALSE si se produjo un error. Aquí hay un pequeño complemento para solucionar esto:

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (WCM) PHPMailer Exceptions & SMTP
 * Description: WordPress by default returns <code>FALSE</code> instead of an <code>Exception</code>. This plugin fixes that.
 */

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;

    // Enable SMTP
    # $phpmailer->IsSMTP();
    $phpmailer->SMTPDebug = 2;
    $phpmailer->debug     = 1;

    // Use `var_dump( $data )` to inspect stuff at the latest point and see
    // if something got changed in core. You should consider dumping it during the
    // `wp_mail` filter as well, so you get the original state for comparison.
    $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

Los complementos están disponibles en este Gist en GitHub , así que considera revisar esos complementos desde allí para obtener actualizaciones.

emperador
fuente
3

Las otras respuestas a esta publicación, si bien proporcionan una solución de trabajo, no abordan el problema de seguridad de almacenar sus credenciales SMTP en un archivo de complemento o funciones.php. En algunos casos, eso puede estar bien, pero las mejores prácticas dictarían almacenar esta información de manera más segura. Realmente no hay una buena razón para no seguir las mejores prácticas cuando se trata de proteger sus credenciales.

Algunos sugerirían guardarlo en la base de datos como una opción, pero también proporciona los mismos problemas de seguridad dependiendo de la cantidad de usuarios administrativos que tenga su sitio y si esos usuarios deberían poder ver estas credenciales de inicio de sesión. Esta es también la misma razón para no usar un complemento para esto.

La mejor manera de hacerlo es definir constantes para la información de phpmailer en su archivo wp-config.php. En realidad, esto se ha discutido como una característica en el componente de correo , pero no se ha aceptado como una mejora real en este momento. Pero puede hacerlo usted mismo agregando lo siguiente a wp-config.php:

/**
 * Set the following constants in wp-config.php
 * These should be added somewhere BEFORE the
 * constant ABSPATH is defined.
 */
define( 'SMTP_USER',   '[email protected]' );    // Username to use for SMTP authentication
define( 'SMTP_PASS',   'smtp password' );       // Password to use for SMTP authentication
define( 'SMTP_HOST',   'smtp.example.com' );    // The hostname of the mail server
define( 'SMTP_FROM',   '[email protected]' ); // SMTP From email address
define( 'SMTP_NAME',   'e.g Website Name' );    // SMTP From name
define( 'SMTP_PORT',   '25' );                  // SMTP port number - likely to be 25, 465 or 587
define( 'SMTP_SECURE', 'tls' );                 // Encryption system to use - ssl or tls
define( 'SMTP_AUTH',    true );                 // Use SMTP authentication (true|false)
define( 'SMTP_DEBUG',   0 );                    // for debugging purposes only set to 1 or 2

Una vez que se definen en wp-config.php, se pueden usar en cualquier lugar usando la constante definida. Por lo tanto, podría usarlos en un archivo de complemento o en su functions.php. (Específico para el OP, use un archivo de complemento).

/**
 * This function will connect wp_mail to your authenticated
 * SMTP server. Values are constants set in 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 detalles sobre esto en esta publicación y una idea general de github aquí .

butlerblog
fuente
Una muy buena solución!
Phill Healey
1
Pequeña adición: No hace falta decir que no almacene credenciales en el control de versiones. Utilice el .envarchivo gitignored en su lugar. Pero wp-config.php, de todos modos, nadie que pone algo sensible está usando el control de versiones ...
jsphpl