Contents
Introducción
Este tutorial explica de forma exhaustiva cómo enviar correos electrónicos desde WordPress usando la función wp_mail y plantillas HTML en PHP. Incluye ejemplos prácticos, configuración del tipo de contenido, carga de plantillas, seguridad, personalización del remitente y depuración. Los fragmentos de código están listados para copiar y pegar directamente en temas o plugins.
Qué es wp_mail y cómo funciona
wp_mail() es la envoltura de WordPress sobre PHPMailer. Permite enviar correo usando parámetros simples (to, subject, message, headers, attachments). Por defecto envía texto plano para enviar HTML hay que indicar el Content-Type adecuado o usar filtros. Además, hay filtros útiles como wp_mail_from, wp_mail_from_name y wp_mail_content_type para personalizar comportamiento.
Requisitos y buenas prácticas previas
- Asegúrate de que tu servidor puede enviar correo saliente. En muchos casos conviene configurar un SMTP real (por ejemplo mediante el plugin WP Mail SMTP) o usando phpmailer_init para ajustar credenciales.
- Sanitiza y valida las direcciones de correo con sanitize_email() y is_email() antes de pasarlas a wp_mail.
- Usa nonces y comprobaciones de permisos al enviar correos desde formularios públicos para evitar abuso y envío masivo no autorizado.
Contenido HTML: establecer el tipo correctamente
Para que los clientes de correo interpreten correctamente HTML, debes indicar el Content-Type. Lo habitual es añadir un filtro temporal que lo ponga en text/html charset=UTF-8:
add_filter(wp_mail_content_type, function() { return text/html charset=UTF-8 })
Tras enviar el correo conviene restablecer el tipo por defecto (text/plain) para no romper otros envíos:
// Añadir antes de wp_mail add_filter(wp_mail_content_type, my_html_content_type) wp_mail(to, subject, message, headers, attachments) remove_filter(wp_mail_content_type, my_html_content_type) function my_html_content_type() { return text/html charset=UTF-8 }
Carga de una plantilla HTML desde el tema o plugin
Lo ideal es mantener plantillas HTML separadas en archivos y cargarlas para evitar concatenar cadenas en el código. A continuación un patrón seguro para cargar una plantilla y pasarle variables.
Ejemplo de plantilla (archivo: email-templates/user-welcome.php) — contiene HTML completo y placeholders:
lt!doctype htmlgt lthtml lang=esgt ltheadgt ltmeta charset=utf-8gt ltmeta name=viewport content=width=device-widthgt lttitlegtBienvenidolt/titlegt ltstylegt / CSS mínimo inline recomendado para compatibilidad en clientes de correo / body { font-family: Arial, sans-serif color: #333 } .container { width: 100% max-width: 600px margin: 0 auto } .btn { display:inline-block padding:10px 16px background:#0073aa color:#fff text-decoration:none border-radius:3px } lt/stylegt lt/headgt ltbodygt lttable role=presentation width=100% cellpadding=0 cellspacing=0gt lttrgtlttd class=containergt lth2gtHola, {{name}}!lt/h2gt ltpgtGracias por registrarte en nuestro sitio. Para activar tu cuenta pulsa el siguiente botón:lt/pgt ltpgtlta class=btn href={{activation_url}}gtActivar cuentalt/agtlt/pgt ltpgtSi no has solicitado esto, ignora este correo.lt/pgt lt/tdgtlt/trgt lt/tablegt lt/bodygt lt/htmlgt
Función para renderizar y enviar usando la plantilla anterior:
function send_templated_email( to, subject, template_path, vars = array(), attachments = array() ) { // Validaciones básicas to = sanitize_email( to ) if ( ! is_email( to ) ) { return false } // Localiza la plantilla en tema/child o en plugin located = locate_template( template_path ) if ( ! located ) { // Si estás en un plugin puedes usar plugin_dir_path(__FILE__) . templates/ . template_path return false } // Cargar plantilla y capturar salida ob_start() load_template( located, false ) message = ob_get_clean() // Reemplazar variables seguras (usar esc_html para valores simples) foreach ( vars as key => value ) { safe = esc_html( value ) message = str_replace( {{ . key . }}, safe, message ) } // Cabeceras: indicar HTML add_filter(wp_mail_content_type, function() { return text/html charset=UTF-8 }) // Enviar sent = wp_mail( to, subject, message, array(), attachments ) // Restaurar filtros remove_filter(wp_mail_content_type, wp_mail_content_type) return sent }
Ejemplo práctico: envío tras registro (procesamiento de formulario) con nonce y sanitización
if ( isset(_POST[my_register_form]) ) { if ( ! isset(_POST[_wpnonce]) ! wp_verify_nonce( _POST[_wpnonce], my_register_action ) ) { wp_die(Nonce no válido) } email = isset(_POST[email]) ? sanitize_email(_POST[email]) : name = isset(_POST[name]) ? sanitize_text_field(_POST[name]) : if ( ! is_email(email) ) { wp_die(Email no válido) } activation_link = add_query_arg( array( key => wp_generate_uuid4(), email => rawurlencode(email) ), home_url(/activar/) ) vars = array( name => name, activation_url => activation_link, ) sent = send_templated_email( email, Activa tu cuenta, email-templates/user-welcome.php, vars ) if ( sent ) { // Redirigir o mostrar mensaje de éxito } else { // Gestionar error } }
Personalizar el remitente (From) de forma segura
Modificar From mediante cabeceras puede funcionar, pero lo recomendado es usar los filtros de WordPress para evitar problemas con múltiples envíos concurrentes. Ejemplo:
function my_mail_from( original_email_address ) { return no-reply@tudominio.com } function my_mail_from_name( original_email_from ) { return Tu Sitio } // Antes de enviar add_filter(wp_mail_from, my_mail_from) add_filter(wp_mail_from_name, my_mail_from_name) wp_mail(to, subject, message) // Después de enviar (restaurar) remove_filter(wp_mail_from, my_mail_from) remove_filter(wp_mail_from_name, my_mail_from_name)
Configurar SMTP mediante phpmailer_init (opción programática)
Si no quieres usar plugins, puedes configurar PHPMailer con el hook phpmailer_init. Útil para entornos donde el mail() está deshabilitado.
add_action(phpmailer_init, function(phpmailer) { phpmailer->isSMTP() phpmailer->Host = smtp.example.com phpmailer->SMTPAuth = true phpmailer->Port = 587 phpmailer->Username = usuario@smtp phpmailer->Password = contraseña phpmailer->SMTPSecure = tls // o ssl phpmailer->From = no-reply@tudominio.com phpmailer->FromName = Tu Sitio })
Adjuntos y cabeceras adicionales
wp_mail acepta un array de cabeceras y un array de rutas de archivos como adjuntos. Ejemplo:
headers = array( Reply-To: Soporte, X-Mailer: WordPress/ . get_bloginfo(version) ) attachments = array( WP_CONTENT_DIR . /uploads/manual.pdf ) wp_mail( to, subject, message, headers, attachments )
Cómo depurar envíos que fallan
- Activa WP_DEBUG y revisa logs. A veces wp_mail devuelve false y no hay mensajes: habilita el log del servidor SMTP o depura PHPMailer con el hook phpmailer_init.
- Plugins como WP Mail SMTP ofrecen registros para ver errores SMTP.
- Comprueba que el servidor no esté bloqueando el puerto SMTP y revisa SPF/DKIM/DMARC si los correos llegan marcados como spam.
Seguridad y compatibilidad
- Sanitiza inputs antes de incluirlos en la plantilla para evitar inyección de HTML no deseada. Usa esc_html() para texto simple y wp_kses_post() si permites etiquetas HTML limitadas.
- No incluyas datos sensibles en correos no cifrados (contraseñas en texto claro, tokens permanentes, etc.).
- Para emails transaccionales críticos, usa proveedores SMTP/servicios dedicados (SendGrid, Mailgun, Amazon SES) para mayor entregabilidad y métricas.
- Para plantillas con CSS avanzado, aplica estilos inline o utiliza herramientas para inlinizar CSS antes de enviar (mejor compatibilidad con clientes de correo).
Pruebas y flujo recomendado
Prueba localmente con servicios de inspección de correo (MailHog, Mailtrap) o plugins que redirijan correos a logs durante desarrollo. Implementa primero la versión en texto plano y luego añade HTML para depurar de forma más sencilla.
Resumen
Enviar correos HTML en WordPress con wp_mail implica:
- Establecer el content-type a text/html.
- Organizar plantillas HTML separadas y cargarlas con locate_template/load_template o desde carpetas de plugin.
- Sanitizar datos, usar nonces en formularios y configurar el remitente de forma segura mediante filtros.
- Si el servidor no envía correctamente, configurar SMTP vía plugin o phpmailer_init.
Enlaces útiles
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |