libro / blog / enviar-correos-php-phpmailer

// correo

Cómo enviar correos con PHP usando PHPMailer y SMTP

Gustavo Arias8 min de lectura

TL;DR La función mail() depende de la configuración del servidor y sus correos suelen acabar en spam. Usa PHPMailer con un servidor SMTP autenticado, envía siempre versión HTML y texto plano, guarda las credenciales fuera del código y configura SPF, DKIM y DMARC en tu dominio.

Confirmar un registro, recuperar una contraseña, avisar de un pedido: casi toda aplicación web necesita enviar correos. Y casi todos los principiantes tropiezan con lo mismo: el correo “se envía” pero nunca llega, o llega a la carpeta de spam. En el libro PHP desde cero hasta experto el envío de correos tiene su propio capítulo; aquí tienes la forma fiable de hacerlo con PHPMailer.

Por qué no usar mail()

PHP trae la función mail(), pero tiene problemas serios en la práctica:

PHPMailer resuelve todo eso: se conecta a un servidor SMTP real (el de tu hosting, Gmail, Microsoft 365 o un servicio transaccional) y arma el mensaje correctamente.

Instalar PHPMailer con Composer

$ composer require phpmailer/phpmailer

Composer descarga la librería en la carpeta vendor/ y genera el archivo vendor/autoload.php, que carga las clases automáticamente. Si no usas Composer, PHPMailer también puede incluirse a mano, pero Composer es el estándar actual en PHP.

Ejemplo: enviar un correo HTML por SMTP

<?php
declare(strict_types=1);

use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;

require __DIR__ . '/vendor/autoload.php';
$config = require __DIR__ . '/config/correo.php';   // credenciales fuera del código

function enviarCorreo(array $config, string $para, string $asunto, string $html, string $texto): bool
{
    $mail = new PHPMailer(true);   // true = lanza excepciones si falla

    try {
        $mail->isSMTP();
        $mail->Host       = $config['host'];
        $mail->SMTPAuth   = true;
        $mail->Username   = $config['usuario'];
        $mail->Password   = $config['clave'];
        $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
        $mail->Port       = 587;
        $mail->CharSet    = PHPMailer::CHARSET_UTF8;   // tildes y eñes correctas

        $mail->setFrom($config['remitente'], 'Mi Aplicación');
        $mail->addAddress($para);

        $mail->isHTML(true);
        $mail->Subject = $asunto;
        $mail->Body    = $html;
        $mail->AltBody = $texto;   // versión en texto plano

        $mail->send();
        return true;
    } catch (Exception $e) {
        error_log('Error al enviar correo: ' . $mail->ErrorInfo);
        return false;
    }
}

$ok = enviarCorreo(
    $config,
    'cliente@ejemplo.com',
    'Confirma tu cuenta',
    '<h1>¡Bienvenida!</h1><p>Gracias por registrarte.</p>',
    "¡Bienvenida!\nGracias por registrarte."
);
echo $ok ? 'Correo enviado' : 'No se pudo enviar el correo';
<?php
return [
    'host'      => 'smtp.tu-proveedor.com',
    'usuario'   => 'no-responder@tudominio.com',
    'clave'     => 'contraseña-de-aplicación',
    'remitente' => 'no-responder@tudominio.com',
];
Si usas Gmail o Microsoft 365, no pongas tu contraseña personal: genera una contraseña de aplicación (requiere la verificación en dos pasos) o usa el servidor SMTP de tu hosting.

Adjuntos

<?php
$mail->addAttachment(__DIR__ . '/facturas/factura-1024.pdf', 'Factura 1024.pdf');

Plantillas y datos del usuario

Mezclar HTML dentro de strings de PHP se vuelve inmanejable rápido. Una solución simple es guardar la plantilla en un archivo aparte y rellenarla con los datos, escapados:

<?php
function renderizarPlantilla(string $archivo, array $datos): string
{
    $seguros = array_map(fn($v) => htmlspecialchars((string) $v, ENT_QUOTES, 'UTF-8'), $datos);
    $html = file_get_contents($archivo);   // contiene marcadores como {{nombre}}
    foreach ($seguros as $clave => $valor) {
        $html = str_replace('{{' . $clave . '}}', $valor, $html);
    }
    return $html;
}

$html = renderizarPlantilla(__DIR__ . '/plantillas/bienvenida.html', ['nombre' => $nombre]);

Escapar importa también en los correos: si el nombre del usuario contiene HTML, podría alterar el mensaje o insertar enlaces engañosos.

Que tus correos no lleguen a spam

El uso más habitual de todo esto es el flujo de “olvidé mi contraseña”, que construimos paso a paso en recuperación de contraseña con tokens seguros.

Correos automatizados en tus proyectos

El libro PHP desde cero hasta experto enseña a enviar correos electrónicos automatizados, como confirmaciones de registro y recuperación de contraseña.

Comprar en Amazon