Correos electrónicos con PHPMailer

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail
Correos con PHP

Correos con PHP

El envío de correos electrónicos es fundamental en cualquier aplicativo web moderno. Es normal que, según los procesos que se lleven a cabo, sea necesario que la aplicación le envíe al usuario determinados correos, avisándole, por ejemplo, de que hay nuevos contenidos de su interés, o de que tiene tales o cuales opciones disponibles, o de lo que sea.

Cuando el correo es sólo un texto plano no hay problema. La función mail() de PHP cumple de sobra con este cometido.

La cuestión es que esos correos son muy pobres a la vista. No despiertan ningún interés en el usuario y lo normal es que acabe borrándolos sin leerlos siquiera o, peor aún, que ponga a nuestros envíos en la lista de spam, porque le molestan y tiene la sensación de que no le aportan nada.

En cambio, si envías un correo enriquecido con HTML, imágenes, enlaces, archivos adjuntos, etc. el correo resulta más llamattivo, más atractivo y e mucho más fácil captar la atención del destinatario.

EL PAQUETE PHPMailer

PHPMailer es una clase PHP que ha sido concebida para diseñar nuestros correos electrónicos de una forma fácil y rápida, con todas las funcionalidades que podemos necesitar. Es open source, lo que quiere decir que el código es abierto, su descarga y uso es completamente gratuito (no existe eso de demo, o trial, o algo de eso) y es muy fácil de implementar en nuestros proyectos. Además, es robusto y fiable.

Lo primero que puedes hacer es descargártelo de este enlace.

Una vez descargado descomprímelo en un directorio al que puedes llamar php_mailer y cópialo dentro del directorio de tu proyecto. Yo suelo incluir estas cosas en un directorio al que llamo includes, y así las tengo organizadas, disponibles para toda la aplicación. Así pues, la ruta del paquete en tu proyecto podría ser, por ejemplo, proyecto/includes/php_mailer/.

Dentro del directorio proyecto vamos a crear un directorio llamado imagenes, en el que almacenaremos una imagen para usar en nuestras pruebas. La llamaremos imagen.png. La ruta completa será, por tanto, proyecto/imagenes/imagen.png.

También tendremos un archivo que usaremos para hacer pruebas de envío de adjuntos. Lo guardaremos en un directorio llamado adjuntos y su nombre será adjunto.pdf. La ruta completa será proyecto/adjuntos/adjunto.pdf.

Dentro del directorio proyecto crearemos un script llamado index.php, que será el que nos envíe correos para probar el funcionamiento de PHPMailer. El esquema de nuestro escenario de pruebas queda, por lo tanto, como ves en la imagen reproducida a continuación:

Esquema del proyecto para probarPHPMailer

Esquema del proyecto para probarPHPMailer

 OPCIONES PARA LAS PRUEBAS

Si tienes contratado algún alojamiento de Internet (los hay muy asequibles) puedes subir toda la estructura de ficheros al servidor remoto, dentro de un directorio al que llamaremos pruebas, por ejemplo, y hacer que desde allí se envíen los correos a alguna cuenta tuya personal. Esta es la opción que yo te recomiendo. Si no tienes hosting remoto, siempre puedes instalar un servidor de correo local en tu ordenador. Al igual que con el servidor web de XAMPP, tu equipo será servidor y cliente a la vez. Si vas a elegir esta opción, mira este artículo, para saber cómo instalarte un servidor de correo.

EMPEZANDO CON PHPMailer

Vamos a empezar a escribir nuestro script index.php para mandarnos correos de pruebas, para ver cómo funciona la clase PHPMailer. Por supuesto, lo primero de todo es incluir el paquete en nuestro script, así:

require ('includes/php_mailer/PHPMailerAutoload.php');

A continuación crearemos un objeto de la clase PHPMailer, que será el que usemos para mandar correos. Lo haremos así:

$objetoCorreo = new PHPMailer;

Ahora es el momento de averiguar si el servidor que vamos a usar permite o no el envío directo de correos por SMTP. Si tenemos nuestro hosting en un servidor compartido, es probable, cómo es mi caso, que el proveedor (la empresa que gestiona el servicio) no permita el uso directo de este protocolo, por cuestiones de seguridad. No hay problema. Con PHPMailer podemos enviar correos igualmente, aunque la forma de hacerlo presenta algunas diferencias. Lo primero que haremos en ponernos en contacto con nuestro proveedor, para que nos informe de si podemos o no enviar correos por SMTP. Si nos dicen que sí podemos hacerlo, incluiremos las siguientes líneas:

$objetoCorreo->isSMTP();
$objetoCorreo->Host = 'smtp.proveedor.com'; // El proveedor nos proporciona este dato.
$objetoCorreo->SMTPAuth = true; // El proveedor nos proporciona este dato.
$objetoCorreo->SMTPSecure = 'tls'; // Puede ser tls o ssl. El proveedor nos proporciona este dato.
$objetoCorreo->Port = 587; // El proveedor nos proporciona este dato.

Si el proveedor nos informa de que NO nos permite acceder a SMTP, simplemente omitimos estas líneas (o las comentamos).

La siguiente línea la incluiremos también en cualquier caso. Si se produce un error durante el envío de correos, nos permitirá obtener información muy detallada.

$objetoCorreo->SMTPDebug = 3;

Podemos poner cualquier valor por encima de 2. Con 3 ya nos vale.

Las siguientes líneas que vamos a incluir, con o sin SMTP (eso ya es irrelevante), son las siguientes:

$objetoCorreo->Username = 'mi.cuenta@mi.servidor.com';
$objetoCorreo->Password = 'mi_contraseña';

Pondremos en estas dos últimas nuestra cuenta de correo electrónico en el servidor, y la contraseña que tengamos.

Lo siguiente que haremos será establecer la cuenta y el nombre que queremos que aparezca en el mensaje como remitente (From). Lo haremos así:

$objetoCorreo->setFrom('cuenta.de.remite@eldesvandejose.com', 'Remitente');

Evidentemente tu pondrás tu cuenta de correo electrónico, y el nombre que quieras que el destinatario vea.

Ahora pondremos el correo y el nombre del destinatario, así:

$objetoCorreo->addAddress('destinatario@destino.com', 'Destinatario');

Podremos añadir tantos destinatarios cómo queramos, poniendo esta línea por cada uno.

Por último, estableceremos la cuenta de correo y el nombre al que el usuario podrá enviar una respuesta, si pulsa el botón Reply to:, Responder, Responder a: o similar de su correo electrónico, así:

$objetoCorreo->addReplyTo('cuenta.de.respuesta@mi.servidor.com', 'Respuestas');

Como en el caso anterior, podremos poner todas las cuentas de respuesta que queramos.

En estos tres métodos (PHPMailer::setFrom(), PHPMailer::addAddress() y PHPMailer::addReplyTo()) es opcional que el segundo parámetro sea una cadena vacía si no lo conocemos o, simplemente, no queremos incluirlo.

Vamos a indicarle a PHPMailer que el correo irá en formato HTML. Esto es bastante obvio ya que, para enviar un correo cutre en texto plano lo hubiéramos mandado con la función mail() de PHP y no nos estaríamos complicando la vida, pero, aún así, debemos indicarlo, con la siguiente línea:

$objetoCorreo->isHTML(true);

Ahora establecemos el asunto del mensaje, así:

$objetoCorreo->Subject = 'El asunto de nuestro mensaje';

Ahora creamos el cuerpo del mensaje (vamos, el mensaje en sí mismo, para entendernos; lo que le queremos mandar al destinatario). Lo hacemos así:

$objetoCorreo->Body = 'Este es el cuerpo del mensaje <b>y esto está en negrita</b>';

Cómo ves, se pueden incluir tags HTML. Este primer mensaje es muy simplón, para que veamos el mecanismo. Luego montaremos uno un poquito mas molón.

También esta bien poder incluir una versión del correo en texto plano, por si el cliente de correo del destinatario no acepta HTML. Aunque hoy día todos los programas para ver correos lo aceptan, en las empresas grandes es costumbre limitarlo, por “cuestiones de seguridad” (dicen). En ese caso, al destinatario le aparecerá un cuerpo de mensaje alternativo. Lo fjamos así:

$objetoCorreo->AltBody = 'Este es el cuerpo del mensaje y esto estaría en negrita si tus jefes no fueran unos cutres y te dejaran ver tus correos en HTML.';

Y ya lo tenemos todo. Solo nos falta enviar el correo con el método PHPMailer::send(), así:

$objetoCorreo->send()

Este método no sólo intenta enviar el mensaje, sino que devuelve un valor booleano que será true si se ha podido enviar correctamente, o false, si no se ha podido enviar. Una de las razones de que no se pueda enviar un mensaje es que hayamos tecleado más la cuenta de destino, o que hayamos configurado PHPMailer para usar SMTP, pero el servidor nuestro no lo permita. En todo caso, podemos usar este valor para que se nos informe de lo ocurrido, así:

if(!$objetoCorreo->send()) {
    echo 'No se pudo enviar el mensaje';
    echo 'Detalles del error: '.$objetoCorreo->ErrorInfo;
} else {
    echo 'Se ha enviado el mensaje';
}

La propiedad PHPMailer::ErrorInfo nos devuelve información detallada sobre el error (si es que este se ha producido) si establecimos un valor superior a 2 en la propiedad PHPMailer::SMTPDebug que vimos un poco más arriba.

UN CORREO MÁS ELABORADO

Con el fichero index.php que hemos construido línea a línea en el apartado anterior hemos conseguido mandar un correo HTML a través de PHPMailer. Pero se trata de mandar correos más elaborados. En este apartado vamos a ver una versión mucho más potente de nuestro script. El listado es el siguiente:

Si lo pruebas veras (si has puesto tu dirección real de destino), que te llega un correo como el que ves a continuación, con todo el HTML, la imagen incrustada, el fichero adjunto… Genial.

Un correo HTML completo, enviado con PHPMailer.

Un correo HTML completo, enviado con PHPMailer.

LOS MÉTODOS Y PROPIEDADES DE PHPMailer

Básicamente, ya sabemos cómo usar PHPMailer. En este apartado vamos a recopilar las propiedades y métodos que debemos conocer para configurar cualquier correo que necesitemos enviar desde nuestra web.

PROPIEDAD O
MÉTODO
FINALIDAD PARÁMETROS Y USO
SMTPDebug Establecer el nivel de información que queremos
cuando se producen errores.
Se le asigna un valor por encima de 2.
isSMTP() Indicar a PHP que nuestro servidor emplea SMTP No recibe argumentos.
Host Establecer cual es nuestro servidor SMTP. Se le asigna una cadena con el nombre del servidor SMTP.
SMTPAuth Indicar si nuestro servidor requiere autenticación SMTP Se le asigna un valor booleano.
SMTPSecure Indicar el tipo de seguridad de nuestro servidor SMTP. Una cadena indicando si la seguridad es ssl o tls.
Port Indicar el puerto por el que enviará nuestro servidor los correos. Un valor numérico entero.
Username Establecer nuestra dirección de correo electrónico. La dirección de correo que vamos a usar para mandar correos a los destinatarios.
Password Indicar nuestra contraseña Debemos autenticar nuestro correo electrónico.
CharSet Indicar la codificación en que se enviará el correo electrónico. Normalmente se establece UTF-8, para evitar problemas con letras acentuadas y otros caracteres especiales.
Subject Estableceremos el asunto del correo. Una cadena con el asunto del correo.
isHTML() Indicar que el correo es HTML. Recibe un solo argumento: un valor booleano que indica si el correo es HTML.
setFrom() Indicar la cuenta de correo y el remitente del correo. Recibe dos parámetros. El primero es la cuenta de correo del remitente (la nuestra, vamos). El segundo es el nombre con el que queremos que figure el remitente en el correo. En este último podemos poner una cadena vacía o ni siquiera aparecer; es opcional.
addAddress() Establecer el destinatario del correo. Recibe dos parámetros. El primero es la cuenta de correo del destinatario, y el segundo es su nombre (este último puede ser una cadena vacía o ni siquiera aparecer; es opcional). (1)
addReplyTo() Establecer el correo al que el usuario podrá responder mediante el botón que tienen, al efecto, los programas de correo electrónico. Recibe dos parámetros. El primero es la dirección a la que el destinatario responderá y el segundo el nombre que queremos que vea. Este último puede ser una cadena vacía o ni siquiera aparecer; es opcional.
addAttachment() Incluir uno o más archivos adjuntos al correo electrónico. Como argumento recibe el nombre del fichero que queremos adjuntar (incluyendo su ruta de ubicación en nuestro servidor, cómo has visto en el ejemplo del apartado anterior). Cómo segundo argumento, opcional, puedes poner un nombre con el que le llegará al destinatario. (2)
AddEmbeddedImage() Incluir imágenes que se integrarán con el contenido del correo, cómo hemos visto en el ejemplo del apartado anterior. Este método recibe hasta cinco parámetros, de los que sólo los dos primeros son obligatorios. (3)
SMTPKeepAlive Mantener activa la conexión SMTP. Si se van a enviar varios correos es conveniente, para evitar que se sobrecargue el servidor.  Le asignamos un valor booleano.
body Permite asignar el contenido del correo que queremos mandar. A esta propiedad le asignamos el contenido del correo que queremos mandar.
msgHTML() Este método es una alternativa al uso de la propiedad anterior. Es adecuado cuando vamos a enviar distintos correos a distintos destinatarios. Cómo argumento recibe el cuerpo del correo que vamos a enviar en ese momento.
AltBody Se usa para establecer un mensaje de texto plano alternativo que visualizarán los destinartarios cuyo programa cliente de correo no permita mostrar HTML. Se le asigna una cadena de texto plano.
ErrorInfo Esta propiedad contiene información detallada del error que se haya producido e impedido el envío, si es que se produce un error. No se le asigna nada. Ya contiene la información del error.
clearAddresses() Borra las direcciones de correo que tengamos como destinatarios, para poder establecerlas de nuevo (por ejemplo, si estamos recorriendo una matriz o base de datos con correos de destinatarios, borraremos las direcciones de aquellos a los que ya se haya enviado el correo, para cargar nuevas). (4)  No recibe argumentos.
clearAttachments() Quita los adjuntos que le hubiéramos asignado al correo, por si, después de enviarlo, queremos enviar otro sin adjuntos. No recibe argumentos.
isSendmail() Le indica a PHPMailer que use Sendmail como transporte de correos. Contactaremos con nuestro proveedor de servicios para saber si debemos o no usar Sendmail. No recibe argumentos.
addCC() Establece una dirección de destino a la que mandar una copia del correo. Como argumento, recibe la dirección a la que queremos mandar la copia. Opcionalmente, cómo segundo argumento, el nombre del destinatario de la copia. (1)
addBCC() Funciona del mismo modo que el anterior, para copias ocultas. Recibe los mismos argumentos que el anterior. (1)
send() Una vez configurado el correo, este método intenta mandarlo, si todo ha ido bien. (5) Devuelve un valor booleano, que será true si el correo se ha mandado correctamente, o false, si no se puedo enviar.

NOTAS

(1). Podemos repetir estos métodos tantas veces cómo necesitemos para enviar el mismo correo a varios destinatarios en una sóla operación. Por ejemplo, para madar el mismo correo a tres destinatarios, pondríamos:

$objetoDeCorreo->addAddress('destinatario.1@servidor.com', 'Destinatario 1');
$objetoDeCorreo->addAddress('destinatario.2@servidor.com', 'Destinatario 2');
$objetoDeCorreo->addAddress('destinatario.3@servidor.com', 'Destinatario 3');

Lo mismo es válido para los métodos addCC() y addBCC(), si los usamos.

(2). Evidentemente, la ruta es relativa a la ubicación de nuestro script de envío de correos, no a la ubicación de PHPMailer.

(3). Los argumentos que recibe son:

  • El nombre de la imagen, incluyendo la ruta relativa a la ubicación de nuestro script.
  • Un alias (llamado, en este contexto, cid) para luego poder referirnos a esta imagen en el HTML. Observa, en el ejemplo de este artículo, cómo hemos establecido el atributo src de img, al contruir el HTML. A continuación te reproduaco la línea, para que la veas:

<img src='cid:logo_php' align='left' border='0' hspace='10' />

  • Una pequeña descripción de la imagen.
  • La forma de codificarla para el envío..
  • El tipo MIME de la imagen.

(4). Evidentemente, este método borra las direcciones de destino del objeto de correo que estamos manipulando, no de la fuente de origen de los datos.

(5). Este método es, por supuesto, el último que se emplea, para mandar el correo cuando ya está todo configurado.

     

3 comentarios:

  1. Pingback: Gestión de dependencias en PHP: Composer » eldesvandejose.com

  2. Maite Rusciel

    Hola, se que este articulo es de hace un tiempo, pero estoy presentando un problemilla con phpmailer, tengo una funcion que le paso el asunto, cuerpo, direccion de email y nombre del destinatario para que envie un email, y lo hace a la perfecccion, el problema es que quiero enviar dos correo diferentes a destinatarios diferentes, llamo a la funcion dos veces con los respectivos datos de cada correo, pero me dice que no puede crear otra instancia de phpmailer y solo envia un correo, tiene alguna sugerencia para mi.

    • Hola.
      Depende de cual sea tu nivel de privacidad hay varias formas de hacerlo. Me explico. Si no te importa que un destinatario vea que también le envías el correo al otro, puuedes repetir el método addAddress(), añadiendo al correo tantos destinatarios como quieras. También puedes añadirlos como copias, con el método addCC() o con addBCC().
      Si lo que quieres es enviar el correo a un número n de destinatarios de forma individual, de tal modo que cada uno no sepa de los demás (que suele ser el caso más habitual), puedes, después del envío con el método send() eliminar el destinatario con removeAddress() y añadir el nuevo destinatario con addAddress(). Después, lanzas de nuevo el método send().

      Sin embargo, la mejor opción siempre es el desacoplamiento. Me explico. En una función metes el código para crear el objeto de la clase phpMailer, los métodos para añadir destinatarios, los métodos para crear el cuerpo y el asunto del mensaje y el método send(). A la función la llamas pasando todos los parámetros, y dejas que sea la función la que se ocupe de crear el objeto, montar el correo y mandarlo. De este modo, el objeto del correo sólo vive en la función. Cuando esta termina, es destruido de forma transparente (tú no tienes que hacer nada). Cuando la función es invocada de nuevo, se crea el objeto del nuevo correo. Lo que haces es recorrer la matriz de destinatarios con un bucle y, dentro de este, para caada destinatario invocas a la función. Esto último es lo que yo hago siempre en mis trabajos, y considero que es la mejor solución.

      Si empleas PHP 7 puedes considerar SwiftMailer como alternativa a phpMailer (en breve prepararé un artículo sobre esta herramienta). Sin embargo, si aún empleas PHP 5, SwiftMailer no te funcionará, y tendrás que usar phpMailer.

Deja un comentario

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