Gestor de Correos

PostManager

El envío de correos corporativos a un colectivo es una herramienta que se usa en todas las empresas y en los proyectos, pues es el medio de envío de boletines, etc., mensajes que se desea compartir con un conjunto amplio de personas.

Hay muchas herramientas Open Source que hace esta función, pero aquellos que trabajamos con PHPRunner nos gusta verlo en esta plataforma y sobre todo, integrado con nuestros aplicativos.

Requisitos de la solución

Cuando me he planteado hacer este ejemplo, me marqué estos objetivos:

  • Debía de utilizar una cuenta de Gmail (XOAUTH2). Este tipo de autenticación es el requerido por las plataformas más seguras de gestión de correos electrónicos.
  • Debía de utilizar un editor de mensajes muy completo, con el fin de hacer mensajes muy ricos en características gráficas, con un gestor de imágenes o multimedia.
  • Debería poder utilizar texto escritos en Word.
  • Debería de poder personalizar el mensaje con datos del destinatario (nombre, apellidos email, etc.)
  • Debería poder enviar ficheros adjuntos.
  • Debería poder seleccionar (de formas múltiples) la lista de destinatarios.
  • Debería ser multi-idioma (inglés y español) en todos sus componentes. Esto posibilita que a otros idiomas sea fácil adaptarlo.

Como en todas los ejemplos  que pongo en el Blog, estos no son aplicaciones, si no que son ejemplos para que cada uno lo personalice y lo integre en sus soluciones.

 

Entorno de DEMO

DEMO: https://fhumanes.com/postmanager

Por cambios en las políticas de las cuentas de GMAIL, se ha solicitado una password de aplicación y todo funciona bien.

Usuario:  admin
Password: admin

El ejemplo lo he limitado a un máximo de 5 Contactos, para que no se utilice como SPAM. Se pueden borrar Contactos, para que cada usuario ponga en ellos una cuenta de email donde quiera ver el resultado del email.

 

Descripción funcional

Como el objetivo no es hacer un producto “acabado” si no que sea reutilizable para personalizar por los desarrolladores de PHPRunner, voy a hacer especial referencia a las dos entidades en las que he trabajado el ejemplo.

Pasos para construir un correo electrónico:

Se puede crear, editar y visualizar el Mensaje. Este tiene un asunto, un cuerpo del mensaje y los adjuntos.

Se utiliza para el cuerpo del mensaje el editor (rico) que viene con PHPRunner, Innovaeditor y el gestor de ficheros que viene con él. En la parte técnica se explicará los cambios que se han hecho en este editor.

En el texto se utilizará estas etiquetas que será sustituidas con los datos del destinatario:

  • {name} .- Nombre del contacto
  • {surname}.- Apellidos del contacto
  • {email}.- Correo electrónico del contacto

También, en la opción de “pegar” tiene una opción para mejorar el HTML de los documentos Word. Con esta funcionalidad, se puede escribir los mensajes en Word y “pegar” en el cuerpo de los mensajes.

Una vez tenemos el mensaje pasamos a seleccionar los contactos destinatarios y para ello vamos a la opción de “Contactos”.

En esta pantalla he puesto varias formas de seleccionar la lista de los Contactos, aunque en ambas formas se inicia con el clic del botón “Select for Post” (1).

  1. Se pueden seleccionar los Contactos con el check (2) que tiene cada registro de Contacto.
  2. Si no existe selección, se recogen todos los registros mostrados de acuerdo a la seleccione de filtros (3) o búsqueda (4) que se hayan indicado.

Partiendo de la selección, saldrá una pantalla popup en donde tendremos que indicar a qué mensaje se asocia la lista de contactos seleccionados. Se puede hacer esta operación varias veces.

Una vez hechas estas operaciones, asociado a los Mensajes tendremos la lista de contactos que hemos creado para el mensaje.

El envío de los email se inicia con el clic del botón “Send Email” (1).

También aquí hay dos métodos de indicar a quienes de la lista hay que enviar el mensaje:

  1. Se envía a los Contacto que tienen el check (2). El mensaje se envía aunque ya se haya enviado anteriormente.
  2. Si no se ha puesto el check a ningún Contacto se envía a todos los usuarios de la lista siempre que no se haya enviado con anterioridad. Esto se controla porque la fecha de envío (3) está a nulo, si no se ha enviado el mensaje.

 

Datos técnicos de la solución

El modelo de datos que utiliza el ejemplo es:

Como he indicado es muy simple. El objetivo es que se personalice con las necesidades de cada organización.

Como en casi todos los ejemplos que hago, se dispone de una opción de configuración para personalizar los datos de la instalación. Creo que las etiquetas son autoexplicativas.

 

Adaptaciones del editor Innovaeditor

Al revisar la solución, sobre todo en la gestión de recursos (imágenes, video, etc.) y el uso que de forma estándar utiliza PHPRunner, se identificó:

  • No hay forma (desde PHPRunner) personalizar el directorio donde se ubican los recursos.
  • El gestor de recursos se puede utilizar sin que se controle el acceso (un problema grave de seguridad)
  • Aunque el editor tiene la posibilidad de ser multi-idioma, no se puede configurar desde PHPRunner.

Los cambios que he realizado, en la ubicación de la instalación de PHPRunner (en mi caso C:\Program Files\PHPRunner10.4\source\plugins\innovaeditor) son:

. En directorio “C:\Program Files\PHPRunner10.4\source\plugins\innovaeditor\assetmanager”:

Fichero “assetmanager.php”, se añaden estas líneas.

// Control environment PHPRunner
$name_file = __DIR__."/phprunner_setting.php";
if (file_exists($name_file)) {
    require __DIR__."/phprunner_setting.php";
}

Se ha añadido el fichero “phprunner_setting.php” con este contenido:

<?php
require_once("../../../include/dbcommon.php"); // DataBase PHPRunner
// Control user login
if (!isset($_SESSION["UserID"])) {
  die("Please connect aplications");
}
// Confgig assetmanager
$bReturnAbsolute=false;
$sBaseVirtual0=$_SESSION['config'][array_search('EDITOR_BaseVirtual0', array_column($_SESSION['config'], 'name'))][value];
$sBase0=$_SESSION['config'][array_search('EDITOR_Base0', array_column($_SESSION['config'], 'name'))][value];
if ($_SESSION["language"] == "Spanish") {
    $sLang="es-ES";
} else {
    $sLang="en-US";
}

En directorio “C:\Program Files\PHPRunner10.4\source”:

Fichero innova.php (es para la gestión de multi-idioma)
En versión PHPRunner 10.7 se «ha perdido» este fichero por lo que ya no es posible configurar el idioma del interface de este editor.

 if ($_SESSION["language"] == "Spanish") {
    $sLang="es-ES";
    $LangScript = '<script type="text/javascript" src="'. projectURL() . ("plugins/innovaeditor/scripts/language/".$sLang."/editor_lang.js").'"></script>';
} else {
    $sLang="en-US";
    $LangScript='';
}
       
echo '<html>
            <body style="margin:0;">
            <form name="innovaform" '.$onsubmit.'>'.
            $LangScript.
            '<script type="text/javascript" src="'. projectURL() . ("plugins/innovaeditor/scripts/innovaeditor.js").'"></script>
            <textarea id="'.$cfield.'" name="'.$cfield.'" style="width:100%; height:'.($nHeight).'px;">';

 

Función de envío de correos

Se utiliza la librería PHPMAILER, en su versión 6.1. esta es la última versión y no es la misma que incorpora el producto PHPRunner.

El código, con sus comentarios es el fichero “send_mail.php”:

<?php
// For send of email selected
// $_SESSION['mail_select']  Id of email_contact selected
// $_SESSION['mail_where']  Condition where last select of email_contact
$select_record = $_SESSION['mail_select'];
$count = count($_SESSION['mail_select']);
if ($count == 0 ) { //  All Record of List
      $sql=$_SESSION['mail_sql'];
      if ($_SESSION['mail_where'] <> ''){
            $sql.= " and dateEmail is null";
      } else {
            $sql.= " where dateEmail is null";
      }
      $resql=db_query($sql,$conn);
      while($row=db_fetch_array($resql))
            {
                  $select_record[] = $row['idemail_contact'];
            }
      $_SESSION['mail_select'] = $select_record;
}
// field of Config
$GMAIL_Username = $_SESSION['config'][array_search('GMAIL_Username', array_column($_SESSION['config'], 'name'))][value];
$GMAIL_Password = $_SESSION['config'][array_search('GMAIL_Password', array_column($_SESSION['config'], 'name'))][value];
$GMAIL_setFrom_email = $_SESSION['config'][array_search('GMAIL_setFrom_email', array_column($_SESSION['config'], 'name'))][value];$GMAIL_Username = $_SESSION['config'][array_search('GMAIL_Username', array_column($_SESSION['config'], 'name'))][value];
$GMAIL_setFrom_name = $_SESSION['config'][array_search('GMAIL_setFrom_name', array_column($_SESSION['config'], 'name'))][value];
$EDITOR_UrlBase0 = $_SESSION['config'][array_search('EDITOR_UrlBase0', array_column($_SESSION['config'], 'name'))][value];
$EDITOR_BaseVirtual0 = $_SESSION['config'][array_search('EDITOR_BaseVirtual0', array_column($_SESSION['config'], 'name'))][value];
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
require __DIR__.'/../phpmailer_6.1/autoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer;
// Activo condificacción utf-8
$mail->CharSet = 'UTF-8';
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
// SMTP::DEBUG_OFF = off (for production use)
// SMTP::DEBUG_CLIENT = client messages
// SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_OFF;
//Set the hostname of the mail server
$mail->Host = 'smtp.gmail.com';
// use
// $mail->Host = gethostbyname('smtp.gmail.com');
// if your network does not support SMTP over IPv6
//Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
$mail->Port = 587;
//Set the encryption mechanism to use - STARTTLS or SMTPS
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Username to use for SMTP authentication - use full email address for gmail
$mail->Username = $GMAIL_Username;
//Password to use for SMTP authentication
$mail->Password = $GMAIL_Password;
//Set who the message is to be sent from
$mail->setFrom($GMAIL_setFrom_email,$GMAIL_setFrom_name);
//Set an alternative reply-to address
// $mail->addReplyTo('[email protected]', 'First Last');
//Set the subject line
$mail->Subject = $masterData['subject'];
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$message = str_replace('"'.$EDITOR_BaseVirtual0,'"'.$EDITOR_UrlBase0,$masterData['message']);
// $mail->msgHTML($message);
// Attachments
$filesArray = my_json_decode($masterData['attachments']);
foreach ($filesArray as $File) {
      $mail->addAttachment(__DIR__."/../".$File["name"],$File["usrName"],'base64', $File["type"]);
}
$count_send = 0;
foreach ($_SESSION['mail_select'] as &$contact) {
      $sql = "SELECT contact.name, contact.surname, email_contact.email FROM contact join email_contact
                              on (contact.contact_id = email_contact.contact_contact_id and email_contact.idemail_contact = $contact)";
      $resql=db_query($sql,$conn);
      while($row=db_fetch_array($resql)) {
            $count_send = $count_send + 1;
            // Message customization
            $message0 = str_replace('{name}',$row['name'],$message);
            $message0 = str_replace('{surname}',$row['surname'],$message0);
            $message0 = str_replace('{email}',$row['email'],$message0);
            $mail->msgHTML($message0);
            //  $mail->AltBody = $mail->html2text($message0); // Text plain alternative
            $mail->addAddress($row['email'], $row['name'].' '.$row['surname']);
            $status = $mail->send();
            // Updating the email sending record
            $sql2 = "update email_contact set dateEmail = now(), Status = '$status' where idemail_contact = $contact"; 
            $resql2=db_query($sql2,$conn);
      }
}
// delete variables of session
unset($_SESSION['mail_select']); 
unset($_SESSION['mail_where']);
?>

 

Configuración de la cuenta de Gmail

Para que Gmail nos permita conectarnos es necesario que se configure el “Acceso de aplicaciones pocos seguras”.

Para cualquier duda o explicación, contactar conmigo a través de email [email protected]

En el artículo os dejo todos los fuentes, para que los descarguéis y los adaptéis a vuestros equipos.

 

Blog personal para facilitar soporte gratuito a usuarios de React y PHPRunner