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
About a year ago I wrote a blog on how to retrieve copies of emails for archival and viewing but I did not broach the actual storing of the email or related data, and recently I wrote a blog on storing all of the event data (i.e. when the email was sent, opens, clicks bounces, unsubscribes, etc) on an email for the purpose of auditing, but chose not to create any supporting code.
With the increase of email usage in regulatory environments, I have decided it is time to start a new project that pulls all of this together with code samples on how to store the email body and all of its associated data. Over the next year, I will continue to build on this project with the aim to create a working storage and viewing application for archived emails and all log information produced by SparkPost. SparkPost does not have a system that archives the email body but it does make building an archival platform fairly easy.
In this blog series, I will describe the process I went through in order to store the email body onto S3 (Amazon’s Simple Store Service) and all relevant log data in MySQL for easy cross-referencing. For production archiving systems that require robust database backup strategies, consider implementing a comprehensive PostgreSQL backup and restore process to ensure your archival data is properly protected. Ultimately, this is the starting point for building an application that will allow for easy searching of archived emails, then displaying those emails along with the event (log) data. The code for this project can be found in the following GitHub repository: PHPArchivePlatform on GitHub
This first entry of the blog series is going to describe the challenge and lay out an architecture for the solution. The rest of the blogs will detail out portions of the solution along with code samples.
The first step in my process was to figure out how I was going to obtain a copy of the email sent to the original recipient. In order to obtain a copy of the email body, you need to either:
Email Body Capture Options
Method | Who creates the copy | Reflects tracking changes | Automation friendly | Used in this solution |
|---|---|---|---|---|
Capture before send | Application | ❌ No | ✅ Yes | ❌ |
Email server stores copy | Mail server | ✅ Yes | ❌ Limited | ❌ |
SparkPost Archive feature | SparkPost | ✅ Yes | ✅ Yes | ✅ |
Capture the email body before sending the email
Get the email server to store a copy
Have the email server create a copy for you to store
If the email server is adding items like link tracking or open tracking, you can’t use #1 because it won’t reflect the open/click tracking changes.
That means that either the server has to store the email or somehow offer a copy of that email to you for storage. Since SparkPost does not have a storage mechanism for email bodies but does have a way to create a copy of the email, we will have SparkPost send us a duplicate of the email for us to store in S3.
This is done by using SparkPost’s Archive feature. SparkPost’s Archive feature gives the sender the ability to tell SparkPost to send a duplicate of the email to one or more email addresses and use the same tracking and open links as the original. SparkPost documentation defines their Archive feature in the following manner:
Recipients in the archive list will receive an exact replica of the message that was sent to the RCPT TO address. In particular, any encoded links intended for the RCPT TO recipient will be identical in the archive messages
The only differences from the RCPT TO email are that some of the headers will be different since the target address for the archiving email is different, but the body of the email will be an exact replica!
If you want a deeper explanation here is a link to the SparkPost documentation on creating duplicate (or archive) copies of an email.
As a side note, SparkPost actually allows you to send emails to cc, bcc, and archive email addresses. For this solution, we are focused on the archive addresses.
* Notice * Archived emails can ONLY be created when injecting emails into SparkPost via SMTP!
Now that we know how to obtain a copy of the original email, we need to look at the log data that is produced and some of the subtle nuances within that data. SparkPost tracks everything that happens on its servers and offers that information up to you in the form of message-events. Those events are stored on SparkPost for 10 days and can be pulled from the server via a RESTful API called message-events, or you can have SparkPost push those events to any number of collecting applications that you wish. The push mechanism is done through webhooks and is done in real time.
Currently, there are 14 different events that may happen to an email. Here is a list of the current events:
Bounce
ClickDelay
Delivery
Generation Failure
Generation Rejection
Initial Open
InjectionLink Unsubscribe
List Unsubscribe
Open
Out of Band
Policy RejectionSpam Complaint
* Follow this link for an up to date reference guide for a description of each event along with the data that is shared for each event.
Each event has numerous fields that match the event type. Some fields like the transmission_id are found in every event, but other fields may be more event-specific; for example, only open and click events have geotag information.
Identifiers Used in the Archiving System
Identifier | Where it originates | Shared across | Purpose | Limitation |
|---|---|---|---|---|
transmission_id | SparkPost outbound | Original, archive, cc, bcc | Correlates all message events | Not available in inbound relay |
message_id | SparkPost outbound | Original + archive | Identifies individual messages | Different for cc/bcc |
Hidden UID | Injected by sender | Outbound + inbound | Links archived email body to events | Must be custom-implemented |
One very important message event entry to this project is the transmission_id. All of the message event entries for the original email, archived email, and any cc and bcc addresses will share the same transmission_id.
There is also a common entry called the message_id that will have the same id for each entry of the original email and the archived email. Any cc or bcc addresses will have their own id for the message_id entry.
So far this sounds great and frankly fairly easy, but now is the challenging part. Remember, in order to get the archive email, we have SparkPost send a duplicate of the original email to another email address which corresponds to some inbox that you have access to. But in order to automate this solution and store the email body, I’m going to use another feature of SparkPost’s called Inbound Email Relaying. What that does, is take all emails sent to a specific domain and process them. By processing them, it rips the email apart and creates a JSON structure which is then delivered to an application via a webhook. See Appendix A for a sample JSON.
If you look real carefully, you will notice that the JSON structure from the inbound relay is missing a very important field; the transmission_id. While all of the outbound emails have the transmission_id with the same entry which binds all of the data from the original email, archive, cc, and bcc addresses; SparkPost has no way to know that the email captured by the inbound process is connected to any of the outbound emails. The inbound process simply knows that an email was sent to a specific domain and to parse the email. That’s it. It will treat any email sent to that domain the same way, be it a reply from a customer or the archive email send from SparkPost.
So the trick is; how do you glue the outbound data to the inbound process that just grabbed the archived version of the email? What I decided to do is to hide a unique id in the body of the email. How this is done is up to you, but I simply created an input field with the hidden tag turned on.
<input name="ArchiveCode" type="hidden" value="<<UID>>">
I also added that field into the metadata block of the X-MSYS-API header which is passed to SparkPost during injection. This hidden UID will end up being the glue to the whole process, and is a main component of the project and will be discussed in depth in the following blog posts.
Now that we have the UID that will glue this project together and understand why it’s necessary, I can start to build the vision of the overall project and corresponding blog posts.
Capturing and storing the archive email along with a database entry for searching/indexing
Capture all message event data
Create an application to view the email and all corresponding data
Here is a simple diagram of the project:

The first drop of code will cover the archive process and storing the email onto S3, while the second code drop will cover storing all of the log data from message-events into MySQL. You can expect the first two code drops and blog entries sometime in early 2019. If you have any questions or suggestions, please feel free to pass them along.
Happy Sending.
– Jeff
Appendix A:

About a year ago I wrote a blog on how to retrieve copies of emails for archival and viewing but I did not broach the actual storing of the email or related data, and recently I wrote a blog on storing all of the event data (i.e. when the email was sent, opens, clicks bounces, unsubscribes, etc) on an email for the purpose of auditing, but chose not to create any supporting code.
With the increase of email usage in regulatory environments, I have decided it is time to start a new project that pulls all of this together with code samples on how to store the email body and all of its associated data. Over the next year, I will continue to build on this project with the aim to create a working storage and viewing application for archived emails and all log information produced by SparkPost. SparkPost does not have a system that archives the email body but it does make building an archival platform fairly easy.
In this blog series, I will describe the process I went through in order to store the email body onto S3 (Amazon’s Simple Store Service) and all relevant log data in MySQL for easy cross-referencing. For production archiving systems that require robust database backup strategies, consider implementing a comprehensive PostgreSQL backup and restore process to ensure your archival data is properly protected. Ultimately, this is the starting point for building an application that will allow for easy searching of archived emails, then displaying those emails along with the event (log) data. The code for this project can be found in the following GitHub repository: PHPArchivePlatform on GitHub
This first entry of the blog series is going to describe the challenge and lay out an architecture for the solution. The rest of the blogs will detail out portions of the solution along with code samples.
The first step in my process was to figure out how I was going to obtain a copy of the email sent to the original recipient. In order to obtain a copy of the email body, you need to either:
Email Body Capture Options
Method | Who creates the copy | Reflects tracking changes | Automation friendly | Used in this solution |
|---|---|---|---|---|
Capture before send | Application | ❌ No | ✅ Yes | ❌ |
Email server stores copy | Mail server | ✅ Yes | ❌ Limited | ❌ |
SparkPost Archive feature | SparkPost | ✅ Yes | ✅ Yes | ✅ |
Capture the email body before sending the email
Get the email server to store a copy
Have the email server create a copy for you to store
If the email server is adding items like link tracking or open tracking, you can’t use #1 because it won’t reflect the open/click tracking changes.
That means that either the server has to store the email or somehow offer a copy of that email to you for storage. Since SparkPost does not have a storage mechanism for email bodies but does have a way to create a copy of the email, we will have SparkPost send us a duplicate of the email for us to store in S3.
This is done by using SparkPost’s Archive feature. SparkPost’s Archive feature gives the sender the ability to tell SparkPost to send a duplicate of the email to one or more email addresses and use the same tracking and open links as the original. SparkPost documentation defines their Archive feature in the following manner:
Recipients in the archive list will receive an exact replica of the message that was sent to the RCPT TO address. In particular, any encoded links intended for the RCPT TO recipient will be identical in the archive messages
The only differences from the RCPT TO email are that some of the headers will be different since the target address for the archiving email is different, but the body of the email will be an exact replica!
If you want a deeper explanation here is a link to the SparkPost documentation on creating duplicate (or archive) copies of an email.
As a side note, SparkPost actually allows you to send emails to cc, bcc, and archive email addresses. For this solution, we are focused on the archive addresses.
* Notice * Archived emails can ONLY be created when injecting emails into SparkPost via SMTP!
Now that we know how to obtain a copy of the original email, we need to look at the log data that is produced and some of the subtle nuances within that data. SparkPost tracks everything that happens on its servers and offers that information up to you in the form of message-events. Those events are stored on SparkPost for 10 days and can be pulled from the server via a RESTful API called message-events, or you can have SparkPost push those events to any number of collecting applications that you wish. The push mechanism is done through webhooks and is done in real time.
Currently, there are 14 different events that may happen to an email. Here is a list of the current events:
Bounce
ClickDelay
Delivery
Generation Failure
Generation Rejection
Initial Open
InjectionLink Unsubscribe
List Unsubscribe
Open
Out of Band
Policy RejectionSpam Complaint
* Follow this link for an up to date reference guide for a description of each event along with the data that is shared for each event.
Each event has numerous fields that match the event type. Some fields like the transmission_id are found in every event, but other fields may be more event-specific; for example, only open and click events have geotag information.
Identifiers Used in the Archiving System
Identifier | Where it originates | Shared across | Purpose | Limitation |
|---|---|---|---|---|
transmission_id | SparkPost outbound | Original, archive, cc, bcc | Correlates all message events | Not available in inbound relay |
message_id | SparkPost outbound | Original + archive | Identifies individual messages | Different for cc/bcc |
Hidden UID | Injected by sender | Outbound + inbound | Links archived email body to events | Must be custom-implemented |
One very important message event entry to this project is the transmission_id. All of the message event entries for the original email, archived email, and any cc and bcc addresses will share the same transmission_id.
There is also a common entry called the message_id that will have the same id for each entry of the original email and the archived email. Any cc or bcc addresses will have their own id for the message_id entry.
So far this sounds great and frankly fairly easy, but now is the challenging part. Remember, in order to get the archive email, we have SparkPost send a duplicate of the original email to another email address which corresponds to some inbox that you have access to. But in order to automate this solution and store the email body, I’m going to use another feature of SparkPost’s called Inbound Email Relaying. What that does, is take all emails sent to a specific domain and process them. By processing them, it rips the email apart and creates a JSON structure which is then delivered to an application via a webhook. See Appendix A for a sample JSON.
If you look real carefully, you will notice that the JSON structure from the inbound relay is missing a very important field; the transmission_id. While all of the outbound emails have the transmission_id with the same entry which binds all of the data from the original email, archive, cc, and bcc addresses; SparkPost has no way to know that the email captured by the inbound process is connected to any of the outbound emails. The inbound process simply knows that an email was sent to a specific domain and to parse the email. That’s it. It will treat any email sent to that domain the same way, be it a reply from a customer or the archive email send from SparkPost.
So the trick is; how do you glue the outbound data to the inbound process that just grabbed the archived version of the email? What I decided to do is to hide a unique id in the body of the email. How this is done is up to you, but I simply created an input field with the hidden tag turned on.
<input name="ArchiveCode" type="hidden" value="<<UID>>">
I also added that field into the metadata block of the X-MSYS-API header which is passed to SparkPost during injection. This hidden UID will end up being the glue to the whole process, and is a main component of the project and will be discussed in depth in the following blog posts.
Now that we have the UID that will glue this project together and understand why it’s necessary, I can start to build the vision of the overall project and corresponding blog posts.
Capturing and storing the archive email along with a database entry for searching/indexing
Capture all message event data
Create an application to view the email and all corresponding data
Here is a simple diagram of the project:

The first drop of code will cover the archive process and storing the email onto S3, while the second code drop will cover storing all of the log data from message-events into MySQL. You can expect the first two code drops and blog entries sometime in early 2019. If you have any questions or suggestions, please feel free to pass them along.
Happy Sending.
– Jeff
Appendix A:

About a year ago I wrote a blog on how to retrieve copies of emails for archival and viewing but I did not broach the actual storing of the email or related data, and recently I wrote a blog on storing all of the event data (i.e. when the email was sent, opens, clicks bounces, unsubscribes, etc) on an email for the purpose of auditing, but chose not to create any supporting code.
With the increase of email usage in regulatory environments, I have decided it is time to start a new project that pulls all of this together with code samples on how to store the email body and all of its associated data. Over the next year, I will continue to build on this project with the aim to create a working storage and viewing application for archived emails and all log information produced by SparkPost. SparkPost does not have a system that archives the email body but it does make building an archival platform fairly easy.
In this blog series, I will describe the process I went through in order to store the email body onto S3 (Amazon’s Simple Store Service) and all relevant log data in MySQL for easy cross-referencing. For production archiving systems that require robust database backup strategies, consider implementing a comprehensive PostgreSQL backup and restore process to ensure your archival data is properly protected. Ultimately, this is the starting point for building an application that will allow for easy searching of archived emails, then displaying those emails along with the event (log) data. The code for this project can be found in the following GitHub repository: PHPArchivePlatform on GitHub
This first entry of the blog series is going to describe the challenge and lay out an architecture for the solution. The rest of the blogs will detail out portions of the solution along with code samples.
The first step in my process was to figure out how I was going to obtain a copy of the email sent to the original recipient. In order to obtain a copy of the email body, you need to either:
Email Body Capture Options
Method | Who creates the copy | Reflects tracking changes | Automation friendly | Used in this solution |
|---|---|---|---|---|
Capture before send | Application | ❌ No | ✅ Yes | ❌ |
Email server stores copy | Mail server | ✅ Yes | ❌ Limited | ❌ |
SparkPost Archive feature | SparkPost | ✅ Yes | ✅ Yes | ✅ |
Capture the email body before sending the email
Get the email server to store a copy
Have the email server create a copy for you to store
If the email server is adding items like link tracking or open tracking, you can’t use #1 because it won’t reflect the open/click tracking changes.
That means that either the server has to store the email or somehow offer a copy of that email to you for storage. Since SparkPost does not have a storage mechanism for email bodies but does have a way to create a copy of the email, we will have SparkPost send us a duplicate of the email for us to store in S3.
This is done by using SparkPost’s Archive feature. SparkPost’s Archive feature gives the sender the ability to tell SparkPost to send a duplicate of the email to one or more email addresses and use the same tracking and open links as the original. SparkPost documentation defines their Archive feature in the following manner:
Recipients in the archive list will receive an exact replica of the message that was sent to the RCPT TO address. In particular, any encoded links intended for the RCPT TO recipient will be identical in the archive messages
The only differences from the RCPT TO email are that some of the headers will be different since the target address for the archiving email is different, but the body of the email will be an exact replica!
If you want a deeper explanation here is a link to the SparkPost documentation on creating duplicate (or archive) copies of an email.
As a side note, SparkPost actually allows you to send emails to cc, bcc, and archive email addresses. For this solution, we are focused on the archive addresses.
* Notice * Archived emails can ONLY be created when injecting emails into SparkPost via SMTP!
Now that we know how to obtain a copy of the original email, we need to look at the log data that is produced and some of the subtle nuances within that data. SparkPost tracks everything that happens on its servers and offers that information up to you in the form of message-events. Those events are stored on SparkPost for 10 days and can be pulled from the server via a RESTful API called message-events, or you can have SparkPost push those events to any number of collecting applications that you wish. The push mechanism is done through webhooks and is done in real time.
Currently, there are 14 different events that may happen to an email. Here is a list of the current events:
Bounce
ClickDelay
Delivery
Generation Failure
Generation Rejection
Initial Open
InjectionLink Unsubscribe
List Unsubscribe
Open
Out of Band
Policy RejectionSpam Complaint
* Follow this link for an up to date reference guide for a description of each event along with the data that is shared for each event.
Each event has numerous fields that match the event type. Some fields like the transmission_id are found in every event, but other fields may be more event-specific; for example, only open and click events have geotag information.
Identifiers Used in the Archiving System
Identifier | Where it originates | Shared across | Purpose | Limitation |
|---|---|---|---|---|
transmission_id | SparkPost outbound | Original, archive, cc, bcc | Correlates all message events | Not available in inbound relay |
message_id | SparkPost outbound | Original + archive | Identifies individual messages | Different for cc/bcc |
Hidden UID | Injected by sender | Outbound + inbound | Links archived email body to events | Must be custom-implemented |
One very important message event entry to this project is the transmission_id. All of the message event entries for the original email, archived email, and any cc and bcc addresses will share the same transmission_id.
There is also a common entry called the message_id that will have the same id for each entry of the original email and the archived email. Any cc or bcc addresses will have their own id for the message_id entry.
So far this sounds great and frankly fairly easy, but now is the challenging part. Remember, in order to get the archive email, we have SparkPost send a duplicate of the original email to another email address which corresponds to some inbox that you have access to. But in order to automate this solution and store the email body, I’m going to use another feature of SparkPost’s called Inbound Email Relaying. What that does, is take all emails sent to a specific domain and process them. By processing them, it rips the email apart and creates a JSON structure which is then delivered to an application via a webhook. See Appendix A for a sample JSON.
If you look real carefully, you will notice that the JSON structure from the inbound relay is missing a very important field; the transmission_id. While all of the outbound emails have the transmission_id with the same entry which binds all of the data from the original email, archive, cc, and bcc addresses; SparkPost has no way to know that the email captured by the inbound process is connected to any of the outbound emails. The inbound process simply knows that an email was sent to a specific domain and to parse the email. That’s it. It will treat any email sent to that domain the same way, be it a reply from a customer or the archive email send from SparkPost.
So the trick is; how do you glue the outbound data to the inbound process that just grabbed the archived version of the email? What I decided to do is to hide a unique id in the body of the email. How this is done is up to you, but I simply created an input field with the hidden tag turned on.
<input name="ArchiveCode" type="hidden" value="<<UID>>">
I also added that field into the metadata block of the X-MSYS-API header which is passed to SparkPost during injection. This hidden UID will end up being the glue to the whole process, and is a main component of the project and will be discussed in depth in the following blog posts.
Now that we have the UID that will glue this project together and understand why it’s necessary, I can start to build the vision of the overall project and corresponding blog posts.
Capturing and storing the archive email along with a database entry for searching/indexing
Capture all message event data
Create an application to view the email and all corresponding data
Here is a simple diagram of the project:

The first drop of code will cover the archive process and storing the email onto S3, while the second code drop will cover storing all of the log data from message-events into MySQL. You can expect the first two code drops and blog entries sometime in early 2019. If you have any questions or suggestions, please feel free to pass them along.
Happy Sending.
– Jeff
Appendix A:

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.
<input name="ArchiveCode" type="hidden" value="<<UID>>">
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:

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.
<input name="ArchiveCode" type="hidden" value="<<UID>>">
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:

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.
<input name="ArchiveCode" type="hidden" value="<<UID>>">
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:




