PHPMailer es la biblioteca más utilizada para enviar correo electrónico desde PHP. Envuelve SMTP para que configures host, puerto y credenciales una sola vez, y luego construyas y envíes mensajes con una API de objetos clara. La función integrada mail() de PHP se queda corta (sin autenticación, reportes de error débiles), por eso la mayoría de los proyectos usan PHPMailer en su lugar. A continuación, un envío completo y funcional.
¿Cómo instalas PHPMailer?
Usa Composer:
composer require phpmailer/phpmailer
Luego carga el autoloader e importa las clases que necesitas:
<?php
require "vendor/autoload.php";
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
¿Cómo configuras SMTP y envías un mensaje?
Crea una instancia de PHPMailer, cámbiala al modo SMTP con isSMTP() y configura los campos de conexión y mensaje. Envuelve la llamada en try/catch para que un envío fallido se reporte en lugar de pasar desapercibido:
<?php
$mail = new PHPMailer(true); // true enables exceptions
try {
// Server settings
$mail->isSMTP();
$mail->Host = "smtp.example.com";
$mail->SMTPAuth = true;
$mail->Username = getenv("SMTP_USER");
$mail->Password = getenv("SMTP_PASS");
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
// Recipients
$mail->setFrom("you@yourdomain.com", "Your App");
$mail->addAddress("recipient@example.org", "Recipient Name");
// Content
$mail->isHTML(true);
$mail->Subject = "Your receipt";
$mail->Body = "<p>Thanks for your order.</p>";
$mail->AltBody = "Thanks for your order. This is the plain-text version.";
$mail->send();
echo "Message sent.";
} catch (Exception $e) {
echo "Send failed: {$mail->ErrorInfo}";
}
Algunos detalles que causan problemas. SMTPSecure y Port van juntos: usa ENCRYPTION_STARTTLS con 587, o ENCRYPTION_SMTPS con 465. isHTML(true) le indica a PHPMailer que el Body es HTML y que envíe AltBody como alternativa en texto plano. Pasa true al constructor para que los fallos lancen una Exception en lugar de devolver false en silencio.
¿Cómo agregas un adjunto?
Llama a addAttachment con una ruta de archivo antes de send():
<?php
$mail->addAttachment("./invoices/invoice-1042.pdf", "invoice.pdf");
El segundo argumento renombra el archivo tal como lo ve el destinatario. Puedes llamarlo más de una vez para varios adjuntos.
Envíalo con Bird
PHPMailer habla SMTP, lo que significa que en producción necesitas un servidor de correo con buena reputación, registros de autenticación correctos y un lugar donde ver qué pasó después del envío. Una HTTP API elimina el servidor. Envías JSON a través de HTTPS y obtienes una respuesta estructurada. Con la Bird de correo electrónico de API el mismo mensaje se reduce a una sola llamada:
use Bird\Bird;
$bird = new Bird(getenv("BIRD_API_KEY"));
$bird->emails->send([
"from" => "you@yourdomain.com",
"to" => "delivered@bird.dev",
"subject" => "Hello from PHP",
"html" => "<p>It works.</p>",
]);
La dirección sandbox de delivered@bird.dev siempre acepta correo, así que puedes verificar la integración antes de enviar a bandejas reales. Sin socket SMTP, sin elegir puerto, sin reputación que calentar tú mismo.
Preguntas frecuentes
¿Por qué no usar simplemente la función mail() de PHP?
mail() entrega el mensaje al binario sendmail local sin autenticación SMTP y casi sin reporte de errores. PHPMailer se autentica contra un servidor remoto, soporta TLS, construye mensajes multiparte y te indica por qué falló un envío.
¿Cuál es la diferencia entre Body y AltBody?
Body es la versión HTML y AltBody es el respaldo en texto plano. Con isHTML(true) activado, los clientes que no pueden renderizar HTML muestran AltBody, lo que también ayuda con la entregabilidad.
¿STARTTLS o SMTPS?
ENCRYPTION_STARTTLS en el puerto 587 actualiza una conexión sin cifrar a TLS, mientras que ENCRYPTION_SMTPS en el puerto 465 cifra desde el inicio. Ajusta la configuración al puerto que espera tu servidor de correo.
PHPMailer es la herramienta adecuada cuando quieres enviar por SMTP desde PHP. Si prefieres no operar el servidor, la guía de envío de correo electrónico muestra la ruta de API completa.