
En este blog, describiré el proceso que seguí para almacenar el cuerpo del correo electrónico en S3 (el Servicio de Almacenamiento Simple de Amazon) y los datos auxiliares en una tabla MySQL para facilitar la referencia cruzada.
En este blog, describiré el proceso que seguí para almacenar el cuerpo del correo electrónico en S3 (Servicio de Almacenamiento Simple de Amazon) y los datos auxiliares en una tabla MySQL para facilitar la referencia cruzada. En última instancia, este es el punto de partida para la base de código que incluirá una aplicación que permitirá la búsqueda fácil de correos electrónicos archivados, y luego mostrar esos correos electrónicos junto con los datos de eventos (registro). El código para este proyecto se puede encontrar en el siguiente repositorio de GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Aunque aprovecharé S3 y MySQL en este proyecto, de ninguna manera son estas las únicas tecnologías que se pueden usar para construir una plataforma de archivado, pero dada su ubicuidad, pensé que eran una buena opción para este proyecto. En un sistema de alto volumen a gran escala, usaría una base de datos de mayor rendimiento que MySQL, pero para este proyecto de muestra, MySQL es perfecto. Para las organizaciones que consideran PostgreSQL como su elección de base de datos para archivo, es esencial implementar procedimientos adecuados de respaldo y restauración para mantener la integridad de los datos en sistemas de producción.
He detallado a continuación, los pasos que tomé en esta primera fase del proyecto:
Creación del correo electrónico duplicado para archivado
Usar las funciones de archivado y retransmisión entrante de SparkPost para enviar una copia del correo electrónico original nuevamente a SparkPost para su procesamiento en una estructura JSON, luego enviada a un recolector de webhook (aplicación)
Desmantelar la estructura JSON para obtener los componentes necesarios
Enviar el cuerpo del correo electrónico a S3 para su almacenamiento
Registrar una entrada en MySQL para cada correo electrónico para la referencia cruzada
Creando un Duplicate del Email
En SparkPost, la mejor manera de archivar un correo electrónico es crear una copia idéntica del correo específicamente diseñada para propósitos de archivo. Esto se hace utilizando la función de Archivo de SparkPost. La función de Archivo de SparkPost le da al remitente la capacidad de enviar una copia duplicada del correo a una o más direcciones de correo electrónico. Este duplicado utiliza los mismos enlaces de seguimiento y apertura que el original. La documentación de SparkPost define la función de Archivo de la siguiente manera:
Los destinatarios en la lista de archivo recibirán una réplica exacta del mensaje que fue enviado a la dirección RCPT TO. En particular, cualquier enlace codificado destinado al destinatario RCPT TO será idéntico en los mensajes de archivo.
La única diferencia entre esta copia de archivo y el correo original RCPT TO es que algunos de los encabezados serán diferentes, ya que la dirección de destino para el correo de archivo es diferente, ¡pero el cuerpo del correo será una réplica exacta!
Si deseas una explicación más profunda, aquí hay un enlace a la documentación de SparkPost sobre cómo crear copias duplicadas (o de archivo) de un correo. Ejemplos de encabezados X-MSYS-API para este proyecto se muestran más adelante en este blog.
Hay una advertencia a este enfoque; mientras que toda la información del evento en el correo original está ligada tanto a un transmission_id como a un message_id, no hay información en el evento de retransmisión entrante (el mecanismo para obtener y difundir el correo de archivo) para el correo duplicado que se vincule a uno de esos dos id’s y, por lo tanto, la información del correo original. Esto significa que necesitamos colocar datos en el cuerpo del correo y en el encabezado del correo original como una forma de unir todos los datos de SparkPost del correo original y el de archivo.
Para crear el código que se coloca en el cuerpo del correo, usé el siguiente proceso en la aplicación de creación de correos.
En algún lugar del cuerpo del correo, coloqué la siguiente entrada de inserción:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Luego creé un código único y reemplacé el campo <<UID>>:$uid = md5(uniqid(rand(), true)); $emailBody = str_replace(“<<UID>>,$uid,$emailBody);
Aquí hay un ejemplo de salida:
<input name="ArchiveCode" type="hidden" value="00006365263145">
Luego, me aseguré de agregar el $UID al bloque meta_data del encabezado X-MSYS-API. Este paso se asegura de que el UID esté incrustado en cada salida de evento para el correo original:
Ahora tenemos una manera de unir todos los datos del correo original al cuerpo del correo de archivo.
Obteniendo la versión Archive
Obteniendo el email duplicado en una estructura JSON
En la primera fase de este proyecto, todo lo que estoy almacenando es el formato de correo electrónico rfc822 en S3 y algunos campos de descripción de alto nivel en una tabla SQL para búsqueda. Dado que SparkPost enviará los datos del correo electrónico en una estructura JSON a mi plataforma de archivo a través de flujos de datos webhook, construí una aplicación (a menudo referida como un collector) que acepta el flujo de datos Relay_Webhook.
Cada paquete del SparkPost Relay_Webhook contendrá la información de un correo electrónico duplicado a la vez, por lo que desglosar la estructura JSON en los componentes específicos para este proyecto es bastante sencillo. En mi código PHP, obtener el correo electrónico con formato rfc822 fue tan fácil como las siguientes líneas de código:
Parte de la información que quiero almacenar en mi tabla SQL reside en un array de campos de encabezado. Así que escribí una pequeña función que acepta el array de encabezado y recorre el array para obtener los datos en los que estaba interesado en almacenar:
Ahora que tengo los datos, estoy listo para almacenar el cuerpo en S3.
Almacenar el correo electrónico duplicado en S3
Lamento decepcionarte, pero no voy a ofrecer un tutorial paso a paso sobre cómo crear un bucket de S3 para almacenar el correo electrónico, ni voy a describir cómo crear la clave de acceso necesaria que necesitarás en tu aplicación para subir contenido a tu bucket; hay mejores tutoriales sobre este tema de los que yo podría escribir. Aquí tienes un par de artículos que pueden ayudar:
https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/
Lo que haré es señalar algunas de las configuraciones que elegí para un proyecto como este.
Control de Acceso. No solo necesitas configurar la seguridad para el bucket, sino que necesitas establecer los permisos para los propios elementos. En mi proyecto, utilizo una política pública de lectura muy abierta porque los datos de muestra no son personales y quería un acceso fácil a los datos. Probablemente querrás un conjunto de políticas ACL mucho más estrictas. Aquí hay un buen artículo sobre configuraciones de ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Archivando el Archivo. En S3 hay algo llamado Gestión del Ciclo de Vida. Esto te permite mover datos de un tipo de clase de almacenamiento de S3 a otro. Las diferentes clases de almacenamiento representan la cantidad de acceso que necesitas a los datos almacenados, con costos más bajos asociados al almacenamiento al que accedes menos. Un buen documento sobre las diferentes clases y cómo transitar entre ellas se puede encontrar en una guía de AWS llamada, Transitioning Objects. En mi caso, elegí crear un ciclo de vida que moviera cada objeto de Standard a Glacier después de un año. El acceso a Glacier es mucho más barato que el archivo estándar de S3 y me ahorrará dinero en costos de almacenamiento.
Una vez que tengo el bucket de S3 creado y mis configuraciones en su lugar, S3 está listo para que suba el correo electrónico conforme a rfc822 que obtuve del flujo de datos SparkPost Relay Webhook. Pero antes de subir el contenido del correo electrónico a S3, necesito crear un nombre de archivo único que usaré para almacenar ese correo electrónico.
Para el nombre de archivo único, voy a buscar en el cuerpo del correo electrónico el id oculto que la aplicación remitente colocó en el correo y usar ese id como el nombre del archivo. Hay maneras más elegantes de extraer el connectorId del cuerpo html, pero por simplicidad y claridad voy a usar el siguiente código:
* asumimos que $inputField contiene el valor “ArchiveCode” y fue encontrado en mi archivo config.php.
Con el UID, podemos crear el nombre del archivo que se usará en S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Ahora puedo abrir mi conexión a S3 y subir el archivo. Si miras el archivo s3.php en el repositorio de GitHub, verás que se necesita muy poco código para subir el archivo.
Mi último paso es registrar esta entrada en la tabla MYSQL.
Almacenando los Meta Data en MySQL
Recopilamos todos los datos necesarios en un paso anterior, por lo que el paso de almacenamiento es fácil. En esta primera fase, elegí construir una tabla con los siguientes campos:
Una entrada de campo automatizada para fecha/hora
La dirección de correo electrónico de destino (RCPT_TO)
La marca de tiempo del encabezado de la fecha del correo electrónico
El encabezado SUBJECT
El encabezado de la dirección de correo electrónico FROM
El directorio utilizado en el bucket S3
El nombre de archivo S3 para el correo electrónico archivado
La función llamada MySQLLog dentro del archivo de aplicación upload.php atraviesa los pasos necesarios para abrir el enlace a MySQL, inyectar la nueva fila, probar los resultados y cerrar el enlace. Agrego otro paso por si acaso, que es registrar estos datos en un archivo de texto. ¿Debería hacer mucho más registro para errores? Sí. Pero quiero mantener este código ligero para permitirle ejecutar extremadamente rápido. A veces este código se llamará cientos de veces por minuto y necesita ser lo más eficiente posible. En futuras actualizaciones, agregaré código auxiliar que procesará las fallas y enviará esos errores por correo electrónico a un administrador para su monitoreo.
En resumen
Así que, en unos pocos pasos bastante sencillos, pudimos recorrer la primera fase de construcción de un sistema robusto de archivo de correos electrónicos que guarda el duplicado del correo en S3 y referencia cruzada de datos en una tabla MySQL. Esto nos dará una base para el resto del proyecto que se abordará en varios futuros posts.
En futuras revisiones de este proyecto, esperaría:
Almacenar todos los eventos de registro del correo original
Enviar errores de almacenamiento a un administrador cuando ocurra una falla en la carga o registro
Minimizar la complejidad del colector.
Agregar una interfaz de usuario para ver todos los datos
Soportar la capacidad de reenviar el correo
Mientras tanto, espero que este proyecto haya sido interesante y útil para usted; feliz envío.