
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:
Tworzenie duplikatu e-maila do archiwizacji
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)
Rozmontuj strukturę JSON, aby uzyskać niezbędne składniki
Wyślij treść e-maila do S3 do przechowywania
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.
Gdzieś w treści wiadomości e-mail umieściłem następujący wpis:<input name="ArchiveCode" type="hidden" value="<<UID>>">
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">
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:
Teraz mamy sposób na powiązanie wszystkich danych z oryginalnej wiadomości e-mail z treścią wiadomości archiwalnej.
Uzyskiwanie wersji Archive
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:
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:
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.
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
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:
* 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ę:
Przechowywania wszystkich zdarzeń logowania oryginalnego e-maila
Wysyłania błędów przechowywania do administratora, gdy wystąpi problem z przesyłaniem lub logowaniem
Minimalizowania złożoności kolektora.
Dodania interfejsu użytkownika do przeglądania wszystkich danych
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.