Budowanie systemu archiwizacji e-maili: wyzwania i oczywiście rozwiązanie – Część 1
Jeff Goldstein
4 lut 2019
1 min read

Kluczowe Wnioski
Archiwizowanie e-maili jest coraz bardziej konieczne w środowiskach regulacyjnych, zgodności i audytowych.
SparkPost nie przechowuje treści e-maili, ale jego funkcja Archiwum pozwala nadawcom otrzymywać duplikaty wiadomości, które odwzorowują linki śledzące i treść.
Treści e-maili mogą być przechowywane w Amazon S3, podczas gdy metadane zdarzeń wiadomości można przechowywać w MySQL do zapytań i tworzenia odniesień krzyżowych.
Zdarzenia wiadomości w SparkPost dostarczają bogatych dzienników aktywności (odbiory, dostawy, kliknięcia, otwarcia, wypisy, skargi i więcej).
Kopie archiwalne są generowane tylko przy wysyłaniu e-maili przez SMTP.
Zdarzenia wiadomości dla oryginalnych, archiwalnych, CC i BCC e-maili dzielą wspólny transmission_id.
Inbound Email Relay może przetwarzać zarchiwizowane wiadomości, ale nie zawiera transmission_id, co tworzy wyzwanie związane z łączeniem danych.
Umieszczenie ukrytego unikalnego identyfikatora (UID) w treści wiadomości wypełnia tę lukę i wiąże zawartość przychodzącą z dziennikami wychodzącymi.
Łączenie archiwalnych e-maili + zdarzeń wiadomości umożliwia budowanie przeszukiwalnego, audytowalnego systemu archiwizacji.
Długoterminowy projekt obejmuje wydania kodu do przechowywania archiwalnych e-maili w S3 i rejestrowania danych zdarzeń w MySQL.
Końcowa aplikacja pozwoli na łatwe wyszukiwanie, przeglądanie i uzgadnianie treści e-maili z całą związaną historią zdarzeń.
Idealne dla branż o rygorystycznych wymogach zgodności, które potrzebują pełnej widoczności każdej wysłanej wiadomości.
Q&A Highlights
Dlaczego budować własny system archiwizacji email?
Regulowane branże często wymagają długoterminowego przechowywania zarówno treści e-maila, jak i wszystkich powiązanych dzienników zdarzeń. SparkPost nie przechowuje treści wiadomości, więc stworzenie niestandardowego systemu zapewnia zgodność, audyt i widoczność.
Jak uzyskać dokładną kopię oryginalnej wysłanej wiadomości email?
Funkcja Archive SparkPost wysyła kopię każdego wysłanego e-maila na wyznaczone adresy archiwalne, zachowując wszystkie zakodowane linki i śledzenie zachowań.
Dlaczego nie można uchwycić treści e-maila przed wysłaniem?
Pre-send capture nie obejmuje modyfikacji SparkPost (śledzenie otwarć, śledzenie kliknięć, kodowanie linków). Używanie kopii Archive gwarantuje, że zapisana wersja dokładnie odpowiada temu, co otrzymują odbiorcy.
Czy SparkPost archiwizuje e-maile automatycznie?
Nie. SparkPost nie przechowuje treści wiadomości. Kopie archiwalne muszą być żądane przez określenie adresów archiwizacyjnych podczas wstrzykiwania SMTP.
Co jest przechowywane gdzie w tym systemie archiwizacji?
Treść e-maila → Amazon S3
Logi zdarzeń wiadomości → MySQL
To rozdzielenie wspiera szybkie wyszukiwanie, zapytania strukturalne i niedrogie przechowywanie obiektów.
Jak długo SparkPost przechowuje dane zdarzeń?
SparkPost przechowuje zdarzenia wiadomości przez 10 dni. Po tym okresie, dane muszą być pobierane za pomocą webhooka lub zapytania i przechowywane w innym miejscu.
Jakie zdarzenia wiadomości są dostępne?
SparkPost obecnie udostępnia 14 zdarzeń, w tym dostawy, odbicia, kliknięcia, otwarcia, odrzucenia, kwestie polityki, skargi dotyczące spamu, wypisania się i więcej.
Jakie identyfikatory łączą wszystkie wydarzenia?
Wszystkie wiadomości wychodzące (oryginał, archiwum, CC, BCC) dzielą ten sam transmission_id. Oryginał i e-mail z archiwum również dzielą ten sam message_id.
Dlaczego przetwarzanie inbound jest wyzwaniem?
SparkPost’s Inbound Email Relay zamienia pocztę przychodzącą na JSON, ale ten JSON nie zawiera transmission_id. Bez dodatkowych danych, kopia przychodząca nie może być powiązana z historią logów wychodzących.
Jak połączyć przychodzące zarchiwizowane e-maile z wychodzącymi zdarzeniami wiadomości?
Osadź ukryty unique identifier (UID) w treści e-maila i przekaż ten sam UID w metadanych. Ten UID staje się wspólnym odniesieniem w przychodzących i wychodzących rekordach.
Jak Inbound Email Relay pomaga w automatyzacji archiwizacji?
Otrzymuje zarchiwizowane e-maile wysłane do twojej domeny archiwalnej, przetwarza je na strukturalne JSON i przesyła do twojej aplikacji za pomocą webhooka—umożliwiając automatyczne wydobywanie i przechowywanie.
Jaka jest długoterminowa wizja projektu?
Kompletna aplikacja, która:
Przechowuje archiwalne e-maile w S3
Przechowuje wszystkie dzienniki zdarzeń w MySQL
Pozwala użytkownikom wyszukiwać e-maile
Wyświetla oryginalny e-mail i każde powiązane zdarzenie w jednym, zintegrowanym interfejsie
Około rok temu napisałem blog o tym, jak pobrać kopie e-maili do archiwizacji i przeglądania, ale nie poruszyłem kwestii rzeczywistego przechowywania e-maila ani powiązanych danych, a ostatnio napisałem blog o przechowywaniu wszystkich danych zdarzeń (tj. kiedy wysyłana jest wiadomość e-mail, otwarcia, kliknięcia, odbicia, rezygnacje z subskrypcji itp.) w celu audytu, ale postanowiłem nie tworzyć żadnego wspierającego kodu.
Z rosnącym wykorzystaniem e-maili w środowiskach regulowanych zdecydowałem, że nadszedł czas, aby rozpocząć nowy projekt, który połączy to wszystko z przykładami kodu, jak przechowywać treść wiadomości e-mail oraz wszystkie powiązane dane. W ciągu kolejnego roku będę kontynuował rozwijanie tego projektu, dążąc do stworzenia działającej aplikacji do przechowywania i przeglądania archiwizowanych wiadomości e-mail i wszystkich informacji o logach produkowanych przez SparkPost. SparkPost nie posiada systemu, który by archiwizował treść wiadomości e-mail, ale czyni budowanie platformy archiwizacyjnej dość łatwym.
W tej serii blogów opiszę proces, przez który przeszedłem, aby zapisać treść wiadomości e-mail na S3 (Amazon’s Simple Store Service) oraz wszystkie istotne dane logów w MySQL dla łatwego odniesienia. Dla systemów archiwizacyjnych, które wymagają solidnych strategii tworzenia kopii zapasowych baz danych, rozważ wdrożenie kompleksowego procesu tworzenia kopii zapasowej i odtwarzania PostgreSQL, aby upewnić się, że twoje dane archiwalne są odpowiednio chronione. W końcu jest to punkt początkowy do budowy aplikacji, która umożliwi łatwe przeszukiwanie archiwizowanych wiadomości e-mail, a następnie wyświetlanie tych wiadomości wraz z danymi zdarzeń (logów). Kod dla tego projektu można znaleźć w następującym repozytorium GitHub: PHPArchivePlatform na GitHub
Ten pierwszy wpis serii blogów opisze wyzwanie i zaproponuje architekturę rozwiązania. Reszta blogów szczegółowo opisze części rozwiązania wraz z przykładami kodu.
Pierwszym krokiem w moim procesie było ustalenie, jak uzyskać kopię wiadomości e-mail wysłanej do oryginalnego odbiorcy. Aby uzyskać kopi, musisz:
Przechwytywać treść wiadomości e-mail przed jej wysłaniem
Spowodować, aby serwer e-mail zapisał kopię
Uzyskać, aby serwer e-mail stworzył kopię dla Ciebie do zapisu
Jeśli serwer e-mail dodaje elementy takie jak śledzenie linków czy śledzenie otwarć, nie możesz użyć #1, ponieważ nie odzwierciedli to zmian w śledzeniu otwarć/kliknięć.
To oznacza, że albo serwer musi zapisać wiadomość, albo w jakiś sposób zaoferować jej kopię dla Ciebie do zapisania. Ponieważ SparkPost nie posiada mechanizmu przechowywania treści wiadomości, ale posiada możliwość tworzenia kopii wiadomości, poprosimy SparkPost o wysłanie nam duplikatu wiadomości, abyśmy mogli zapisać go w S3.
To jest realizowane poprzez użycie funkcji Archive SparkPost. Funkcja Archive SparkPost daje nadawcy możliwość poinstruowania SparkPost, aby wysłał duplikat wiadomości na jeden lub więcej adresów e-mail i używa tych samych linków do śledzenia i otwierania co oryginał. Dokumentacja SparkPost definiuje funkcję Archive w następujący sposób:
Odbiorcy na liście archiwalnej otrzymają dokładną replikę wiadomości, która została wysłana na adres RCPT TO. W szczególności wszelkie zakodowane linki przeznaczone dla odbiorcy RCPT TO będą identyczne w wiadomościach archiwalnych
Jedynymi różnicami od wiadomości do RCPT TO są pewne różnice w nagłówkach, ponieważ docelowy adres e-mail dla archiwizacji jest inny, ale treść wiadomości będzie dokładną repliką!
Jeśli chcesz głębszego wyjaśnienia, oto link do dokumentacji SparkPost dotyczącej tworzenia duplikatów (lub kopii archiwalnych) wiadomości e-mail.
Jako uwaga dodatkowa, SparkPost faktycznie pozwala na wysyłanie wiadomości e-mail do adresów cc, bcc i archiwalnych. Dla tego rozwiązania skupiamy się na adresach archiwalnych.
* Uwaga * Archiwalne e-maile mogą być utworzone TYLKO podczas wprowadzania e-maili do SparkPost przez SMTP!
Teraz, gdy wiemy, jak uzyskać kopię oryginalnej wiadomości e-mail, musimy przyjrzeć się danym logów, które są produkowane i niektórym subtelnym niuansom w tych danych. SparkPost śledzi wszystko, co dzieje się na jego serwerach i oferuje te informacje w formie zdarzeń wiadomości. Te zdarzenia są przechowywane w SparkPost przez 10 dni i można je pobrać z serwera za pośrednictwem API RESTful o nazwie zdarzeń wiadomości, lub można poprosić SparkPost o przesyłanie tych zdarzeń do dowolnej liczby aplikacji zbierających, które chcesz. Mechanizm przesyłania jest realizowany za pośrednictwem webhooków i odbywa się w czasie rzeczywistym.
Obecnie istnieje 14 różnych zdarzeń, które mogą dotyczyć wiadomości e-mail. Oto lista obecnych zdarzeń:
Bounce
ClickDelay
Delivery
Generation Failure
Generation Rejection
Initial Open
InjectionLink Unsubscribe
List Unsubscribe
Open
Out of Band
Policy RejectionSpam Complaint
* Przejdź do tego linku po aktualny przewodnik referencyjny z opisem każdego zdarzenia wraz z danymi, które są udostępniane dla każdego zdarzenia.
Każde zdarzenie ma liczne pola dopasowane do typu zdarzenia. Niektóre pola, jak transmission_id, znajdują się w każdym zdarzeniu, ale inne pola mogą być bardziej specyficzne dla zdarzenia; na przykład tylko zdarzenia otwarcia i kliknięcia mają informacje geotagowe.
Bardzo ważnym wpisem w zdarzeniu wiadomości dla tego projektu jest transmission_id. Wszystkie wpisy zdarzeń wiadomości dla oryginalnego e-maila, archiwalnego e-maila oraz wszelkich adresów cc i bcc będą miały wspólne transmission_id.
Jest także wspólny wpis o nazwie message_id, który będzie miał to samo id dla każdego wpisu oryginalnego e-maila i e-maila archiwalnego. Wszelkie adresy cc lub bcc będą miały własne id dla wpisu message_id.
Do tej pory wszystko brzmi dobrze, a nawet dość łatwo, ale teraz zaczyna się trudna część. Pamiętaj, aby uzyskać archiwalną wiadomość, prosimy SparkPost o wysłanie duplikatu oryginalnej wiadomości na inny adres e-mail, który odpowiada skrzynce odbiorczej, do której masz dostęp. Ale aby zautomatyzować to rozwiązanie i przechowywać treść wiadomości e-mail, użyję innej funkcji SparkPost o nazwie Inbound Email Relaying. Co to robi, to przechwytuje wszystkie e-maile wysłane na określoną domenę i przetwarza je. Podczas przetwarzania rozdziela wiadomość e-mail i tworzy strukturę JSON, która jest potem dostarczana do aplikacji za pomocą webhooka. Zobacz Dodatek A dla przykładowego JSON.
Jeśli przyjrzysz się uważnie, zauważysz, że struktura JSON z przekazu przychodzącego nie zawiera bardzo ważnego pola; transmission_id. Podczas gdy wszystkie wiadomości wychodzące mają transmission_id z tym samym wpisem, który łączy wszystkie dane z oryginalnej wiadomości e-mail, archiwum, adresów cc i bcc; SparkPost nie ma możliwości wiedzieć, że wiadomość e-mail przechwycona przez proces przychodzący jest powiązana z którąkolwiek z wiadomości wychodzących. Proces przychodzący po prostu wie, że wiadomość e-mail została wysłana na określoną domenę i ma ją przeanalizować. To wszystko. Potraktuje każdą wiadomość e-mail wysłaną na tę domenę jednakowo, niezależnie od tego, czy jest to odpowiedź od klienta, czy archiwalna wiadomość wysłana z SparkPost.
Więc sztuczką jest; jak powiązać dane wychodzące z procesem przychodzącym, który właśnie przechwycił archiwalną wersję wiadomości e-mail? Co postanowiłem zrobić, to ukryć unikalne id w treści wiadomości e-mail. Jak to zrobisz, zależy od Ciebie, ale po prostu stworzyłem pole wejściowe z włączoną tagiem ukrytym.
Dodałem ten także ten field do bloku metadanych nagłówka X-MSYS-API, który jest przekazywany do SparkPost podczas wprowadzania. Ten ukryty UID będzie klejem do całego procesu i jest głównym elementem projektu i zostanie omówiony szczegółowo w kolejnych wpisach na blogu.
Teraz, gdy mamy UID, który połączy ten projekt razem i rozumiemy, dlaczego jest to konieczne, mogę zacząć budować wizję całego projektu i odpowiadające wpisy na blogu.
Przechwytywanie i przechowywanie archiwalnej wiadomości e-mail wraz z wpisem do bazy danych do wyszukiwania/indeksowania
Przechwytywanie wszystkich danych zdarzeń wiadomości
Tworzenie aplikacji do przeglądania wiadomości e-mail i wszystkich powiązanych danych
Oto prosty diagram projektu:

Pierwszy zrzut kodu będzie obejmować proces archiwizacji i przechowywanie wiadomości e-mail na S3, podczas gdy drugi zrzut kodu obejmie przechowywanie wszystkich danych logów z message-events do MySQL. Możesz oczekiwać pierwszych dwóch zrzutów kodu i wpisów na blogu na początku 2019 roku. Jeśli masz jakieś pytania lub sugestie, proszę o przesłanie ich.
Szczęśliwego wysyłania.
– Jeff
Dodatek A:




