Correo electrónico recibido en Gmail

Enviar correo electrónico con HTML desde PHP

En este post se explica cómo enviar un correo electrónico, desde PHP, a cualquier dirección de correo electrónico. Por ejemplo, enviar desde PHP un mail a tu_usuario@gmail.com o cualquier dominio, así como si lo enviáramos a mano.

Correo electrónico recibido en Gmail
Correo electrónico recibido en Gmail

Lo que se verá es:

  • Enviar un correo desde PHP
  • Poner un asunto incluso si el mismo tiene letras con acentos
  • Establecer el remitente a un nombre personalizado
  • Cortar el mensaje para evitar truncarlo
  • Enviar HTML a través de un correo

Este tutorial será muy sencillo y simple para que se pueda apreciar lo básico para enviar un correo con PHP usando la función mail.

Cómo funciona el envío de correos desde PHP

Hace algún tiempo, en mis inicios de esto de la programación, no sabía cómo funcionaba el envío de correo, ni los servidores, ni PHP; nada. Y en una ocasión alguien me pidió algo muy simple: un formulario de contacto, en donde el mensaje que un visitante enviara le llegara por correo. Justo ahora, lo podría hacer en 10 minutos, pero en aquellos tiempos no.

El punto es que voy a responder aquí unas dudas que tal vez como principiantes tengamos:

¿Es fácil? claro que sí, es llamar a una función, pasarle argumentos y listo

¿Cómo sé si el mensaje se envió? la función devuelve un booleano indicando si se envió o no

¿Cómo sé si el mensaje llegó? eso es más difícil de saber, porque a veces los filtros de correo marcan a nuestros mensajes como spam; pero bueno, puedes probar primero enviando un mensaje a tu correo personal.

¿Puedo enviar correos a cualquier dirección? claro, no importa si es gmail, hotmail o de un dominio personalizado.

¿PHP ya viene con un servidor de correos? No. Tú tienes que instalar un servidor de correos, lo cual es una historia aparte; pero tengo buenas noticias para ti: en el mundo del desarrollo web, la mayoría de veces se programa en un hosting compartido; que es un servidor que compartes con otras personas que ya tiene todo configurado e instalado; PHP, apache y esas cosas; incluso un servidor de correos. Está listo para enviar correos electrónicos y para que le pongas tus scripts.

En caso de que no tengas un hosting compartido, no te preocupes; pronto traeré un tutorial de cómo instalar un servidor de correos en Linux.

Requisitos y recomendaciones

Antes de comenzar, recuerda tener instalado PHP y Apache con XAMPP. Igualmente te recomiendo que instales este programa para ver los correos que se envían, en lugar de ocupar tu dirección verdadera.

Enviar correo electrónico

La forma más simple es poner, en un script de PHP lo siguiente:

<?php
/*
    Enviar correo desde PHP con mail
*/
$resultado = mail("tu_correo@dominio.com", "Yo soy el asunto del correo", "Yo soy el mensaje");
if ($resultado) {
    echo "El correo fue enviado";
} else {
    echo "El correo no fue enviado";
}

Si lo pones en un servidor que tenga un servidor de correo instalado, o desde tu PC con el programa que dejé al inicio, verás que el correo se envía (obviamente poniendo una dirección real). Eso es lo mínimo que necesitas para enviar un correo con PHP.

Ahora que ya comprobaste que se pudo (revisa la carpeta de spam si lo enviaste a una dirección) es hora de hacer cosas un poco más avanzadas; no tan avanzadas, pero verás que son interesantes.

Poner asunto con caracteres especiales

Esto me pasó en producción alguna vez. El asunto era algo como “Activación de tu cuenta en bla bla”. Lo que pasaba era que la o acentuada o con tilde no se mostraba; investigando un poco encontré una función que se encarga de arreglar esto.

Lo que se hace es codificar el encabezado o algo así, la función queda de la siguiente manera:

<?php
function limpiarAsunto($asunto)
{
    $cadena = "Subject";
    $longitud = strlen($cadena) + 2;
    return substr(
        iconv_mime_encode(
            $cadena,
            $asunto,
            [
                "input-charset" => "UTF-8",
                "output-charset" => "UTF-8",
            ]
        ),
        $longitud
    );
}

echo limpiarAsunto("Activación de tu cuenta para bla bla");
?>

Usamos substr porque la función regresa una cadena que tiene “Subject: “, y no queremos eso, queremos lo que sigue después.

Para usar esta función, hacemos esto:

mail("correo@dominio.com", limpiarAsunto("El asunto del correo"), "El mensaje" );

Establecer el remitente a un nombre personalizado

Otra de las cosas que son necesarias al enviar un correo electrónico es poner un remitente personalizado; que aunque nuestro dominio sea parzibyte.me, en el remitente diga “Luis Cabrera” (por ejemplo). Para ello, ponemos algunos encabezados separados por \r\n y los mandamos como cuarto argumento:

<?php
function limpiarAsunto($asunto)
{
    $cadena = "Subject";
    $longitud = strlen($cadena) + 2;
    return substr(
        iconv_mime_encode(
            $cadena,
            $asunto,
            [
                "input-charset" => "UTF-8",
                "output-charset" => "UTF-8",
            ]
        ),
        $longitud
    );
}

$asunto = limpiarAsunto("Boletín semanal");
$destinatario = "staff@gmail.com";

$encabezados = "MIME-Version: 1.0" . "\r\n";

# ojo, es una concatenación:
$encabezados .= 'From: Luis Cabrera<contacto@parzibyte.me>' . "\r\n";

$mensaje = "Hola, este es un mensaje";
$resultado = mail($destinatario, $asunto, $mensaje, $encabezados); #Mandar al final los encabezados
if ($resultado) {
    echo "Correo enviado";
} else {
    echo "Correo NO enviado";
}

Es un poco complicado al inicio, pero no tanto. Lo importante es que si mandamos más encabezados, los separemos con \r\n.

Aquí estamos enviando la versión de MIME y también el remitente, puedes cambiarlo si gustas, pero en el correo pon uno de tu dominio. En mi caso el correo llega así:

Correo enviado desde PHP con asunto y caracteres especiales

Ahí mismo se ve que aunque el asunto tiene acentos, los mismos se muestran correctamente.

Cortar el mensaje para evitar truncarlo

El texto del mensaje debe ir separado en líneas de 70 caracteres. Para ello ya existe una función llamada wordwrap:

$mensaje = wordwrap($mensaje, 70, "\r\n");

Enviar HTML

Actualización: si experimentas errores enviando HTML, omite la parte en donde cortas el mensaje con wordwrap; manda directamente todo el contenido, sin saltos de línea ni cortes.

Para terminar y poner todo junto, vamos a enviar un correo electrónico con un poco de HTML. El código es este:

<?php
function limpiarAsunto($asunto)
{
    $cadena = "Subject";
    $longitud = strlen($cadena) + 2;
    return substr(
        iconv_mime_encode(
            $cadena,
            $asunto,
            [
                "input-charset" => "UTF-8",
                "output-charset" => "UTF-8",
            ]
        ),
        $longitud
    );
}

$asunto = limpiarAsunto("Boletín semanal");
$destinatario = "staff@gmail.com";

$encabezados = "MIME-Version: 1.0" . "\r\n";

# ojo, es una concatenación:
$encabezados .= "Content-type:text/html; charset=UTF-8" . "\r\n";
$encabezados .= 'From: Luis Cabrera<contacto@parzibyte.me>' . "\r\n";

$mensaje = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>Este es un mensaje</title>
    <style type="text/css">
        h1{
            color: #8bc34a;
        }
        p{
            font-size: 1rem;
        }
        img{
            width: 10rem;
            height: 10rem;
        }
    </style>
</head>
<body>
<h1>Este es un t&iacute;tulo con estilo</h1>
<p>Hola, mundo. Este es un mensaje largo</p>
<p>
Tambi&eacute;n se pueden poner links: <a href="https://parzibyte.me/blog">parzibyte.me</a>,cosas
como <strong>negritas</strong> o <code>c&oacute;digo</code>. Es decir, cualquier cosa que tenga que ver con HTML
puede enviarse en los correos.
</p>
<h1>Una imagen...</h1>
<img src="https://github.com/parzibyte.png">
</body>';
$mensaje = wordwrap($mensaje, 70, "\r\n");
$resultado = mail($destinatario, $asunto, $mensaje, $encabezados); #Mandar al final los encabezados
if ($resultado) {
    echo "Correo enviado";
} else {
    echo "Correo NO enviado";
}

Aunque su estructura se ve mal, funciona. Ya luego podemos mejorar eso con un motor de plantillas o separando conceptos; el punto es renderizar el HTML y los estilos, así como el mensaje.

Como se puede ver, agregamos estilos CSS en la etiqueta <head>. Desafortunadamente para los programadores, y afortunadamente para el usuario final, no se pueden incluir estilos con una etiqueta <link>. Esto es por la seguridad de que no se pueden incluir contenidos de enlaces externos.

El mensaje que llega es este:

Correo electrónico con HTML e imágenes desde PHP con mail
Correo electrónico con HTML e imágenes desde PHP con mail

Esa es la captura del programa que captura mensajes de correo, pero en Gmail se ve distinto, como en la captura del inicio.

Conclusión

Así de simple es enviar correos con PHP. Podemos enviar HTML, texto plano, imágenes, estilos y más cosas. Más adelante traeré ejemplos de cómo enviar adjuntos, prevenir inyecciones de encabezados, etcétera.

Si hay dudas ahí están los comentarios.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

2 comentarios en “Enviar correo electrónico con HTML desde PHP”

  1. Pingback: Obtener IP de un usuario a través de un correo electrónico - Parzibyte's blog

  2. Pingback: Configurar servidor SMTP para pruebas de PHP - Parzibyte's blog

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *