Costruire un sistema di archiviazione delle email: memorizzare il corpo dell'email
Uccello
4 mar 2019
1 min read

Conclusioni principali
Scopo: Questo post delinea la prima fase della costruzione di un sistema di archiviazione email utilizzando SparkPost, Amazon S3, e MySQL. Spiega come duplicare, catturare e memorizzare email per accesso a lungo termine e conformità.
Idea principale: Il sistema memorizza automaticamente il corpo email grezzo (formato rfc822) in S3 e registra i metadati (oggetto, mittente, timestamp, ecc.) in MySQL per una ricerca e recupero rapidi.
Essenziali coperti:
Creazione di duplicati per l'archiviazione: Usa la funzionalità Archivia di SparkPost per inviare copie identiche di email in uscita a un indirizzo di archivio designato, assicurando che il corpo e i link di tracciamento rimangano identici.
Associazione dei dati tramite UID: Inserisci un identificatore univoco (UID) sia nel corpo dell'email che nei metadati X-MSYS-API per collegare i messaggi originali e archiviati.
Elaborazione in entrata: Configura un dominio in entrata e webhook in SparkPost per ricevere i payload JSON delle email archiviate tramite un raccoglitore di applicazioni.
Archiviazione delle email in S3: Carica il corpo rfc822 analizzato in un bucket S3, utilizzando regole di ciclo di vita (ad esempio, transizione a Glacier dopo un anno) per ridurre i costi di archiviazione.
Registrazione dei metadati in MySQL: Memorizza campi chiave come RCPT_TO, FROM, SUBJECT e nome file S3 per l'indicizzazione delle ricerche e il recupero futuro.
Considerazioni sulle prestazioni: L'efficienza del codice e il minimo log garantiscono che il raccoglitore possa gestire centinaia di richieste al minuto con una latenza minima.
Visione d'insieme: Questa base supporta futuri miglioramenti—come la memorizzazione degli eventi di log, gli avvisi di errore e la visualizzazione dell'interfaccia utente—ponendo le basi per una soluzione di archiviazione email scalabile e verificabile.
Q&A Highlights
Qual è l'obiettivo di questo progetto?
Per creare un sistema di archiviazione delle email automatizzato che memorizza i corpi dei messaggi in Amazon S3 mantenendo i metadati ricercabili in un database MySQL.
Perché usare la funzione Archive di SparkPost?
Consente di generare duplicati esatti delle email in uscita, preservandone la struttura e i dati di tracciamento per la conformità e la revisione.
Come è collegata ogni email archiviata al suo messaggio originale?
Un UID unico è incorporato sia nel corpo dell'email che nei metadati, consentendo un riferimento incrociato accurato tra le copie originali e archiviate.
Perché usare S3 per lo storage?
S3 offre opzioni di archiviazione scalabili e gestione del ciclo di vita (come Glacier), rendendolo conveniente per la conservazione a lungo termine delle email.
Cosa conserva il database MySQL?
Conserva campi di metadati ricercabili, come la linea dell'oggetto, il mittente, i timestamp e il nome del file S3, consentendo una query e un recupero efficienti.
Quali sono i prossimi passi di sviluppo?
Aggiunta del tracciamento degli eventi di log, segnalazione automatica degli errori, un raccoglitore semplificato e un'interfaccia utente per visualizzare o rinviare le email archiviate.
In questo blog, descriverò il processo che ho seguito per memorizzare il corpo dell'email su S3 (Amazon's Simple Store Service) e i dati ausiliari in una tabella MySQL per un facile riferimento incrociato. Questo è il punto di partenza per la base di codice che includerà un'applicazione che consentirà una facile ricerca delle email archiviate e la visualizzazione di tali email insieme ai dati dell'evento (log). Il codice di questo progetto può essere trovato nel seguente repository GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Sebbene userò S3 e MySQL in questo progetto, non sono assolutamente le uniche tecnologie che possono essere utilizzate per costruire una piattaforma di archiviazione, ma data la loro ubiquità, ho pensato che fossero una buona scelta per questo progetto. In un sistema ad alta scala e alto volume utilizzerei un database con prestazioni migliori rispetto a MySQL, ma per questo progetto di esempio, MySQL è perfetto. Per le organizzazioni che considerano PostgreSQL come la loro scelta di database di archiviazione, implementare correttamente le procedure di backup e ripristino è essenziale per mantenere l'integrità dei dati nei sistemi di produzione.
Ho dettagliato di seguito i passaggi che ho intrapreso in questa prima fase del progetto:
Creazione dell'email duplicata per l'archiviazione
Usare le funzionalità di Archiving e Inbound Relay di SparkPost per inviare una copia dell'email originale nuovamente a SparkPost per l'elaborazione in una struttura JSON, quindi inviata a un raccoglitore webhook (applicazione)
Smontare la struttura JSON per ottenere i componenti necessari
Inviare il corpo dell'email a S3 per la memorizzazione
Registrare un'entrata in MySQL per ogni email per il riferimento incrociato
In questo blog, descriverò il processo che ho seguito per memorizzare il corpo dell'email su S3 (Amazon's Simple Store Service) e i dati ausiliari in una tabella MySQL per un facile riferimento incrociato. Questo è il punto di partenza per la base di codice che includerà un'applicazione che consentirà una facile ricerca delle email archiviate e la visualizzazione di tali email insieme ai dati dell'evento (log). Il codice di questo progetto può essere trovato nel seguente repository GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Sebbene userò S3 e MySQL in questo progetto, non sono assolutamente le uniche tecnologie che possono essere utilizzate per costruire una piattaforma di archiviazione, ma data la loro ubiquità, ho pensato che fossero una buona scelta per questo progetto. In un sistema ad alta scala e alto volume utilizzerei un database con prestazioni migliori rispetto a MySQL, ma per questo progetto di esempio, MySQL è perfetto. Per le organizzazioni che considerano PostgreSQL come la loro scelta di database di archiviazione, implementare correttamente le procedure di backup e ripristino è essenziale per mantenere l'integrità dei dati nei sistemi di produzione.
Ho dettagliato di seguito i passaggi che ho intrapreso in questa prima fase del progetto:
Creazione dell'email duplicata per l'archiviazione
Usare le funzionalità di Archiving e Inbound Relay di SparkPost per inviare una copia dell'email originale nuovamente a SparkPost per l'elaborazione in una struttura JSON, quindi inviata a un raccoglitore webhook (applicazione)
Smontare la struttura JSON per ottenere i componenti necessari
Inviare il corpo dell'email a S3 per la memorizzazione
Registrare un'entrata in MySQL per ogni email per il riferimento incrociato
In questo blog, descriverò il processo che ho seguito per memorizzare il corpo dell'email su S3 (Amazon's Simple Store Service) e i dati ausiliari in una tabella MySQL per un facile riferimento incrociato. Questo è il punto di partenza per la base di codice che includerà un'applicazione che consentirà una facile ricerca delle email archiviate e la visualizzazione di tali email insieme ai dati dell'evento (log). Il codice di questo progetto può essere trovato nel seguente repository GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Sebbene userò S3 e MySQL in questo progetto, non sono assolutamente le uniche tecnologie che possono essere utilizzate per costruire una piattaforma di archiviazione, ma data la loro ubiquità, ho pensato che fossero una buona scelta per questo progetto. In un sistema ad alta scala e alto volume utilizzerei un database con prestazioni migliori rispetto a MySQL, ma per questo progetto di esempio, MySQL è perfetto. Per le organizzazioni che considerano PostgreSQL come la loro scelta di database di archiviazione, implementare correttamente le procedure di backup e ripristino è essenziale per mantenere l'integrità dei dati nei sistemi di produzione.
Ho dettagliato di seguito i passaggi che ho intrapreso in questa prima fase del progetto:
Creazione dell'email duplicata per l'archiviazione
Usare le funzionalità di Archiving e Inbound Relay di SparkPost per inviare una copia dell'email originale nuovamente a SparkPost per l'elaborazione in una struttura JSON, quindi inviata a un raccoglitore webhook (applicazione)
Smontare la struttura JSON per ottenere i componenti necessari
Inviare il corpo dell'email a S3 per la memorizzazione
Registrare un'entrata in MySQL per ogni email per il riferimento incrociato
Creare un Duplicate dell'Email
In SparkPost il modo migliore per archiviare un'email è creare una copia identica dell'email specificamente progettata per scopi di archiviazione. Questo viene fatto utilizzando la funzione Archive di SparkPost. La funzione Archive di SparkPost dà al mittente la capacità di inviare un duplicato dell'email a uno o più indirizzi email. Questo duplicato utilizza gli stessi link di tracciamento e apertura dell'originale. La documentazione di SparkPost definisce la funzione Archive nel modo seguente:
I destinatari nella lista di archivio riceveranno una replica esatta del messaggio inviato all'indirizzo RCPT TO. In particolare, qualsiasi link codificato destinato al destinatario RCPT TO sarà identico nei messaggi di archivio
L'unica differenza tra questa copia di archivio e l'email originale RCPT TO è che alcune intestazioni saranno diverse poiché l'indirizzo di destinazione per l'email di archiviazione è differente, ma il corpo dell'email sarà una replica esatta!
Se vuoi una spiegazione più approfondita, ecco un link alla documentazione di SparkPost sulla creazione di copie duplicate (o di archivio) di un'email. Gli esempi di intestazioni X-MSYS-API per questo progetto sono mostrati più avanti in questo blog.
C'è un avvertimento a questo approccio; mentre tutte le informazioni sull'evento nell'email originale sono collegate insieme da un transmission_id e un message_id, non ci sono informazioni nell'evento di inoltro in entrata (il meccanismo per ottenere e diffondere l'email di archivio) per l'email duplicata che si collega a uno di quei due id e quindi alle informazioni per l'email originale. Questo significa che dobbiamo inserire dei dati nel corpo dell'email e nell'intestazione dell'email originale come modo per collegare insieme tutti i dati di SparkPost dall'email originale e dall'email di archivio.
Per creare il codice che viene inserito nel corpo dell'email, ho utilizzato il seguente processo nell'applicazione di creazione dell'email.
Da qualche parte nel corpo dell'email, ho inserito il seguente ingresso:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Poi ho creato un codice univoco e ho sostituito il campo <<UID>>:$uid = md5(uniqid(rand(), true)); $emailBody = str_replace(“<<UID>>,$uid,$emailBody);
Ecco un esempio di output:
<input name="ArchiveCode" type="hidden" value="00006365263145">
Successivamente, mi sono assicurato di aggiungere il $UID al blocco meta_data dell'intestazione X-MSYS-API. Questo passaggio assicura che il UID sia incorporato in ciascun output di evento per l'email originale:
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>" } }
Ora abbiamo un modo per collegare tutti i dati dall'email originale al corpo dell'email di archivio.
In SparkPost il modo migliore per archiviare un'email è creare una copia identica dell'email specificamente progettata per scopi di archiviazione. Questo viene fatto utilizzando la funzione Archive di SparkPost. La funzione Archive di SparkPost dà al mittente la capacità di inviare un duplicato dell'email a uno o più indirizzi email. Questo duplicato utilizza gli stessi link di tracciamento e apertura dell'originale. La documentazione di SparkPost definisce la funzione Archive nel modo seguente:
I destinatari nella lista di archivio riceveranno una replica esatta del messaggio inviato all'indirizzo RCPT TO. In particolare, qualsiasi link codificato destinato al destinatario RCPT TO sarà identico nei messaggi di archivio
L'unica differenza tra questa copia di archivio e l'email originale RCPT TO è che alcune intestazioni saranno diverse poiché l'indirizzo di destinazione per l'email di archiviazione è differente, ma il corpo dell'email sarà una replica esatta!
Se vuoi una spiegazione più approfondita, ecco un link alla documentazione di SparkPost sulla creazione di copie duplicate (o di archivio) di un'email. Gli esempi di intestazioni X-MSYS-API per questo progetto sono mostrati più avanti in questo blog.
C'è un avvertimento a questo approccio; mentre tutte le informazioni sull'evento nell'email originale sono collegate insieme da un transmission_id e un message_id, non ci sono informazioni nell'evento di inoltro in entrata (il meccanismo per ottenere e diffondere l'email di archivio) per l'email duplicata che si collega a uno di quei due id e quindi alle informazioni per l'email originale. Questo significa che dobbiamo inserire dei dati nel corpo dell'email e nell'intestazione dell'email originale come modo per collegare insieme tutti i dati di SparkPost dall'email originale e dall'email di archivio.
Per creare il codice che viene inserito nel corpo dell'email, ho utilizzato il seguente processo nell'applicazione di creazione dell'email.
Da qualche parte nel corpo dell'email, ho inserito il seguente ingresso:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Poi ho creato un codice univoco e ho sostituito il campo <<UID>>:$uid = md5(uniqid(rand(), true)); $emailBody = str_replace(“<<UID>>,$uid,$emailBody);
Ecco un esempio di output:
<input name="ArchiveCode" type="hidden" value="00006365263145">
Successivamente, mi sono assicurato di aggiungere il $UID al blocco meta_data dell'intestazione X-MSYS-API. Questo passaggio assicura che il UID sia incorporato in ciascun output di evento per l'email originale:
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>" } }
Ora abbiamo un modo per collegare tutti i dati dall'email originale al corpo dell'email di archivio.
In SparkPost il modo migliore per archiviare un'email è creare una copia identica dell'email specificamente progettata per scopi di archiviazione. Questo viene fatto utilizzando la funzione Archive di SparkPost. La funzione Archive di SparkPost dà al mittente la capacità di inviare un duplicato dell'email a uno o più indirizzi email. Questo duplicato utilizza gli stessi link di tracciamento e apertura dell'originale. La documentazione di SparkPost definisce la funzione Archive nel modo seguente:
I destinatari nella lista di archivio riceveranno una replica esatta del messaggio inviato all'indirizzo RCPT TO. In particolare, qualsiasi link codificato destinato al destinatario RCPT TO sarà identico nei messaggi di archivio
L'unica differenza tra questa copia di archivio e l'email originale RCPT TO è che alcune intestazioni saranno diverse poiché l'indirizzo di destinazione per l'email di archiviazione è differente, ma il corpo dell'email sarà una replica esatta!
Se vuoi una spiegazione più approfondita, ecco un link alla documentazione di SparkPost sulla creazione di copie duplicate (o di archivio) di un'email. Gli esempi di intestazioni X-MSYS-API per questo progetto sono mostrati più avanti in questo blog.
C'è un avvertimento a questo approccio; mentre tutte le informazioni sull'evento nell'email originale sono collegate insieme da un transmission_id e un message_id, non ci sono informazioni nell'evento di inoltro in entrata (il meccanismo per ottenere e diffondere l'email di archivio) per l'email duplicata che si collega a uno di quei due id e quindi alle informazioni per l'email originale. Questo significa che dobbiamo inserire dei dati nel corpo dell'email e nell'intestazione dell'email originale come modo per collegare insieme tutti i dati di SparkPost dall'email originale e dall'email di archivio.
Per creare il codice che viene inserito nel corpo dell'email, ho utilizzato il seguente processo nell'applicazione di creazione dell'email.
Da qualche parte nel corpo dell'email, ho inserito il seguente ingresso:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Poi ho creato un codice univoco e ho sostituito il campo <<UID>>:$uid = md5(uniqid(rand(), true)); $emailBody = str_replace(“<<UID>>,$uid,$emailBody);
Ecco un esempio di output:
<input name="ArchiveCode" type="hidden" value="00006365263145">
Successivamente, mi sono assicurato di aggiungere il $UID al blocco meta_data dell'intestazione X-MSYS-API. Questo passaggio assicura che il UID sia incorporato in ciascun output di evento per l'email originale:
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>" } }
Ora abbiamo un modo per collegare tutti i dati dall'email originale al corpo dell'email di archivio.
Ottenere la versione Archive
Per ottenere una copia di un'email per archivio, è necessario seguire i seguenti passaggi:
Crea un sottodominio a cui invierai tutte le email di archivio (duplicati)
Imposta i record DNS appropriati affinché tutte le email inviate a quel sottodominio siano indirizzate a SparkPost
Crea un dominio inbound in SparkPost
Crea un webhook inbound in SparkPost
Crea un'applicazione (collettore) per ricevere il flusso di dati webhook di SparkPost
I seguenti due link possono essere utilizzati per guidarti attraverso questo processo:
Documento tecnico di SparkPost: Enabling Inbound Email Relaying & Relay Webhooks
Inoltre, il blog che ho scritto l'anno scorso, Archiving Emails: A How-To Guide for Tracking Sent Mail ti guiderà nella creazione del relay inbound all'interno di SparkPost
* Nota: a partire da ottobre 2018, la funzione di archivio funziona solo quando si inviano email utilizzando una connessione SMTP a SparkPost, l'API RESTful non supporta questa funzione. Probabilmente non è un problema perché la maggior parte delle email che necessita di questo livello di controllo di audit tende a essere personalizzata e completamente costruita da un'applicazione backend prima che sia necessaria la consegna dell'email.
Per ottenere una copia di un'email per archivio, è necessario seguire i seguenti passaggi:
Crea un sottodominio a cui invierai tutte le email di archivio (duplicati)
Imposta i record DNS appropriati affinché tutte le email inviate a quel sottodominio siano indirizzate a SparkPost
Crea un dominio inbound in SparkPost
Crea un webhook inbound in SparkPost
Crea un'applicazione (collettore) per ricevere il flusso di dati webhook di SparkPost
I seguenti due link possono essere utilizzati per guidarti attraverso questo processo:
Documento tecnico di SparkPost: Enabling Inbound Email Relaying & Relay Webhooks
Inoltre, il blog che ho scritto l'anno scorso, Archiving Emails: A How-To Guide for Tracking Sent Mail ti guiderà nella creazione del relay inbound all'interno di SparkPost
* Nota: a partire da ottobre 2018, la funzione di archivio funziona solo quando si inviano email utilizzando una connessione SMTP a SparkPost, l'API RESTful non supporta questa funzione. Probabilmente non è un problema perché la maggior parte delle email che necessita di questo livello di controllo di audit tende a essere personalizzata e completamente costruita da un'applicazione backend prima che sia necessaria la consegna dell'email.
Per ottenere una copia di un'email per archivio, è necessario seguire i seguenti passaggi:
Crea un sottodominio a cui invierai tutte le email di archivio (duplicati)
Imposta i record DNS appropriati affinché tutte le email inviate a quel sottodominio siano indirizzate a SparkPost
Crea un dominio inbound in SparkPost
Crea un webhook inbound in SparkPost
Crea un'applicazione (collettore) per ricevere il flusso di dati webhook di SparkPost
I seguenti due link possono essere utilizzati per guidarti attraverso questo processo:
Documento tecnico di SparkPost: Enabling Inbound Email Relaying & Relay Webhooks
Inoltre, il blog che ho scritto l'anno scorso, Archiving Emails: A How-To Guide for Tracking Sent Mail ti guiderà nella creazione del relay inbound all'interno di SparkPost
* Nota: a partire da ottobre 2018, la funzione di archivio funziona solo quando si inviano email utilizzando una connessione SMTP a SparkPost, l'API RESTful non supporta questa funzione. Probabilmente non è un problema perché la maggior parte delle email che necessita di questo livello di controllo di audit tende a essere personalizzata e completamente costruita da un'applicazione backend prima che sia necessaria la consegna dell'email.
Ottenere l'email duplicata in una struttura JSON
Nella prima fase di questo progetto, tutto ciò che sto memorizzando è il formato email rfc822 in S3 e alcuni campi descrittivi di alto livello in una tabella SQL per la ricerca. Poiché SparkPost invierà i dati dell'email in una struttura JSON alla mia piattaforma di archiviazione tramite flussi di dati webhook, ho costruito un'applicazione (spesso chiamata collector) che accetta il flusso di dati Relay_Webhook.
Ogni pacchetto dal SparkPost Relay_Webhook conterrà le informazioni di un'email duplicata alla volta, quindi suddividere la struttura JSON nei componenti mirati per questo progetto è piuttosto semplice. Nel mio codice PHP, ottenere l'email formattata rfc822 è stato facile come le seguenti poche righe di codice:
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']; }
Alcune delle informazioni che voglio memorizzare nella mia tabella SQL risiedono in un array di campi header. Quindi ho scritto una piccola funzione che accetta l'array dell'header e passa in rassegna l'array per ottenere i dati che mi interessano memorizzare:
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; } } } }
Ora che ho i dati, sono pronto a memorizzare il corpo in S3.
Nella prima fase di questo progetto, tutto ciò che sto memorizzando è il formato email rfc822 in S3 e alcuni campi descrittivi di alto livello in una tabella SQL per la ricerca. Poiché SparkPost invierà i dati dell'email in una struttura JSON alla mia piattaforma di archiviazione tramite flussi di dati webhook, ho costruito un'applicazione (spesso chiamata collector) che accetta il flusso di dati Relay_Webhook.
Ogni pacchetto dal SparkPost Relay_Webhook conterrà le informazioni di un'email duplicata alla volta, quindi suddividere la struttura JSON nei componenti mirati per questo progetto è piuttosto semplice. Nel mio codice PHP, ottenere l'email formattata rfc822 è stato facile come le seguenti poche righe di codice:
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']; }
Alcune delle informazioni che voglio memorizzare nella mia tabella SQL risiedono in un array di campi header. Quindi ho scritto una piccola funzione che accetta l'array dell'header e passa in rassegna l'array per ottenere i dati che mi interessano memorizzare:
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; } } } }
Ora che ho i dati, sono pronto a memorizzare il corpo in S3.
Nella prima fase di questo progetto, tutto ciò che sto memorizzando è il formato email rfc822 in S3 e alcuni campi descrittivi di alto livello in una tabella SQL per la ricerca. Poiché SparkPost invierà i dati dell'email in una struttura JSON alla mia piattaforma di archiviazione tramite flussi di dati webhook, ho costruito un'applicazione (spesso chiamata collector) che accetta il flusso di dati Relay_Webhook.
Ogni pacchetto dal SparkPost Relay_Webhook conterrà le informazioni di un'email duplicata alla volta, quindi suddividere la struttura JSON nei componenti mirati per questo progetto è piuttosto semplice. Nel mio codice PHP, ottenere l'email formattata rfc822 è stato facile come le seguenti poche righe di codice:
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']; }
Alcune delle informazioni che voglio memorizzare nella mia tabella SQL risiedono in un array di campi header. Quindi ho scritto una piccola funzione che accetta l'array dell'header e passa in rassegna l'array per ottenere i dati che mi interessano memorizzare:
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; } } } }
Ora che ho i dati, sono pronto a memorizzare il corpo in S3.
Memorizzazione dell'email duplicata in S3
Mi dispiace deluderti ma non ho intenzione di offrire un tutorial passo-passo su come creare un bucket S3 per memorizzare l'email, né descriverò come creare la chiave di accesso necessaria che avrai bisogno nella tua applicazione per caricare contenuti nel tuo bucket; ci sono tutorial migliori su questo argomento di quelli che potrei mai scrivere. Ecco un paio di articoli che potrebbero aiutare:
https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/
Quello che farò è sottolineare alcuni dei settaggi che ho scelto che riguardano un progetto come questo.
Controllo dell'accesso. Non solo devi impostare la sicurezza per il bucket, ma devi anche impostare i permessi per gli oggetti stessi. Nel mio progetto, uso una politica molto aperta di public-read perché i dati di esempio non sono personali e volevo un facile accesso ai dati. Probabilmente vorrai un set di politiche ACL molto più rigido. Qui c'è un bel articolo sui settaggi ACL:https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Archiviazione dell'archivio. In S3 c'è qualcosa chiamato Lifecycle Management. Questo ti permette di spostare i dati da un tipo di classe di archiviazione S3 a un altro. Le diverse classi di archiviazione rappresentano la quantità di accesso di cui hai bisogno ai dati archiviati con costi minori associati all'archiviazione a cui accedi di meno. Un buon riassunto delle varie classi e della loro transizione può essere trovato in una guida AWS chiamata, Transitioning Objects. Nel mio caso, ho scelto di creare un ciclo di vita che spostava ogni oggetto da Standard a Glacier dopo un anno. L'accesso Glacier è molto più economico della normale archiviazione S3 e mi farà risparmiare sui costi di archiviazione.
Una volta creato il bucket S3 e impostati i miei settaggi, S3 è pronto per evitare di caricare l'email conforme a rfc822 che ho ottenuto dal flusso di dati SparkPost Relay Webhook. Ma prima di caricare il payload email rfc822 su S3, devo creare un nome di file unico che userò per memorizzare quell'email.
Per il nome di file unico, cercherò nel corpo dell'email l'id nascosto che l'applicazione inviante ha inserito nell'email e utilizzerò quell'id come nome del file. Ci sono modi più eleganti per estrarre il connectorId dal corpo html, ma per semplicità e chiarezza userò il seguente codice:
$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); } } }
* stiamo assumendo che $inputField contenga il valore “ArchiveCode” e sia stato trovato nel mio file config.php.
Con l'UID, possiamo poi creare il nome del file che verrà utilizzato in S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Ora sono in grado di aprire la mia connessione a S3 e caricare il file. Se guardi il file s3.php nel repository GitHub vedrai che ci vuole molto poco codice per caricare il file.
Il mio ultimo passo è registrare questa voce nella tabella MYSQL.
Mi dispiace deluderti ma non ho intenzione di offrire un tutorial passo-passo su come creare un bucket S3 per memorizzare l'email, né descriverò come creare la chiave di accesso necessaria che avrai bisogno nella tua applicazione per caricare contenuti nel tuo bucket; ci sono tutorial migliori su questo argomento di quelli che potrei mai scrivere. Ecco un paio di articoli che potrebbero aiutare:
https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/
Quello che farò è sottolineare alcuni dei settaggi che ho scelto che riguardano un progetto come questo.
Controllo dell'accesso. Non solo devi impostare la sicurezza per il bucket, ma devi anche impostare i permessi per gli oggetti stessi. Nel mio progetto, uso una politica molto aperta di public-read perché i dati di esempio non sono personali e volevo un facile accesso ai dati. Probabilmente vorrai un set di politiche ACL molto più rigido. Qui c'è un bel articolo sui settaggi ACL:https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Archiviazione dell'archivio. In S3 c'è qualcosa chiamato Lifecycle Management. Questo ti permette di spostare i dati da un tipo di classe di archiviazione S3 a un altro. Le diverse classi di archiviazione rappresentano la quantità di accesso di cui hai bisogno ai dati archiviati con costi minori associati all'archiviazione a cui accedi di meno. Un buon riassunto delle varie classi e della loro transizione può essere trovato in una guida AWS chiamata, Transitioning Objects. Nel mio caso, ho scelto di creare un ciclo di vita che spostava ogni oggetto da Standard a Glacier dopo un anno. L'accesso Glacier è molto più economico della normale archiviazione S3 e mi farà risparmiare sui costi di archiviazione.
Una volta creato il bucket S3 e impostati i miei settaggi, S3 è pronto per evitare di caricare l'email conforme a rfc822 che ho ottenuto dal flusso di dati SparkPost Relay Webhook. Ma prima di caricare il payload email rfc822 su S3, devo creare un nome di file unico che userò per memorizzare quell'email.
Per il nome di file unico, cercherò nel corpo dell'email l'id nascosto che l'applicazione inviante ha inserito nell'email e utilizzerò quell'id come nome del file. Ci sono modi più eleganti per estrarre il connectorId dal corpo html, ma per semplicità e chiarezza userò il seguente codice:
$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); } } }
* stiamo assumendo che $inputField contenga il valore “ArchiveCode” e sia stato trovato nel mio file config.php.
Con l'UID, possiamo poi creare il nome del file che verrà utilizzato in S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Ora sono in grado di aprire la mia connessione a S3 e caricare il file. Se guardi il file s3.php nel repository GitHub vedrai che ci vuole molto poco codice per caricare il file.
Il mio ultimo passo è registrare questa voce nella tabella MYSQL.
Mi dispiace deluderti ma non ho intenzione di offrire un tutorial passo-passo su come creare un bucket S3 per memorizzare l'email, né descriverò come creare la chiave di accesso necessaria che avrai bisogno nella tua applicazione per caricare contenuti nel tuo bucket; ci sono tutorial migliori su questo argomento di quelli che potrei mai scrivere. Ecco un paio di articoli che potrebbero aiutare:
https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/
Quello che farò è sottolineare alcuni dei settaggi che ho scelto che riguardano un progetto come questo.
Controllo dell'accesso. Non solo devi impostare la sicurezza per il bucket, ma devi anche impostare i permessi per gli oggetti stessi. Nel mio progetto, uso una politica molto aperta di public-read perché i dati di esempio non sono personali e volevo un facile accesso ai dati. Probabilmente vorrai un set di politiche ACL molto più rigido. Qui c'è un bel articolo sui settaggi ACL:https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Archiviazione dell'archivio. In S3 c'è qualcosa chiamato Lifecycle Management. Questo ti permette di spostare i dati da un tipo di classe di archiviazione S3 a un altro. Le diverse classi di archiviazione rappresentano la quantità di accesso di cui hai bisogno ai dati archiviati con costi minori associati all'archiviazione a cui accedi di meno. Un buon riassunto delle varie classi e della loro transizione può essere trovato in una guida AWS chiamata, Transitioning Objects. Nel mio caso, ho scelto di creare un ciclo di vita che spostava ogni oggetto da Standard a Glacier dopo un anno. L'accesso Glacier è molto più economico della normale archiviazione S3 e mi farà risparmiare sui costi di archiviazione.
Una volta creato il bucket S3 e impostati i miei settaggi, S3 è pronto per evitare di caricare l'email conforme a rfc822 che ho ottenuto dal flusso di dati SparkPost Relay Webhook. Ma prima di caricare il payload email rfc822 su S3, devo creare un nome di file unico che userò per memorizzare quell'email.
Per il nome di file unico, cercherò nel corpo dell'email l'id nascosto che l'applicazione inviante ha inserito nell'email e utilizzerò quell'id come nome del file. Ci sono modi più eleganti per estrarre il connectorId dal corpo html, ma per semplicità e chiarezza userò il seguente codice:
$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); } } }
* stiamo assumendo che $inputField contenga il valore “ArchiveCode” e sia stato trovato nel mio file config.php.
Con l'UID, possiamo poi creare il nome del file che verrà utilizzato in S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Ora sono in grado di aprire la mia connessione a S3 e caricare il file. Se guardi il file s3.php nel repository GitHub vedrai che ci vuole molto poco codice per caricare il file.
Il mio ultimo passo è registrare questa voce nella tabella MYSQL.
Archiviare i Meta Data in MySQL
Abbiamo raccolto tutti i dati necessari in un passaggio precedente, quindi la fase di archiviazione è facile. In questa prima fase ho scelto di costruire una tabella con i seguenti campi:
Campi di Metadata MySQL
Campo | Scopo |
Data/ora (auto) | Timestamp quando la voce è stata registrata |
RCPT_TO address | Indirizzo email target per il messaggio archiviato |
Timestamp dell'intestazione DATE | Ora di invio originale dell'email |
Intestazione SUBJECT | Riga dell'oggetto per l'indicizzazione e la ricerca |
Intestazione FROM | Identificatore del mittente per la ricerca |
Directory S3 | Percorso della directory all'interno del bucket S3 |
Nome file S3 | File .eml unico memorizzato in S3 |
La funzione chiamata, MySQLLog all'interno del file applicazione upload.php esegue i passaggi necessari per aprire il link a MySQL, inserire la nuova riga, testare i risultati e chiudere il link. Aggiungo un altro passaggio per buona misura, che è registrare questi dati in un file di testo. Dovrei fare molto più logging per gli errori? Sì. Ma voglio mantenere questo codice leggero per permettergli di essere estremamente rapido. A volte questo codice sarà chiamato centinaia di volte al minuto e deve essere il più efficiente possibile. Negli aggiornamenti futuri, aggiungerò codice accessorio che elaborerà i fallimenti e invierà tali fallimenti a un amministratore per il monitoraggio.
Abbiamo raccolto tutti i dati necessari in un passaggio precedente, quindi la fase di archiviazione è facile. In questa prima fase ho scelto di costruire una tabella con i seguenti campi:
Campi di Metadata MySQL
Campo | Scopo |
Data/ora (auto) | Timestamp quando la voce è stata registrata |
RCPT_TO address | Indirizzo email target per il messaggio archiviato |
Timestamp dell'intestazione DATE | Ora di invio originale dell'email |
Intestazione SUBJECT | Riga dell'oggetto per l'indicizzazione e la ricerca |
Intestazione FROM | Identificatore del mittente per la ricerca |
Directory S3 | Percorso della directory all'interno del bucket S3 |
Nome file S3 | File .eml unico memorizzato in S3 |
La funzione chiamata, MySQLLog all'interno del file applicazione upload.php esegue i passaggi necessari per aprire il link a MySQL, inserire la nuova riga, testare i risultati e chiudere il link. Aggiungo un altro passaggio per buona misura, che è registrare questi dati in un file di testo. Dovrei fare molto più logging per gli errori? Sì. Ma voglio mantenere questo codice leggero per permettergli di essere estremamente rapido. A volte questo codice sarà chiamato centinaia di volte al minuto e deve essere il più efficiente possibile. Negli aggiornamenti futuri, aggiungerò codice accessorio che elaborerà i fallimenti e invierà tali fallimenti a un amministratore per il monitoraggio.
Abbiamo raccolto tutti i dati necessari in un passaggio precedente, quindi la fase di archiviazione è facile. In questa prima fase ho scelto di costruire una tabella con i seguenti campi:
Campi di Metadata MySQL
Campo | Scopo |
Data/ora (auto) | Timestamp quando la voce è stata registrata |
RCPT_TO address | Indirizzo email target per il messaggio archiviato |
Timestamp dell'intestazione DATE | Ora di invio originale dell'email |
Intestazione SUBJECT | Riga dell'oggetto per l'indicizzazione e la ricerca |
Intestazione FROM | Identificatore del mittente per la ricerca |
Directory S3 | Percorso della directory all'interno del bucket S3 |
Nome file S3 | File .eml unico memorizzato in S3 |
La funzione chiamata, MySQLLog all'interno del file applicazione upload.php esegue i passaggi necessari per aprire il link a MySQL, inserire la nuova riga, testare i risultati e chiudere il link. Aggiungo un altro passaggio per buona misura, che è registrare questi dati in un file di testo. Dovrei fare molto più logging per gli errori? Sì. Ma voglio mantenere questo codice leggero per permettergli di essere estremamente rapido. A volte questo codice sarà chiamato centinaia di volte al minuto e deve essere il più efficiente possibile. Negli aggiornamenti futuri, aggiungerò codice accessorio che elaborerà i fallimenti e invierà tali fallimenti a un amministratore per il monitoraggio.
Concludendo
Quindi, in pochi passaggi abbastanza semplici, siamo stati in grado di attraversare la prima fase della costruzione di un sistema di archiviazione email robusto che conserva il duplicato dell'email in S3 e collega i dati incrociati in una tabella MySQL. Questo ci darà una base per il resto del progetto che sarà affrontato in diversi post futuri.
In future revisioni di questo progetto mi aspetto di:
Memorizzare tutti gli eventi di log dell'email originale
Inviare errori di memorizzazione a un amministratore quando si verifica un fallimento di upload o di log
Minimizzare la complessità del collettore.
Aggiungere un'interfaccia utente per visualizzare tutti i dati
Supportare la possibilità di reinviare l'email
Nel frattempo, spero che questo progetto sia stato interessante e utile per te; buon invio.
Quindi, in pochi passaggi abbastanza semplici, siamo stati in grado di attraversare la prima fase della costruzione di un sistema di archiviazione email robusto che conserva il duplicato dell'email in S3 e collega i dati incrociati in una tabella MySQL. Questo ci darà una base per il resto del progetto che sarà affrontato in diversi post futuri.
In future revisioni di questo progetto mi aspetto di:
Memorizzare tutti gli eventi di log dell'email originale
Inviare errori di memorizzazione a un amministratore quando si verifica un fallimento di upload o di log
Minimizzare la complessità del collettore.
Aggiungere un'interfaccia utente per visualizzare tutti i dati
Supportare la possibilità di reinviare l'email
Nel frattempo, spero che questo progetto sia stato interessante e utile per te; buon invio.
Quindi, in pochi passaggi abbastanza semplici, siamo stati in grado di attraversare la prima fase della costruzione di un sistema di archiviazione email robusto che conserva il duplicato dell'email in S3 e collega i dati incrociati in una tabella MySQL. Questo ci darà una base per il resto del progetto che sarà affrontato in diversi post futuri.
In future revisioni di questo progetto mi aspetto di:
Memorizzare tutti gli eventi di log dell'email originale
Inviare errori di memorizzazione a un amministratore quando si verifica un fallimento di upload o di log
Minimizzare la complessità del collettore.
Aggiungere un'interfaccia utente per visualizzare tutti i dati
Supportare la possibilità di reinviare l'email
Nel frattempo, spero che questo progetto sia stato interessante e utile per te; buon invio.



