
Con el aumento del uso del correo electrónico en entornos regulatorios, he decidido que es momento de iniciar un nuevo proyecto que reúna todo esto con ejemplos de código sobre cómo almacenar el cuerpo del correo electrónico y todos sus datos asociados.
Hace aproximadamente un año escribí un blog sobre cómo recuperar copias de correos electrónicos para archivo y visualización, pero no abordé el almacenamiento actual del correo electrónico o los datos relacionados, y recientemente escribí un blog sobre el almacenamiento de todos los datos del evento (es decir, cuándo se envió el correo electrónico, aperturas, clics, rebotes, cancelaciones de suscripción, etc.) en un correo electrónico con el propósito de auditoría, pero elegí no crear ningún código de apoyo.
Con el aumento del uso del correo electrónico en entornos regulatorios, he decidido que es hora de comenzar un nuevo proyecto que reúna todo esto con ejemplos de código sobre cómo almacenar el cuerpo del correo electrónico y todos sus datos asociados. Durante el próximo año, continuaré desarrollando este proyecto con el objetivo de crear una aplicación funcional de almacenamiento y visualización para correos electrónicos archivados y toda la información del registro producida por SparkPost. SparkPost no tiene un sistema que archive el cuerpo del correo electrónico, pero hace que la construcción de una plataforma de archivo sea bastante fácil.
En esta serie de blogs, describiré el proceso que seguí para almacenar el cuerpo del correo electrónico en S3 (Amazon’s Simple Store Service) y todos los datos de registro relevantes en MySQL para una fácil referenciación cruzada. Para sistemas de archivo de producción que requieren estrategias de respaldo de bases de datos robustas, considere implementar un proceso de respaldo y restauración de PostgreSQL integral para asegurar que sus datos de archivo estén debidamente protegidos. En última instancia, este es el punto de partida para construir una aplicación que permita la búsqueda fácil de correos electrónicos archivados y luego mostrar esos correos junto con los datos del evento (registro). El código para este proyecto se puede encontrar en el siguiente repositorio de GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform
Esta primera entrada de la serie de blogs va a describir el desafío y establecer una arquitectura para la solución. El resto de los blogs detallarán partes de la solución junto con ejemplos de código.
El primer paso en mi proceso fue averiguar cómo iba a obtener una copia del correo electrónico enviado al destinatario original. Para obtener una copia del cuerpo del correo electrónico, debe:
Capturar el cuerpo del correo electrónico antes de enviar el correo
Hacer que el servidor de correo almacene una copia
Hacer que el servidor de correo cree una copia para que usted almacene
Si el servidor de correo está agregando elementos como seguimiento de enlaces o seguimiento de apertura, no puede usar el #1 porque no reflejará los cambios de seguimiento de apertura/clic.
Eso significa que el servidor tiene que almacenar el correo electrónico o de alguna manera ofrecerle una copia para su almacenamiento. Dado que SparkPost no tiene un mecanismo de almacenamiento para los cuerpos de correo electrónico, pero tiene una forma de crear una copia del correo, haremos que SparkPost nos envíe un duplicado del correo para almacenarlo en S3.
Esto se hace mediante el uso de la función de Archivo de SparkPost. La función de Archivo de SparkPost brinda al remitente la capacidad de decirle a SparkPost que envíe un duplicado del correo a una o más direcciones de correo electrónico y utilice los mismos enlaces de seguimiento y apertura que el original. La documentación de SparkPost define su función de Archivo de la siguiente manera:
Los destinatarios en la lista de archivo recibirán una réplica exacta del mensaje que se envió a la dirección RCPT TO. En particular, cualquier enlace codificado destinado al destinatario RCPT TO será idéntico en los mensajes de archivo
Las únicas diferencias del correo electrónico RCPT TO son que algunos de los encabezados serán diferentes ya que la dirección objetivo para el correo electrónico de archivo es diferente, ¡pero el cuerpo del correo electrónico será una réplica exacta!
Si desea una explicación más profunda, aquí hay un enlace a la documentación de SparkPost sobre la creación de copias duplicadas (o de archivo) de un correo electrónico.
Como nota al margen, SparkPost realmente le permite enviar correos electrónicos a direcciones de cc, bcc, y archivo. Para esta solución, nos enfocamos en las direcciones de archivo.
* Aviso * Los correos electrónicos archivados SOLO pueden ser creados al inyectar correos electrónicos en SparkPost a través de SMTP!
Ahora que sabemos cómo obtener una copia del correo electrónico original, necesitamos analizar los datos del registro que se producen y algunas de las sutilezas dentro de esos datos. SparkPost rastrea todo lo que sucede en sus servidores y le ofrece esa información en forma de eventos de mensaje. Esos eventos se almacenan en SparkPost durante 10 días y se pueden extraer del servidor a través de una API RESTful llamada eventos de mensaje, o puede hacer que SparkPost empuje esos eventos a cualquier número de aplicaciones de recopilación que desee. El mecanismo de empuje se realiza a través de webhooks y se hace en tiempo real.
Actualmente, hay 14 eventos diferentes que pueden ocurrirle a un correo. Aquí hay una lista de los eventos actuales:
Bounce
ClickDelay
Delivery
Generation Failure
Generation Rejection
Initial Open
InjectionLink Unsubscribe
List Unsubscribe
Open
Out of Band
Policy RejectionSpam Complaint
* Siga este enlace para una guía de referencia actualizada para una descripción de cada evento junto con los datos que se comparten para cada evento.
Cada evento tiene numerosos campos que coinciden con el tipo de evento. Algunos campos como el transmission_id se encuentran en cada evento, pero otros campos pueden ser más específicos del evento; por ejemplo, solo los eventos de apertura y clic tienen información de geoetiqueta.
Una entrada de evento de mensaje muy importante para este proyecto es el transmission_id. Todas las entradas de evento de mensaje para el correo electrónico original, correo electrónico archivado, y cualquier dirección de cc y bcc compartirán el mismo transmission_id.
También hay una entrada común llamada el message_id que tendrá el mismo id para cada entrada del correo electrónico original y el correo electrónico archivado. Cualquier dirección de cc o bcc tendrá su propio id para la entrada del message_id.
Hasta ahora esto suena genial y francamente bastante fácil, pero ahora es la parte desafiante. Recuerde, para obtener el correo electrónico de archivo, necesitamos que SparkPost envíe un duplicado del correo original a otra dirección de correo que corresponda a algún buzón al que tenga acceso. Pero para automatizar esta solución y almacenar el cuerpo del correo electrónico, voy a usar otra función de SparkPost llamada Inbound Email Relaying. Lo que hace es tomar todos los correos enviados a un dominio específico y procesarlos. Al procesarlos, desmonta el correo y crea una estructura JSON que luego se entrega a una aplicación a través de un webhook. Vea el Apéndice A para un JSON de muestra.
Si observa detenidamente, notará que la estructura JSON del relé de entrada carece de un campo muy importante; el transmission_id. Mientras que todos los correos electrónicos de salida tienen el transmission_id con la misma entrada que vincula todos los datos del correo electrónico original, archivo, direcciones de cc, y bcc; SparkPost no tiene forma de saber que el correo capturado por el proceso de entrada está conectado a cualquiera de los correos electrónicos salientes. El proceso de entrada simplemente sabe que se envió un correo a un dominio específico y que debe analizar ese correo. Eso es todo. Tratará cualquier correo enviado a ese dominio de la misma manera, ya sea una respuesta de un cliente o el correo de archivo enviado desde SparkPost.
Entonces, el truco es; ¿cómo unimos los datos de salida al proceso de entrada que acaba de capturar la versión archivada del correo? Lo que decidí hacer fue ocultar un id único en el cuerpo del correo. Cómo se haga esto depende de usted, pero simplemente creé un campo de entrada con la etiqueta oculta activada.
También agregué ese campo en el bloque de metadatos del encabezado X-MSYS-API que se pasa a SparkPost durante la inyección. Este UID oculto terminará siendo el pegamento para todo el proceso y es un componente principal del proyecto y se discutirá en profundidad en las siguientes publicaciones del blog.
Ahora que tenemos el UID que unirá este proyecto y entendemos por qué es necesario, puedo comenzar a construir la visión del proyecto en general y las publicaciones correspondientes del blog.
Capturando y almacenando el correo de archivo junto con una entrada de base de datos para búsqueda/indexación
Captura de todos los datos de eventos de mensaje
Crear una aplicación para ver el correo y todos los datos correspondientes
Aquí hay un diagrama simple del proyecto:

La primera entrega de código cubrirá el proceso de archivo y el almacenamiento del correo en S3, mientras que la segunda entrega de código cubrirá el almacenamiento de todos los datos de registro de los eventos de mensaje en MySQL. Puede esperar las dos primeras entregas de código y entradas de blog en algún momento a principios de 2019. Si tiene alguna pregunta o sugerencia, no dude en comentarlas.
Felices envíos.
– Jeff
Apéndice A:
