Automatizar el envío de correos es esencial para cualquier aplicación web moderna. En esta guía aprenderás a configurar PHPMailer, una biblioteca robusta y segura para enviar emails desde PHP.
Configuración de PHPMailer en PHP
Primero, instala PHPMailer usando Composer (recomendado) o descárgalo desde GitHub:
composer require phpmailer/phpmailer
Luego, incluye PHPMailer en tu script:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require 'vendor/autoload.php';
?>
Nunca hardcodees credenciales de email en producción. Usa variables de entorno o un archivo de configuración seguro.
Enviar correos de confirmación y notificaciones
Ejemplo básico para enviar un correo de bienvenida:
$mail = new PHPMailer(true);
try {
// Configuración del servidor SMTP
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = getenv('SMTP_USER'); // Usar variables de entorno
$mail->Password = getenv('SMTP_PASS');
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->CharSet = 'UTF-8';
// Destinatarios
$mail->setFrom('no-reply@tudominio.com', 'Tu Sitio');
$mail->addAddress('cliente@email.com', 'Cliente');
// Contenido del correo
$mail->isHTML(true);
$mail->Subject = 'Bienvenido a nuestra plataforma';
$mail->Body = '
<h1>¡Hola, bienvenido!</h1>
<p>Gracias por registrarte en nuestra plataforma.</p>
<p>Ya puedes comenzar a usar tu cuenta.</p>
<a href="https://tudominio.com/login"
style="background:#2563eb;color:white;padding:10px 20px;
text-decoration:none;border-radius:5px">
Iniciar sesión
</a>
';
$mail->AltBody = 'Hola, bienvenido. Gracias por registrarte. Visita: https://tudominio.com/login';
$mail->send();
echo 'Correo enviado exitosamente';
} catch (Exception $e) {
error_log("Error al enviar correo: {$mail->ErrorInfo}");
echo "No se pudo enviar el mensaje. Intenta más tarde.";
}
Resultado: Un correo HTML profesional con fallback de texto plano para clientes que no soportan HTML.
Implementación de recuperación de contraseña por correo
Este es uno de los usos más importantes de PHPMailer. Aquí el flujo completo:
Ingresa su email
Token único + expiración
Enlace con token seguro
Nueva contraseña segura
// 1. Generar token seguro (50 bytes = 100 caracteres hex)
$token = bin2hex(random_bytes(50));
$expires = date('Y-m-d H:i:s', strtotime('+1 hour'));
// 2. Guardar en base de datos (tabla password_resets)
$stmt = $conn->prepare("INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $email, $token, $expires);
$stmt->execute();
// 3. Crear enlace de recuperación
$enlace = "https://tudominio.com/recuperar.php?token=" . $token;
// 4. Configurar y enviar correo
$mail = new PHPMailer(true);
$mail->isSMTP();
// ... configuración SMTP ...
$mail->setFrom('no-reply@tudominio.com', 'Tu Sitio');
$mail->addAddress($email);
$mail->Subject = 'Recuperación de contraseña';
$mail->isHTML(true);
$mail->Body = "
<h2>Recuperación de contraseña</h2>
<p>Haz clic en el siguiente enlace para restablecer tu contraseña:</p>
<p><a href='$enlace' style='background:#2563eb;color:white;
padding:12px 24px;text-decoration:none;border-radius:5px;
display:inline-block'>Restablecer contraseña</a></p>
<p style='font-size:0.9rem;color:#64748b'>
Este enlace expira en 1 hora. Si no solicitaste esto, ignora este correo.
</p>
";
$mail->AltBody = "Recuperación de contraseña. Enlace: $enlace (expira en 1 hora)";
$mail->send();
• Usa random_bytes() para tokens criptográficamente seguros
• Establece una expiración corta (30-60 minutos)
• Invalida el token después de usarlo
• Registra intentos para detectar abusos
Validar el token en recuperar.php
Cuando el usuario hace clic en el enlace, valida el token antes de permitir el cambio:
// recuperar.php
$token = $_GET['token'] ?? '';
// 1. Buscar token válido en la base de datos
$stmt = $conn->prepare("
SELECT email, expires_at FROM password_resets
WHERE token = ? AND used = 0 AND expires_at > NOW()
LIMIT 1
");
$stmt->bind_param("s", $token);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
die("Enlace inválido o expirado");
}
$row = $result->fetch_assoc();
$email = $row['email'];
// 2. Mostrar formulario para nueva contraseña (HTML)
// ... formulario con campos password y confirm_password ...
// 3. Procesar el nuevo password
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$new_password = $_POST['password'];
$confirm = $_POST['confirm_password'];
// Validar fortaleza del password
if (strlen($new_password) < 8 || $new_password !== $confirm) {
$error = "La contraseña debe tener al menos 8 caracteres y coincidir";
} else {
// Hash seguro y actualizar usuario
$hash = password_hash($new_password, PASSWORD_DEFAULT);
$stmt = $conn->prepare("UPDATE users SET password = ? WHERE email = ?");
$stmt->bind_param("ss", $hash, $email);
$stmt->execute();
// Marcar token como usado
$stmt = $conn->prepare("UPDATE password_resets SET used = 1 WHERE token = ?");
$stmt->bind_param("s", $token);
$stmt->execute();
echo "Contraseña actualizada exitosamente";
}
}
Seguridad y buenas prácticas
Los tokens viajan por URL. Sin HTTPS, pueden ser interceptados.
Limita solicitudes de recuperación por email/IP para prevenir abusos.
Registra intentos de recuperación para detectar patrones sospechosos.
En el formulario de "Olvidé mi contraseña", siempre muestra el mismo mensaje ("Si el email existe, recibirás instrucciones") para no revelar qué usuarios están registrados en tu sistema.
¿Qué sigue después de PHPMailer?
Este es el séptimo paso del desarrollo full-stack. En el siguiente módulo, integrarás todo lo aprendido en un sistema de autenticación completo con dashboard.
📚 ¿Quieres la versión completa del libro?
Esta guía es una versión resumida del libro "Programación Full-Stack", que incluye ejercicios resueltos, códigos listos y explicaciones profundas de seguridad en correos.
Comprar en Amazon →¿Tienes dudas sobre PHPMailer, tokens o seguridad en correos? ¡Déjalas en los comentarios! 👇