Zasięg

Grow

Manage

Automate

Zasięg

Grow

Manage

Automate

Budowanie systemu archiwizacji e-maili: Przechowywanie treści e-maili

Ptak

4 mar 2019

Email

1 min read

Budowanie systemu archiwizacji e-maili: Przechowywanie treści e-maili

Ptak

4 mar 2019

Email

1 min read

Budowanie systemu archiwizacji e-maili: Przechowywanie treści e-maili

W tym blogu opiszę proces, przez który przeszedłem, aby zapisać treść e-maila w S3 (Prosta Usługa Przechowywania Amazon) oraz dane dodatkowe w tabeli MySQL, aby ułatwić ich wzajemne odniesienie.

W tym blogu opiszę proces, przez który przeszedłem, aby przechowywać treść e-maila na S3 (usłudze Amazon Simple Store) i dane pomocnicze w tabeli MySQL, aby łatwo je krzyżowo odwołać. Ostatecznie jest to punkt wyjścia dla bazy kodu, która będzie zawierać aplikację umożliwiającą łatwe wyszukiwanie zarchiwizowanych e-maili, a następnie wyświetlanie tych e-maili wraz z danymi zdarzeń (dziennika). Kod dla tego projektu można znaleźć w następującym repozytorium GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.

Chociaż w tym projekcie będę korzystać z S3 i MySQL, zdecydowanie nie są to jedyne technologie, które można wykorzystać do budowy platformy archiwizacyjnej, ale biorąc pod uwagę ich powszechność, pomyślałem, że są dobrym wyborem na ten projekt. W pełnoskalowym systemie o dużym wolumenie użyłbym bazy danych o wyższej wydajności niż MySQL, ale do tego przykładowego projektu MySQL jest idealny. Dla organizacji rozważających PostgreSQL jako wybór bazy danych archiwizacyjnej, wdrożenie odpowiednich procedur tworzenia kopii zapasowych i przywracania jest niezbędne do utrzymania integralności danych w systemach produkcyjnych.

Poniżej szczegółowo opisałem kroki, które podjąłem w tym pierwszym etapie projektu:

  1. Tworzenie duplikatu e-maila do archiwizacji

  2. Użyj funkcji SparkPost Archiving i Inbound Relay, aby wysłać kopię oryginalnego e-maila z powrotem do SparkPost do przetworzenia na strukturę JSON, a następnie wysłaną do kolektora webhook (aplikacji)

  3. Rozmontuj strukturę JSON, aby uzyskać niezbędne składniki

  4. Wyślij treść e-maila do S3 do przechowywania

  5. Zaloguj wpis do MySQL dla każdego e-maila dla krzyżowego odniesienia

Tworzenie Duplikatu Email

W SparkPost najlepszym sposobem archiwizacji wiadomości e-mail jest stworzenie identycznej kopii wiadomości e-mail, specjalnie zaprojektowanej do celów archiwizacyjnych. Odbywa się to za pomocą funkcji Archive SparkPost. Funkcja Archive SparkPost daje nadawcy możliwość wysłania duplikatu wiadomości e-mail na jeden lub więcej adresów e-mail.  Ten duplikat korzysta z tego samego śledzenia i otwartych linków 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

Jedyną różnicą między tą kopią archiwalną a oryginalnym mailem RCPT TO jest to, że niektóre nagłówki będą różne, ponieważ adres docelowy dla wiadomości archiwalnej 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. Przykładowe nagłówki X-MSYS-API dla tego projektu są pokazane później w tym blogu.

Jest jedno zastrzeżenie do tego podejścia; podczas gdy wszystkie informacje o zdarzeniach w oryginalnej wiadomości e-mail są połączone zarówno przez transmission_id, jak i message_id, nie ma żadnych informacji w zdarzeniu przekierowania przychodzącego (mechanizm uzyskiwania i rozpowszechniania archiwalnej wiadomości e-mail) dla zduplikowanej wiadomości e-mail, które wiążą się z jednym z tych dwóch identyfikatorów, a tym samym informacji dla oryginalnej wiadomości e-mail. Oznacza to, że musimy umieścić dane w treści wiadomości e-mail i nagłówku oryginalnej wiadomości e-mail jako sposób łączenia wszystkich danych SparkPost z oryginalnej i archiwalnej wiadomości e-mail.

Aby stworzyć kod, który jest umieszczony w treści wiadomości e-mail, użyłem następującego procesu w aplikacji tworzącej wiadomości e-mail.

  1. Gdzieś w treści wiadomości e-mail umieściłem następujący wpis:<input name="ArchiveCode" type="hidden" value="<<UID>>">

  2. Następnie stworzyłem unikalny kod i zamieniłem pole <<UID>>: $uid = md5(uniqid(rand(), true)); $emailBody = str_replace(“<<UID>>,$uid,$emailBody);

    Oto przykład wyniku:

    <input name="ArchiveCode" type="hidden" value="00006365263145">

  3. Następnie upewniłem się, że dodałem $UID do bloku meta_data nagłówka X-MSYS-API. Ten krok zapewnia, że UID jest osadzony w każdym wyjściu zdarzenia dla oryginalnej wiadomości e-mail:

X-MSYS-API: {
  "campaign_id": "<my_campaign>",
  "metadata": {
    "UID": "<UID>"
  },
  "archive": [
    {
      "email": "archive@geekwithapersonality.com"
    }
  ],
  "options": {
    "open_tracking": false,
    "click_tracking": false,
    "transactional": false,
    "ip_pool": "<my_ip_pool>"
  }
}

Teraz mamy sposób na powiązanie wszystkich danych z oryginalnej wiadomości e-mail z treścią wiadomości archiwalnej.

Uzyskiwanie wersji Archive

Aby uzyskać kopię wiadomości e-mail do archiwum, musisz wykonać następujące kroki:

  1. Utwórz subdomenę, na którą będziesz wysyłać wszystkie archiwalne (duplikaty) wiadomości e-mail

  2. Ustaw odpowiednie rekordy DNS, aby wszystkie wiadomości e-mail wysyłane do tej subdomeny były kierowane do SparkPost

  3. Utwórz domenę przychodzącą w SparkPost

  4. Utwórz webhook przychodzący w SparkPost

  5. Utwórz aplikację (kolektor) do odbierania strumienia danych webhooka SparkPost

Poniższe dwa linki mogą pomóc w przejściu przez ten proces:

  1. Dokumentacja techniczna SparkPost: Enabling Inbound Email Relaying & Relay Webhooks

  2. Również blog, który napisałem w zeszłym roku, Archiving Emails: A How-To Guide for Tracking Sent Mail, przeprowadzi Cię przez tworzenie przekierowania przychodzącego w SparkPost

* Uwaga: od października 2018 roku funkcja Archiwum działa tylko przy wysyłaniu wiadomości e-mail za pomocą połączenia SMTP do SparkPost, API RESTful nie obsługuje tej funkcji.  To prawdopodobnie nie stanowi problemu, ponieważ większość wiadomości e-mail, które wymagają tego poziomu kontroli audytu, to spersonalizowane wiadomości e-mail, które są w pełni konstruowane przez aplikację backendową przed koniecznością dostarczenia e-maila.

Aby uzyskać kopię wiadomości e-mail do archiwum, musisz wykonać następujące kroki:

  1. Utwórz subdomenę, na którą będziesz wysyłać wszystkie archiwalne (duplikaty) wiadomości e-mail

  2. Ustaw odpowiednie rekordy DNS, aby wszystkie wiadomości e-mail wysyłane do tej subdomeny były kierowane do SparkPost

  3. Utwórz domenę przychodzącą w SparkPost

  4. Utwórz webhook przychodzący w SparkPost

  5. Utwórz aplikację (kolektor) do odbierania strumienia danych webhooka SparkPost

Poniższe dwa linki mogą pomóc w przejściu przez ten proces:

  1. Dokumentacja techniczna SparkPost: Enabling Inbound Email Relaying & Relay Webhooks

  2. Również blog, który napisałem w zeszłym roku, Archiving Emails: A How-To Guide for Tracking Sent Mail, przeprowadzi Cię przez tworzenie przekierowania przychodzącego w SparkPost

* Uwaga: od października 2018 roku funkcja Archiwum działa tylko przy wysyłaniu wiadomości e-mail za pomocą połączenia SMTP do SparkPost, API RESTful nie obsługuje tej funkcji.  To prawdopodobnie nie stanowi problemu, ponieważ większość wiadomości e-mail, które wymagają tego poziomu kontroli audytu, to spersonalizowane wiadomości e-mail, które są w pełni konstruowane przez aplikację backendową przed koniecznością dostarczenia e-maila.

Aby uzyskać kopię wiadomości e-mail do archiwum, musisz wykonać następujące kroki:

  1. Utwórz subdomenę, na którą będziesz wysyłać wszystkie archiwalne (duplikaty) wiadomości e-mail

  2. Ustaw odpowiednie rekordy DNS, aby wszystkie wiadomości e-mail wysyłane do tej subdomeny były kierowane do SparkPost

  3. Utwórz domenę przychodzącą w SparkPost

  4. Utwórz webhook przychodzący w SparkPost

  5. Utwórz aplikację (kolektor) do odbierania strumienia danych webhooka SparkPost

Poniższe dwa linki mogą pomóc w przejściu przez ten proces:

  1. Dokumentacja techniczna SparkPost: Enabling Inbound Email Relaying & Relay Webhooks

  2. Również blog, który napisałem w zeszłym roku, Archiving Emails: A How-To Guide for Tracking Sent Mail, przeprowadzi Cię przez tworzenie przekierowania przychodzącego w SparkPost

* Uwaga: od października 2018 roku funkcja Archiwum działa tylko przy wysyłaniu wiadomości e-mail za pomocą połączenia SMTP do SparkPost, API RESTful nie obsługuje tej funkcji.  To prawdopodobnie nie stanowi problemu, ponieważ większość wiadomości e-mail, które wymagają tego poziomu kontroli audytu, to spersonalizowane wiadomości e-mail, które są w pełni konstruowane przez aplikację backendową przed koniecznością dostarczenia e-maila.

Uzyskiwanie duplikatu email w strukturze JSON

W pierwszej fazie tego projektu, wszystko, co przechowuję, to format e-maila rfc822 w S3 oraz niektóre pola opisu wysokiego poziomu w tabeli SQL do wyszukiwania.  Ponieważ SparkPost wyśle dane e-mail w strukturze JSON do mojej platformy archiwizacyjnej za pośrednictwem strumieni danych webhook, zbudowałem aplikację (często nazywaną collectorem), która akceptuje strumień danych Relay_Webhook.

Każda paczka ze SparkPost Relay_Webhook będzie zawierać informacje o jednym zduplikowanym e-mailu na raz, więc rozbicie struktury JSON na docelowe komponenty dla tego projektu jest dość proste.  W moim kodzie PHP, pobranie sformatowanego e-maila rfc822 było tak łatwe, jak kilka poniższych linii kodu:

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $body = file_get_contents("php://input");
    $fields = json_decode($body, true);
    $rfc822body = $fields[0]['msys']['relay_message']['content']['email_rfc822'];
    $htmlbody = $fields[0]['msys']['relay_message']['content']['html'];
    $headers  = $fields[0]['msys']['relay_message']['content']['headers'];
}

Niektóre informacje, które chcę przechowywać w mojej tabeli SQL, znajdują się w tablicy pól nagłówka.  Dlatego napisałem małą funkcję, która akceptowała tablicę nagłówków i przechodziła przez tablicę w celu uzyskania danych, które mnie interesowały:

function get_important_headers($headers, &$original_to, &$headerDate, &$subject, &$from) {
    foreach ($headers as $headerGroup) {
        foreach ($headerGroup as $key => $value) {
            if ($key === 'To') {
                $original_to = $value;
            } elseif ($key === 'Date') {
                $headerDate = $value;
            } elseif ($key === 'Subject') {
                $subject = $value;
            } elseif ($key === 'From') {
                $from = $value;
            }
        }
    }
}

Teraz, gdy mam dane, jestem gotów przechowywać treść w S3.

Przechowywanie zduplikowanego e-maila w S3

Przykro mi to stwierdzić, ale nie zamierzam dawać szczegółowego samouczka dotyczącego tworzenia wiadra S3 do przechowywania e-maili ani opisywać, jak stworzyć niezbędny klucz dostępu, który będzie potrzebny w aplikacji do przesyłania zawartości do twojego wiadra; istnieją lepsze poradniki na ten temat niż te, które kiedykolwiek mógłbym napisać.  Oto kilka artykułów, które mogą pomóc:

https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/

To, co zrobię, to wskażę niektóre z ustawień, które wybrałem, odnoszące się do takiego projektu.

  1. Kontrola dostępu.  Musisz nie tylko ustawić zabezpieczenia dla wiadra, ale także ustawić uprawnienia dla samych elementów.  W moim projekcie stosuję bardzo otwartą politykę publicznego odczytu, ponieważ przykładowe dane nie są osobiste i chciałem mieć łatwy dostęp do danych.  Prawdopodobnie będziesz chciał znacznie bardziej rygorystyczny zestaw zasad ACL. Oto dobry artykuł na temat ustawień ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html

  2. Archiwizowanie archiwum. W S3 istnieje coś takiego jak Zarządzanie cyklem życia.  Pozwala to na przenoszenie danych z jednego typu klasy przechowywania S3 do innej.  Różne klasy przechowywania reprezentują ilość dostępu, jakiego potrzebujesz do przechowywanych danych, przy niższych kosztach związanych z przechowywaniem, do którego masz najmniejszy dostęp. Dobry opis różnych klas i przechodzenia przez nie można znaleźć w przewodniku AWS o nazwie, Transitioning Objects. W moim przypadku wybrałem stworzenie cyklu życia, który przenosił każdy obiekt ze Standardu do Glacier po jednym roku. Dostęp do Glacier jest znacznie tańszy niż standardowe archiwum S3 i zaoszczędzi mi pieniądze na kosztach przechowywania.

Gdy mam utworzone wiadro S3 i moje ustawienia są na miejscu, S3 jest gotowe na przesłanie zgodnego z rfc822 e-maila, który uzyskałem z przepływu danych SparkPost Relay Webhook. Ale przed przesłaniem ładunku e-maila rfc822 do S3 muszę stworzyć unikalną nazwę pliku, której użyję do przechowywania tego e-maila.

Dla unikalnej nazwy pliku zamierzam przeszukać treść e-maila pod kątem ukrytego id, które aplikacja wysyłająca umieściła w e-mailu i użyć tego id jako nazwy pliku. Istnieją bardziej eleganckie sposoby na wyciągnięcie connectorId z treści html, ale dla prostoty i jasności zamierzam użyć następującego kodu:

$start = strpos($htmlbody, $inputField);
if ($start !== false) {
    $start = strpos($htmlbody, 'value="', $start);
    if ($start !== false) {
        $start += 7; // Move past 'value="'
        $end = strpos($htmlbody, '"', $start);
        if ($end !== false) {
            $length = $end - $start;
            $UID = substr($htmlbody, $start, $length);
        }
    }
}

* zakładamy, że $inputField zawiera wartość “ArchiveCode” i została znaleziona w moim pliku config.php.

Z UID, możemy potem stworzyć nazwę pliku, która zostanie użyta w S3:

$fileName = $ArchiveDirectory . '/' . $UID . '.eml';

Teraz mogę otworzyć połączenie z S3 i przesłać plik. Jeśli spojrzysz na plik s3.php w repozytorium GitHub, zobaczysz, że potrzeba bardzo mało kodu, aby przesłać plik.

Moim ostatnim krokiem jest zanotowanie tego wpisu w tabeli MYSQL.

Przechowywanie Meta Data w MySQL

Zebraliśmy wszystkie niezbędne dane we wcześniejszym kroku, więc krok przechowywania jest łatwy.  W tej pierwszej fazie wybrałem zbudowanie tabeli z następującymi polami:

  • Zautomatyzowane pole wprowadzania dla daty/czasu

  • Docelowy adres e-mail (RCPT_TO)

  • Znak czasu z nagłówka daty e-maila

  • Nagłówek SUBJECT

  • Nagłówek adresu e-mail FROM

  • Katalog używany w wiadrze S3

  • Nazwa pliku S3 dla zarchiwizowanego e-maila

Funkcja o nazwie MySQLLog w pliku aplikacji upload.php przechodzi przez niezbędne kroki, aby otworzyć link do MySQL, dodać nowy wiersz, przetestować wyniki i zamknąć link. Dodaję jeszcze jeden krok dla pewności, aby zapisać te dane do pliku tekstowego. Czy powinienem prowadzić znacznie więcej logów dla błędów? Tak. Ale chcę utrzymać ten kod lekki, aby działał wyjątkowo szybko. Czasami ten kod będzie wywoływany setki razy na minutę i musi być jak najbardziej wydajny. W przyszłych aktualizacjach dodam dodatkowy kod, który będzie przetwarzał awarie i wysyłał te awarie do administratora do monitorowania.

Podsumowując

Więc w kilku dość prostych krokach udało nam się przejść przez pierwszą fazę budowy solidnego systemu archiwizacji e-maili, który przechowuje duplikat e-maila w S3 i odnosi dane w tabeli MySQL.  Dzięki temu będziemy mieć podstawę do reszty projektu, który będzie realizowany w kilku przyszłych postach.

W przyszłych wersjach tego projektu spodziewałbym się:

  1. Przechowywania wszystkich zdarzeń logowania oryginalnego e-maila

  2. Wysyłania błędów przechowywania do administratora, gdy wystąpi problem z przesyłaniem lub logowaniem

  3. Minimalizowania złożoności kolektora.

  4. Dodania interfejsu użytkownika do przeglądania wszystkich danych

  5. Wsparcia możliwości ponownego wysyłania e-maila

Tymczasem mam nadzieję, że ten projekt był dla Ciebie interesujący i pomocny; miłego wysyłania.

Połączmy Cię z ekspertem Bird.
Zobacz pełną moc Bird w 30 minut.

Przesyłając, zgadzasz się, że Bird może kontaktować się z Tobą w sprawie naszych produktów i usług.

Możesz zrezygnować z subskrypcji w dowolnym momencie. Zobacz Privacy Statement firmy Bird, aby uzyskać szczegóły dotyczące przetwarzania danych.

Company

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.

Połączmy Cię z ekspertem Bird.
Zobacz pełną moc Bird w 30 minut.

Przesyłając, zgadzasz się, że Bird może kontaktować się z Tobą w sprawie naszych produktów i usług.

Możesz zrezygnować z subskrypcji w dowolnym momencie. Zobacz Privacy Statement firmy Bird, aby uzyskać szczegóły dotyczące przetwarzania danych.

Company

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.

Połączmy Cię z ekspertem Bird.
Zobacz pełną moc Bird w 30 minut.

Przesyłając, zgadzasz się, że Bird może kontaktować się z Tobą w sprawie naszych produktów i usług.

Możesz zrezygnować z subskrypcji w dowolnym momencie. Zobacz Privacy Statement firmy Bird, aby uzyskać szczegóły dotyczące przetwarzania danych.

R

Reach

G

Grow

M

Manage

A

Automate

Company

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.