
Mit der Zunahme der E-Mail-Nutzung in regulatorischen Umgebungen habe ich beschlossen, dass es Zeit ist, ein neues Projekt zu starten, das all dies mit Codebeispielen zusammenführt, wie man den E-Mail-Body und alle zugehörigen Daten speichert.
Vor etwa einem Jahr schrieb ich einen Blog darüber, wie man E-Mail-Kopien zur Archivierung und Ansicht abruft, aber ich sprach nicht die eigentliche Speicherung der E-Mail oder der zugehörigen Daten an. Kürzlich schrieb ich einen Blog darüber, wie man alle Ereignisdaten (d.h. wann die E-Mail gesendet wurde, Öffnungen, Klicks, Bounces, Abmeldungen usw.) zu einer E-Mail für Prüfungszwecke speichert, habe mich jedoch entschieden, keinen unterstützenden Code zu erstellen.
Mit dem Anstieg der E-Mail-Nutzung in regulierten Umgebungen habe ich beschlossen, ein neues Projekt zu starten, das all dies zusammenführt mit Codebeispielen, wie man den E-Mail-Text und alle damit verbundenen Daten speichert. Im Laufe des nächsten Jahres werde ich weiterhin an diesem Projekt arbeiten mit dem Ziel, eine funktionierende Speicher- und Ansichtsanwendung für archivierte E-Mails und alle von SparkPost erzeugten Log-Informationen zu erstellen. SparkPost verfügt nicht über ein System, das den E-Mail-Text archiviert, aber es macht den Aufbau einer Archivierungsplattform relativ einfach.
In dieser Blogreihe werde ich den Prozess beschreiben, den ich durchlaufen habe, um den E-Mail-Text auf S3 (Amazons Simple Store Service) zu speichern und alle relevanten Log-Daten in MySQL zum einfachen Querverweis. Für Produktionsarchivierungssysteme, die robuste Datenbank-Backup-Strategien erfordern, sollten Sie die Implementierung eines umfassenden PostgreSQL-Backup- und Wiederherstellungsprozesses in Betracht ziehen, um sicherzustellen, dass Ihre Archivierungsdaten ordnungsgemäß geschützt sind. Letztendlich ist dies der Ausgangspunkt für den Aufbau einer Anwendung, die das einfache Durchsuchen archivierter E-Mails ermöglicht und diese E-Mails zusammen mit den Ereignis- (Log-)Daten anzeigt. Der Code für dieses Projekt ist im folgenden GitHub-Repository zu finden: https://github.com/jeff-goldstein/PHPArchivePlatform
Dieser erste Eintrag der Blogreihe wird die Herausforderung beschreiben und eine Architektur für die Lösung skizzieren. Die restlichen Blogs werden Teile der Lösung zusammen mit Codebeispielen detailliert beschreiben.
Der erste Schritt in meinem Prozess bestand darin, herauszufinden, wie ich eine Kopie der an den ursprünglichen Empfänger gesendeten E-Mail erhalten würde. Um eine Kopie des E-Mail-Textes zu erhalten, müssen Sie entweder:
Den E-Mail-Text abfangen, bevor die E-Mail gesendet wird
Den E-Mail-Server dazu bringen, eine Kopie zu speichern
Den E-Mail-Server dazu bringen, eine Kopie für Sie zu erstellen, die Sie speichern können
Wenn der E-Mail-Server Elemente wie Link-Tracking oder Open-Tracking hinzufügt, können Sie #1 nicht verwenden, da dies die Änderungen am Tracking von Öffnen/Klicken nicht widerspiegelt.
Das bedeutet, dass entweder der Server die E-Mail speichern muss oder Ihnen irgendwie eine Kopie dieser E-Mail zur Speicherung zur Verfügung stellen muss. Da SparkPost keinen Speichermechanismus für E-Mail-Körper hat, aber eine Möglichkeit bietet, eine Kopie der E-Mail zu erstellen, werden wir SparkPost eine Duplikat der E-Mail an uns senden lassen, das wir in S3 speichern können.
Dies geschieht durch die Nutzung der Archivfunktion von SparkPost. Die Archivfunktion von SparkPost gibt dem Absender die Möglichkeit, SparkPost anzuweisen, eine Duplikat der E-Mail an eine oder mehrere E-Mail-Adressen zu senden und dieselben Tracking- und Öffnungslinks wie im Original zu verwenden. Die SparkPost-Dokumentation definiert ihre Archivfunktion auf folgende Weise:
Empfänger auf der Archivliste werden eine exakte Kopie der Nachricht erhalten, die an die RCPT TO-Adresse gesendet wurde. Insbesondere sind alle codierten Links, die für den RCPT TO-Empfänger bestimmt sind, in den Archivnachrichten identisch.
Die einzigen Unterschiede zur RCPT TO-E-Mail bestehen darin, dass einige der Header unterschiedlich sein werden, da die Zieladresse für die Archivierung der E-Mail unterschiedlich ist, aber der Text der E-Mail wird eine exakte Kopie sein!
Wenn Sie eine ausführlichere Erklärung wünschen, finden Sie hier einen Link zur SparkPost-Dokumentation zur Erstellung von Duplikat- (oder Archiv-)Kopien einer E-Mail.
Als Randbemerkung: SparkPost erlaubt Ihnen tatsächlich, E-Mails an cc-, bcc- und Archiv-E-Mail-Adressen zu senden. Bei dieser Lösung konzentrieren wir uns auf die Archiv-Adressen.
* Hinweis * Archivierte E-Mails können NUR erstellt werden, wenn E-Mails über SMTP in SparkPost eingespeist werden!
Da wir nun wissen, wie wir eine Kopie der Original-E-Mail erhalten, müssen wir uns die Log-Daten ansehen, die dabei erzeugt werden, und einige der subtilen Nuancen dieser Daten verstehen. SparkPost verfolgt alles, was auf seinen Servern passiert, und stellt Ihnen diese Informationen in Form von Nachrichtenevents zur Verfügung. Diese Events werden 10 Tage lang auf SparkPost gespeichert und können über eine RESTful-API namens Nachrichten-Events vom Server abgerufen werden, oder Sie können SparkPost diese Events an beliebige Anwendungen senden lassen, die Sie sammeln möchten. Der Push-Mechanismus erfolgt in Echtzeit über Webhooks.
Derzeit gibt es 14 verschiedene Ereignisse, die bei einer E-Mail auftreten können. Hier ist eine Liste der aktuellen Ereignisse:
Bounce
ClickDelay
Delivery
Generation Failure
Generation Rejection
Initial Open
InjectionLink Unsubscribe
List Unsubscribe
Open
Out of Band
Policy RejectionSpam Complaint
* Folgen Sie diesem Link für einen aktuellen Referenzleitfaden für eine Beschreibung jedes Ereignisses zusammen mit den für jedes Ereignis geteilten Daten.
Jedes Ereignis hat zahlreiche Felder, die dem Ereignistyp entsprechen. Einige Felder wie das transmission_id finden sich in jedem Ereignis, aber andere Felder können spezifischer für ein Ereignis sein; beispielsweise haben nur Öffnungs- und Klickevents Geotag-Informationen.
Ein sehr wichtiger Nachrichteneintrag für dieses Projekt ist das transmission_id. Alle Nachrichteneinträge für die Original-E-Mail, archivierte E-Mail und alle cc- und bcc-Adressen teilen dasselbe transmission_id.
Es gibt auch einen gemeinsamen Eintrag namens message_id mit derselben ID für jeden Eintrag der Original-E-Mail und der archivierten E-Mail. Alle cc oder bcc-Adressen haben ihre eigene ID für den message_id Eintrag.
Bisher klingt das großartig und ehrlich gesagt ziemlich einfach, aber jetzt kommt der herausfordernde Teil. Denken Sie daran, um die Archiv-E-Mail zu erhalten, lassen wir SparkPost eine Duplikat der Original-E-Mail an eine andere E-Mail-Adresse senden, die einem Postfach entspricht, auf das Sie Zugriff haben. Um diese Lösung zu automatisieren und den E-Mail-Text zu speichern, werde ich eine weitere Funktion von SparkPost verwenden, die Inbound Email Relaying genannt wird. Was das tut, ist alle E-Mails, die an eine bestimmte Domain gesendet werden, zu nehmen und zu verarbeiten. Bei der Verarbeitung wird die E-Mail zerpflückt und es wird eine JSON-Struktur erstellt, die dann über einen Webhook an eine Anwendung geliefert wird. Siehe Anhang A für ein Beispiel-JSON.
Wenn Sie ganz genau hinsehen, werden Sie feststellen, dass die JSON-Struktur des Inbound-Relais ein sehr wichtiges Feld fehlt; das transmission_id. Während alle ausgehenden E-Mails das transmission_id mit demselben Eintrag haben, das alle Daten von der Original-E-Mail, der Archivierung, cc- und bcc-Adressen verbindet; SparkPost hat keine Möglichkeit zu wissen, dass die E-Mail, die vom Inbound-Prozess erfasst wird, mit einer der ausgehenden E-Mails verbunden ist. Der Inbound-Prozess weiß einfach, dass eine E-Mail an eine bestimmte Domain gesendet wurde und zu parsen ist. Das ist alles. Es wird jede E-Mail, die an diese Domain gesendet wird, auf dieselbe Weise behandeln, sei es eine Antwort von einem Kunden oder die Archiv-E-Mail, die von SparkPost gesendet wird.
Also, der Trick ist: wie verbindet man die ausgehenden Daten mit dem Inbound-Prozess, der gerade die archivierte Version der E-Mail erfasst hat? Was ich beschlossen habe, ist eine eindeutige ID im Text der E-Mail zu verstecken. Wie das gemacht wird, bleibt Ihnen überlassen, ich habe einfach ein Eingabefeld mit eingeschaltetem versteckten Tag erstellt.
Ich habe dieses Feld auch in den Metadatenblock des X-MSYS-API-Headers aufgenommen, der während der Injektion an SparkPost übergeben wird. Diese versteckte UID wird letztendlich der Kleber für den gesamten Prozess sein und ist ein Hauptbestandteil des Projekts, das ausführlich in den folgenden Blogbeiträgen diskutiert wird.
Da wir nun die UID haben, die dieses Projekt zusammenhalten wird, und verstehen, warum sie notwendig ist, kann ich damit beginnen, die Vision des gesamten Projekts und die dazugehörigen Blogbeiträge aufzubauen.
Erfassen und Speichern der Archiv-E-Mail zusammen mit einem Datenbankeintrag zur Suche/Indexierung
Erfassung aller Nachrichtenevent-Daten
Erstellen einer Anwendung zum Anzeigen der E-Mail und aller zugehörigen Daten
Hier ist ein einfaches Diagramm des Projekts:

Der erste Code-Drop wird den Archivierungsprozess abdecken und die E-Mail auf S3 speichern, während der zweite Code-Drop das Speichern aller Log-Daten von Nachrichtenevents in MySQL abdeckt. Sie können die ersten beiden Code-Drops und Blog-Einträge irgendwann Anfang 2019 erwarten. Wenn Sie Fragen oder Vorschläge haben, zögern Sie nicht, diese weiterzugeben.
Viel Spaß beim Senden.
– Jeff
Anhang A:
