Costruire un sistema di archiviazione delle email: Memorizzare il contenuto delle email
Uccello
4 mar 2019
1 min read

Punti Chiave
Scopo: Questo post delinea la prima fase della costruzione di un sistema di archiviazione delle email utilizzando SparkPost, Amazon S3 e MySQL. Spiega come duplicare, catturare e memorizzare le email per un accesso e una conformità a lungo termine.
Idea principale: Il sistema memorizza automaticamente il corpo dell'email grezzo (formato rfc822) in S3 e registra i metadati (oggetto, mittente, timestamp, ecc.) in MySQL per una ricerca e un recupero rapidi.
Elementi essenziali trattati:
Creazione di duplicati per archiviazione: Utilizza la funzione di archivio di SparkPost per inviare copie identiche delle email in uscita a un indirizzo di archiviazione designato, garantendo che il corpo e i link di tracciamento rimangano identici.
Collegamento dei dati tramite UID: Integra un identificatore unico (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 un webhook in SparkPost per ricevere i payload JSON delle email archiviate tramite un'applicazione di raccolta.
Memorizzazione delle email in S3: Carica il corpo rfc822 analizzato in un bucket S3, utilizzando regole di ciclo di vita (ad esempio, passaggio a Glacier dopo un anno) per ridurre i costi di archiviazione.
Registrazione dei metadati in MySQL: Salva i campi chiave come RCPT_TO, FROM, SUBJECT e nome file S3 per l'indicizzazione della ricerca e il recupero futuro.
Considerazioni sulle prestazioni: L'efficienza del codice e la registrazione minima garantiscono che il raccoglitore possa gestire centinaia di richieste al minuto con una latenza minima.
Visione d'insieme: Questa base supporta futuri miglioramenti—come l'archiviazione degli eventi di log, gli avvisi di errore e la visualizzazione dell'interfaccia utente—gettando le basi per una soluzione di archiviazione delle email scalabile e verificabile.
Punti salienti del Q&A
Qual è l'obiettivo di questo progetto?
Creare un sistema automatizzato di archiviazione delle email che memorizza i corpi dei messaggi in Amazon S3 mantenendo nel contempo i metadati ricercabili in un database MySQL.
Perché utilizzare la funzione Archivio di SparkPost?
Ti consente di generare duplicati esatti delle email in uscita, preservando la loro 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 preciso riferimento incrociato tra le copie originali e archiviate.
Perché utilizzare S3 per lo storage?
S3 offre opzioni di archiviazione scalabile e gestione del ciclo di vita (come Glacier), rendendolo conveniente per la retention di email a lungo termine.
Cosa memorizza il database MySQL?
Memorizza campi di metadati ricercabili—come l'oggetto, il mittente, le data/ora e il nome file S3—per consentire query e recupero efficienti.
Quali sono i prossimi passi nello sviluppo?
Aggiungere il tracciamento degli eventi di log, la segnalazione automatica degli errori, un raccoglitore semplificato e un'interfaccia utente per visualizzare o reinviare le email archiviate.
In questo blog, descriverò il processo che ho seguito per memorizzare il corpo dell'email su S3 (Amazon Simple Store Service) e i dati accessori in una tabella MySQL per una facile consultazione incrociata. Alla fine, questo è il punto di partenza per la base di codice che includerà un'applicazione che consentirà una facile ricerca delle email archiviate e poi la visualizzazione di quelle email insieme ai dati degli eventi (log). Il codice per questo progetto può essere trovato nel seguente repository GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Sebbene utilizzerò S3 e MySQL in questo progetto, non sono di certo le uniche tecnologie che possono essere utilizzate per costruire una piattaforma di archiviazione, ma vista la loro ubiquità, pensavo fossero una buona scelta per questo progetto. In un sistema a grande scala e ad alto volume utilizzerei un database con prestazioni superiori rispetto a MySQL, ma per questo progetto esemplare, MySQL è perfetto. Per le organizzazioni che considerano PostgreSQL come scelta del database di archiviazione, implementare procedure di backup e ripristino appropriate è essenziale per mantenere l'integrità dei dati nei sistemi di produzione.
Ho descritto di seguito i passaggi che ho seguito in questa prima fase del progetto:
Creare l'email duplicata per l'archiviazione
Utilizzare le funzionalità di Archiviazione e Inbound Relay di SparkPost per inviare una copia dell'email originale a SparkPost per l'elaborazione in una struttura JSON, quindi inviata a un collector webhook (applicazione)
Smontare la struttura JSON per ottenere i componenti necessari
Inviare il corpo dell'email a S3 per la memorizzazione
Eseguire una registrazione in MySQL per ogni email per la consultazione incrociata
In questo blog, descriverò il processo che ho seguito per memorizzare il corpo dell'email su S3 (Amazon Simple Store Service) e i dati accessori in una tabella MySQL per una facile consultazione incrociata. Alla fine, questo è il punto di partenza per la base di codice che includerà un'applicazione che consentirà una facile ricerca delle email archiviate e poi la visualizzazione di quelle email insieme ai dati degli eventi (log). Il codice per questo progetto può essere trovato nel seguente repository GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Sebbene utilizzerò S3 e MySQL in questo progetto, non sono di certo le uniche tecnologie che possono essere utilizzate per costruire una piattaforma di archiviazione, ma vista la loro ubiquità, pensavo fossero una buona scelta per questo progetto. In un sistema a grande scala e ad alto volume utilizzerei un database con prestazioni superiori rispetto a MySQL, ma per questo progetto esemplare, MySQL è perfetto. Per le organizzazioni che considerano PostgreSQL come scelta del database di archiviazione, implementare procedure di backup e ripristino appropriate è essenziale per mantenere l'integrità dei dati nei sistemi di produzione.
Ho descritto di seguito i passaggi che ho seguito in questa prima fase del progetto:
Creare l'email duplicata per l'archiviazione
Utilizzare le funzionalità di Archiviazione e Inbound Relay di SparkPost per inviare una copia dell'email originale a SparkPost per l'elaborazione in una struttura JSON, quindi inviata a un collector webhook (applicazione)
Smontare la struttura JSON per ottenere i componenti necessari
Inviare il corpo dell'email a S3 per la memorizzazione
Eseguire una registrazione in MySQL per ogni email per la consultazione incrociata
In questo blog, descriverò il processo che ho seguito per memorizzare il corpo dell'email su S3 (Amazon Simple Store Service) e i dati accessori in una tabella MySQL per una facile consultazione incrociata. Alla fine, questo è il punto di partenza per la base di codice che includerà un'applicazione che consentirà una facile ricerca delle email archiviate e poi la visualizzazione di quelle email insieme ai dati degli eventi (log). Il codice per questo progetto può essere trovato nel seguente repository GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Sebbene utilizzerò S3 e MySQL in questo progetto, non sono di certo le uniche tecnologie che possono essere utilizzate per costruire una piattaforma di archiviazione, ma vista la loro ubiquità, pensavo fossero una buona scelta per questo progetto. In un sistema a grande scala e ad alto volume utilizzerei un database con prestazioni superiori rispetto a MySQL, ma per questo progetto esemplare, MySQL è perfetto. Per le organizzazioni che considerano PostgreSQL come scelta del database di archiviazione, implementare procedure di backup e ripristino appropriate è essenziale per mantenere l'integrità dei dati nei sistemi di produzione.
Ho descritto di seguito i passaggi che ho seguito in questa prima fase del progetto:
Creare l'email duplicata per l'archiviazione
Utilizzare le funzionalità di Archiviazione e Inbound Relay di SparkPost per inviare una copia dell'email originale a SparkPost per l'elaborazione in una struttura JSON, quindi inviata a un collector webhook (applicazione)
Smontare la struttura JSON per ottenere i componenti necessari
Inviare il corpo dell'email a S3 per la memorizzazione
Eseguire una registrazione in MySQL per ogni email per la consultazione incrociata
Creare una copia dell'email
In SparkPost il modo migliore per archiviare un'email è creare una copia identica dell'email specificamente progettata per scopi archivi. Questo viene fatto utilizzando la funzione Archive di SparkPost. La funzione Archive di SparkPost dà al mittente la possibilità di inviare un duplicato dell'email a uno o più indirizzi email. Questo duplicato utilizza gli stessi collegamenti di tracciamento e apertura dell'originale. La documentazione di SparkPost definisce la funzione Archive nel seguente modo:
I destinatari nella lista di archiviazione riceveranno una replica esatta del messaggio che è stato inviato all'indirizzo RCPT TO. In particolare, eventuali collegamenti codificati destinati al destinatario RCPT TO saranno identici nei messaggi di archiviazione.
L'unica differenza tra questa copia di archiviazione e l'email originale RCPT TO è che alcuni degli header saranno diversi poiché l'indirizzo di destinazione per l'email di archiviazione è diverso, ma il corpo dell'email sarà una replica esatta!
Se desideri una spiegazione più approfondita, ecco un link alla documentazione di SparkPost su come creare copie duplicate (o di archiviazione) di un'email. Esempi di header X-MSYS-API per questo progetto sono mostrati più avanti in questo blog.
Esiste una limitazione a questo approccio; mentre tutte le informazioni sugli eventi nell'email originale sono collegate da sia un transmission_id che un message_id, non ci sono informazioni nell'evento relay in entrata (il meccanismo per ottenere e divulgare l'email di archiviazione) per l'email duplicata che riporti a uno di quei due id e quindi le informazioni per l'email originale. Questo significa che dobbiamo inserire dati nel corpo dell'email e nell'header dell'email originale come un modo per collegare tutti i dati di SparkPost dall'email originale e dall'email di archiviazione.
Per creare il codice che viene inserito nel corpo dell'email, ho utilizzato il seguente processo nell'applicazione di creazione delle email.
Da qualche parte nel corpo dell'email, ho inserito la seguente voce di input:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Poi ho creato un codice unico 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, ho fatto in modo di aggiungere il $UID al blocco meta_data dell'header X-MSYS-API. Questo passaggio assicura che il UID sia incorporato in ogni 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 archiviazione.
In SparkPost il modo migliore per archiviare un'email è creare una copia identica dell'email specificamente progettata per scopi archivi. Questo viene fatto utilizzando la funzione Archive di SparkPost. La funzione Archive di SparkPost dà al mittente la possibilità di inviare un duplicato dell'email a uno o più indirizzi email. Questo duplicato utilizza gli stessi collegamenti di tracciamento e apertura dell'originale. La documentazione di SparkPost definisce la funzione Archive nel seguente modo:
I destinatari nella lista di archiviazione riceveranno una replica esatta del messaggio che è stato inviato all'indirizzo RCPT TO. In particolare, eventuali collegamenti codificati destinati al destinatario RCPT TO saranno identici nei messaggi di archiviazione.
L'unica differenza tra questa copia di archiviazione e l'email originale RCPT TO è che alcuni degli header saranno diversi poiché l'indirizzo di destinazione per l'email di archiviazione è diverso, ma il corpo dell'email sarà una replica esatta!
Se desideri una spiegazione più approfondita, ecco un link alla documentazione di SparkPost su come creare copie duplicate (o di archiviazione) di un'email. Esempi di header X-MSYS-API per questo progetto sono mostrati più avanti in questo blog.
Esiste una limitazione a questo approccio; mentre tutte le informazioni sugli eventi nell'email originale sono collegate da sia un transmission_id che un message_id, non ci sono informazioni nell'evento relay in entrata (il meccanismo per ottenere e divulgare l'email di archiviazione) per l'email duplicata che riporti a uno di quei due id e quindi le informazioni per l'email originale. Questo significa che dobbiamo inserire dati nel corpo dell'email e nell'header dell'email originale come un modo per collegare tutti i dati di SparkPost dall'email originale e dall'email di archiviazione.
Per creare il codice che viene inserito nel corpo dell'email, ho utilizzato il seguente processo nell'applicazione di creazione delle email.
Da qualche parte nel corpo dell'email, ho inserito la seguente voce di input:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Poi ho creato un codice unico 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, ho fatto in modo di aggiungere il $UID al blocco meta_data dell'header X-MSYS-API. Questo passaggio assicura che il UID sia incorporato in ogni 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 archiviazione.
In SparkPost il modo migliore per archiviare un'email è creare una copia identica dell'email specificamente progettata per scopi archivi. Questo viene fatto utilizzando la funzione Archive di SparkPost. La funzione Archive di SparkPost dà al mittente la possibilità di inviare un duplicato dell'email a uno o più indirizzi email. Questo duplicato utilizza gli stessi collegamenti di tracciamento e apertura dell'originale. La documentazione di SparkPost definisce la funzione Archive nel seguente modo:
I destinatari nella lista di archiviazione riceveranno una replica esatta del messaggio che è stato inviato all'indirizzo RCPT TO. In particolare, eventuali collegamenti codificati destinati al destinatario RCPT TO saranno identici nei messaggi di archiviazione.
L'unica differenza tra questa copia di archiviazione e l'email originale RCPT TO è che alcuni degli header saranno diversi poiché l'indirizzo di destinazione per l'email di archiviazione è diverso, ma il corpo dell'email sarà una replica esatta!
Se desideri una spiegazione più approfondita, ecco un link alla documentazione di SparkPost su come creare copie duplicate (o di archiviazione) di un'email. Esempi di header X-MSYS-API per questo progetto sono mostrati più avanti in questo blog.
Esiste una limitazione a questo approccio; mentre tutte le informazioni sugli eventi nell'email originale sono collegate da sia un transmission_id che un message_id, non ci sono informazioni nell'evento relay in entrata (il meccanismo per ottenere e divulgare l'email di archiviazione) per l'email duplicata che riporti a uno di quei due id e quindi le informazioni per l'email originale. Questo significa che dobbiamo inserire dati nel corpo dell'email e nell'header dell'email originale come un modo per collegare tutti i dati di SparkPost dall'email originale e dall'email di archiviazione.
Per creare il codice che viene inserito nel corpo dell'email, ho utilizzato il seguente processo nell'applicazione di creazione delle email.
Da qualche parte nel corpo dell'email, ho inserito la seguente voce di input:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Poi ho creato un codice unico 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, ho fatto in modo di aggiungere il $UID al blocco meta_data dell'header X-MSYS-API. Questo passaggio assicura che il UID sia incorporato in ogni 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 archiviazione.
Ottenere la versione dell'Archivio
Per ottenere una copia di un'email per l'archiviazione, è necessario seguire i seguenti passaggi:
Creare un sottodominio a cui inviare tutte le email di archivio (duplicate)
Impostare i record DNS appropriati affinché tutte le email inviate a quel sottodominio vadano su SparkPost
Creare un dominio in entrata in SparkPost
Creare un webhook in entrata in SparkPost
Creare un'applicazione (collettore) per ricevere il flusso di dati del webhook di SparkPost
I seguenti due link possono essere utilizzati per guidarti attraverso questo processo:
Documentazione tecnica di SparkPost: Abilitare il Relay di Email in Entrata & Webhook di Relay
Inoltre, il blog che ho scritto l'anno scorso, Archiviazione delle Email: Una Guida Pratica per il Tracciamento delle Email Inviate ti guiderà attraverso la creazione del relay in entrata all'interno di SparkPost
* Nota: da ottobre 2018, la funzionalità di archiviazione funziona solo quando si inviano email utilizzando una connessione SMTP a SparkPost, l'API RESTful non supporta questa funzionalità. Probabilmente non è un problema perché la maggior parte delle email che necessitano di questo livello di controllo di audit tendono a essere email personalizzate che sono completamente costruite da un'applicazione backend prima che la consegna dell'email sia necessaria.
Per ottenere una copia di un'email per l'archiviazione, è necessario seguire i seguenti passaggi:
Creare un sottodominio a cui inviare tutte le email di archivio (duplicate)
Impostare i record DNS appropriati affinché tutte le email inviate a quel sottodominio vadano su SparkPost
Creare un dominio in entrata in SparkPost
Creare un webhook in entrata in SparkPost
Creare un'applicazione (collettore) per ricevere il flusso di dati del webhook di SparkPost
I seguenti due link possono essere utilizzati per guidarti attraverso questo processo:
Documentazione tecnica di SparkPost: Abilitare il Relay di Email in Entrata & Webhook di Relay
Inoltre, il blog che ho scritto l'anno scorso, Archiviazione delle Email: Una Guida Pratica per il Tracciamento delle Email Inviate ti guiderà attraverso la creazione del relay in entrata all'interno di SparkPost
* Nota: da ottobre 2018, la funzionalità di archiviazione funziona solo quando si inviano email utilizzando una connessione SMTP a SparkPost, l'API RESTful non supporta questa funzionalità. Probabilmente non è un problema perché la maggior parte delle email che necessitano di questo livello di controllo di audit tendono a essere email personalizzate che sono completamente costruite da un'applicazione backend prima che la consegna dell'email sia necessaria.
Per ottenere una copia di un'email per l'archiviazione, è necessario seguire i seguenti passaggi:
Creare un sottodominio a cui inviare tutte le email di archivio (duplicate)
Impostare i record DNS appropriati affinché tutte le email inviate a quel sottodominio vadano su SparkPost
Creare un dominio in entrata in SparkPost
Creare un webhook in entrata in SparkPost
Creare un'applicazione (collettore) per ricevere il flusso di dati del webhook di SparkPost
I seguenti due link possono essere utilizzati per guidarti attraverso questo processo:
Documentazione tecnica di SparkPost: Abilitare il Relay di Email in Entrata & Webhook di Relay
Inoltre, il blog che ho scritto l'anno scorso, Archiviazione delle Email: Una Guida Pratica per il Tracciamento delle Email Inviate ti guiderà attraverso la creazione del relay in entrata all'interno di SparkPost
* Nota: da ottobre 2018, la funzionalità di archiviazione funziona solo quando si inviano email utilizzando una connessione SMTP a SparkPost, l'API RESTful non supporta questa funzionalità. Probabilmente non è un problema perché la maggior parte delle email che necessitano di questo livello di controllo di audit tendono a essere email personalizzate che sono completamente costruite da un'applicazione backend prima che la consegna dell'email sia necessaria.
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 delle 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 Relay_Webhook di SparkPost conterrà l'informazione di una email duplicata alla volta, quindi scomporre la struttura JSON nei componenti mirati per questo progetto è piuttosto semplice. Nel mio codice PHP, ottenere l'email formattata in rfc822 è stato facile quanto 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 intestazione. Così ho scritto una piccola funzione che accettava l'array di intestazioni e lo scorreva per ottenere i dati che ero interessato a 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 delle 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 Relay_Webhook di SparkPost conterrà l'informazione di una email duplicata alla volta, quindi scomporre la struttura JSON nei componenti mirati per questo progetto è piuttosto semplice. Nel mio codice PHP, ottenere l'email formattata in rfc822 è stato facile quanto 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 intestazione. Così ho scritto una piccola funzione che accettava l'array di intestazioni e lo scorreva per ottenere i dati che ero interessato a 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 delle 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 Relay_Webhook di SparkPost conterrà l'informazione di una email duplicata alla volta, quindi scomporre la struttura JSON nei componenti mirati per questo progetto è piuttosto semplice. Nel mio codice PHP, ottenere l'email formattata in rfc822 è stato facile quanto 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 intestazione. Così ho scritto una piccola funzione che accettava l'array di intestazioni e lo scorreva per ottenere i dati che ero interessato a 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.
Memorizzare l'email duplicata in S3
Mi dispiace deluderti, ma non darò un tutorial passo passo su come creare un bucket S3 per memorizzare l'email né descriverò come creare la chiave di accesso necessaria alla tua applicazione per caricare contenuti nel tuo bucket; ci sono tutorial migliori su questo argomento di quanto io possa mai scrivere. Ecco un paio di articoli che potrebbero aiutarti:
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ò è evidenziare alcune delle impostazioni che ho scelto e che riguardano un progetto come questo.
Controllo degli Accessi. Non devi solo impostare la sicurezza per il bucket, ma devi anche impostare i permessi per gli oggetti stessi. Nel mio progetto, utilizzo una politica molto aperta di lettura pubblica perché i dati campione non sono personali e volevo un accesso facile ai dati. Probabilmente vorrai un set di politiche ACL molto più rigido. Ecco un bel articolo sulle impostazioni ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Archiviare l'Archivio. In S3 c'è qualcosa chiamato Gestione del Ciclo di Vita. Questo ti consente di spostare i dati da un tipo di classe di archiviazione S3 a un'altra. Le diverse classi di archiviazione rappresentano l'ammontare di accesso di cui hai bisogno ai dati memorizzati, con costi inferiori associati all'archiviazione a cui accedi meno. Un buon articolo sulle diverse classi e sul loro passaggio può essere trovato in una guida AWS chiamata, Transizione degli Oggetti. Nel mio caso, ho scelto di creare un ciclo di vita che spostasse ogni oggetto da Standard a Glacier dopo un anno. L'accesso a Glacier è molto più economico rispetto all'archiviazione standard S3 e mi farà risparmiare denaro sui costi di archiviazione.
Una volta creato il bucket S3 e impostate le mie configurazioni, S3 è pronto per caricare l'email conforme a rfc822 che ho ottenuto dal flusso di dati del Webhook SparkPost Relay. Ma prima di caricare il payload dell'email rfc822 in S3, devo creare un nome file univoco che utilizzerò per memorizzare quell'email.
Per il nome file univoco, cercherò nel corpo dell'email l'id nascosto che l'applicazione di invio 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); } } }
* assumiamo che $inputField contenga il valore "ArchiveCode" e sia stato trovato nel mio file config.php.
Con il UID, possiamo poi creare il nome file che verrà utilizzato in S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Ora posso 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 passaggio è registrare questa voce nella tabella MYSQL.
Mi dispiace deluderti, ma non darò un tutorial passo passo su come creare un bucket S3 per memorizzare l'email né descriverò come creare la chiave di accesso necessaria alla tua applicazione per caricare contenuti nel tuo bucket; ci sono tutorial migliori su questo argomento di quanto io possa mai scrivere. Ecco un paio di articoli che potrebbero aiutarti:
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ò è evidenziare alcune delle impostazioni che ho scelto e che riguardano un progetto come questo.
Controllo degli Accessi. Non devi solo impostare la sicurezza per il bucket, ma devi anche impostare i permessi per gli oggetti stessi. Nel mio progetto, utilizzo una politica molto aperta di lettura pubblica perché i dati campione non sono personali e volevo un accesso facile ai dati. Probabilmente vorrai un set di politiche ACL molto più rigido. Ecco un bel articolo sulle impostazioni ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Archiviare l'Archivio. In S3 c'è qualcosa chiamato Gestione del Ciclo di Vita. Questo ti consente di spostare i dati da un tipo di classe di archiviazione S3 a un'altra. Le diverse classi di archiviazione rappresentano l'ammontare di accesso di cui hai bisogno ai dati memorizzati, con costi inferiori associati all'archiviazione a cui accedi meno. Un buon articolo sulle diverse classi e sul loro passaggio può essere trovato in una guida AWS chiamata, Transizione degli Oggetti. Nel mio caso, ho scelto di creare un ciclo di vita che spostasse ogni oggetto da Standard a Glacier dopo un anno. L'accesso a Glacier è molto più economico rispetto all'archiviazione standard S3 e mi farà risparmiare denaro sui costi di archiviazione.
Una volta creato il bucket S3 e impostate le mie configurazioni, S3 è pronto per caricare l'email conforme a rfc822 che ho ottenuto dal flusso di dati del Webhook SparkPost Relay. Ma prima di caricare il payload dell'email rfc822 in S3, devo creare un nome file univoco che utilizzerò per memorizzare quell'email.
Per il nome file univoco, cercherò nel corpo dell'email l'id nascosto che l'applicazione di invio 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); } } }
* assumiamo che $inputField contenga il valore "ArchiveCode" e sia stato trovato nel mio file config.php.
Con il UID, possiamo poi creare il nome file che verrà utilizzato in S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Ora posso 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 passaggio è registrare questa voce nella tabella MYSQL.
Mi dispiace deluderti, ma non darò un tutorial passo passo su come creare un bucket S3 per memorizzare l'email né descriverò come creare la chiave di accesso necessaria alla tua applicazione per caricare contenuti nel tuo bucket; ci sono tutorial migliori su questo argomento di quanto io possa mai scrivere. Ecco un paio di articoli che potrebbero aiutarti:
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ò è evidenziare alcune delle impostazioni che ho scelto e che riguardano un progetto come questo.
Controllo degli Accessi. Non devi solo impostare la sicurezza per il bucket, ma devi anche impostare i permessi per gli oggetti stessi. Nel mio progetto, utilizzo una politica molto aperta di lettura pubblica perché i dati campione non sono personali e volevo un accesso facile ai dati. Probabilmente vorrai un set di politiche ACL molto più rigido. Ecco un bel articolo sulle impostazioni ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Archiviare l'Archivio. In S3 c'è qualcosa chiamato Gestione del Ciclo di Vita. Questo ti consente di spostare i dati da un tipo di classe di archiviazione S3 a un'altra. Le diverse classi di archiviazione rappresentano l'ammontare di accesso di cui hai bisogno ai dati memorizzati, con costi inferiori associati all'archiviazione a cui accedi meno. Un buon articolo sulle diverse classi e sul loro passaggio può essere trovato in una guida AWS chiamata, Transizione degli Oggetti. Nel mio caso, ho scelto di creare un ciclo di vita che spostasse ogni oggetto da Standard a Glacier dopo un anno. L'accesso a Glacier è molto più economico rispetto all'archiviazione standard S3 e mi farà risparmiare denaro sui costi di archiviazione.
Una volta creato il bucket S3 e impostate le mie configurazioni, S3 è pronto per caricare l'email conforme a rfc822 che ho ottenuto dal flusso di dati del Webhook SparkPost Relay. Ma prima di caricare il payload dell'email rfc822 in S3, devo creare un nome file univoco che utilizzerò per memorizzare quell'email.
Per il nome file univoco, cercherò nel corpo dell'email l'id nascosto che l'applicazione di invio 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); } } }
* assumiamo che $inputField contenga il valore "ArchiveCode" e sia stato trovato nel mio file config.php.
Con il UID, possiamo poi creare il nome file che verrà utilizzato in S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Ora posso 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 passaggio è registrare questa voce nella tabella MYSQL.
Memorizzare i Meta Dati in MySQL
Abbiamo ottenuto tutti i dati necessari in un passaggio precedente, quindi il passaggio di archiviazione è facile. In questa prima fase ho scelto di costruire una tabella con i seguenti campi:
Campi Metadati MySQL
Campo | Scopo |
Data/ora (auto) | Timestamp quando l'entry è stata registrata |
Indirizzo RCPT_TO | Indirizzo email target per il messaggio archiviato |
Timestamp intestazione DATE | Ora di invio dell'email originale |
Intestazione SUBJECT | Linea dell'oggetto per indicizzazione e ricerca |
Intestazione FROM | Identificatore del mittente per ricerca |
Directory S3 | Percorso della directory all'interno del bucket S3 |
Nome file S3 | File .eml unico archiviato in S3 |
La funzione chiamata, MySQLLog all'interno del file dell'applicazione upload.php segue i passaggi necessari per aprire il collegamento a MySQL, iniettare la nuova riga, testare i risultati e chiudere il collegamento. Aggiungo un altro passaggio per sicurezza, ovvero registrare questi dati in un file di testo. Dovrei fare molte più registrazioni per gli errori? Sì. Ma voglio mantenere questo codice leggero per consentirgli di funzionare estremamente veloce. A volte questo codice verrà 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 ottenuto tutti i dati necessari in un passaggio precedente, quindi il passaggio di archiviazione è facile. In questa prima fase ho scelto di costruire una tabella con i seguenti campi:
Campi Metadati MySQL
Campo | Scopo |
Data/ora (auto) | Timestamp quando l'entry è stata registrata |
Indirizzo RCPT_TO | Indirizzo email target per il messaggio archiviato |
Timestamp intestazione DATE | Ora di invio dell'email originale |
Intestazione SUBJECT | Linea dell'oggetto per indicizzazione e ricerca |
Intestazione FROM | Identificatore del mittente per ricerca |
Directory S3 | Percorso della directory all'interno del bucket S3 |
Nome file S3 | File .eml unico archiviato in S3 |
La funzione chiamata, MySQLLog all'interno del file dell'applicazione upload.php segue i passaggi necessari per aprire il collegamento a MySQL, iniettare la nuova riga, testare i risultati e chiudere il collegamento. Aggiungo un altro passaggio per sicurezza, ovvero registrare questi dati in un file di testo. Dovrei fare molte più registrazioni per gli errori? Sì. Ma voglio mantenere questo codice leggero per consentirgli di funzionare estremamente veloce. A volte questo codice verrà 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 ottenuto tutti i dati necessari in un passaggio precedente, quindi il passaggio di archiviazione è facile. In questa prima fase ho scelto di costruire una tabella con i seguenti campi:
Campi Metadati MySQL
Campo | Scopo |
Data/ora (auto) | Timestamp quando l'entry è stata registrata |
Indirizzo RCPT_TO | Indirizzo email target per il messaggio archiviato |
Timestamp intestazione DATE | Ora di invio dell'email originale |
Intestazione SUBJECT | Linea dell'oggetto per indicizzazione e ricerca |
Intestazione FROM | Identificatore del mittente per ricerca |
Directory S3 | Percorso della directory all'interno del bucket S3 |
Nome file S3 | File .eml unico archiviato in S3 |
La funzione chiamata, MySQLLog all'interno del file dell'applicazione upload.php segue i passaggi necessari per aprire il collegamento a MySQL, iniettare la nuova riga, testare i risultati e chiudere il collegamento. Aggiungo un altro passaggio per sicurezza, ovvero registrare questi dati in un file di testo. Dovrei fare molte più registrazioni per gli errori? Sì. Ma voglio mantenere questo codice leggero per consentirgli di funzionare estremamente veloce. A volte questo codice verrà 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.
Riassumendo
Quindi, in pochi passaggi abbastanza facili, siamo riusciti a percorrere la prima fase della costruzione di un robusto sistema di archiviazione delle email che trattiene i duplicati delle email in S3 e confronta i dati in una tabella MySQL. Questo ci fornirà una base per il resto del progetto che sarà affrontato in diversi post futuri.
In future revisioni di questo progetto mi aspetterei di:
Memorizzare tutti gli eventi di log dell'email originale
Inviare errori di archiviazione a un amministratore quando si verifica un errore nel caricamento o nel log
Minimizzare la complessità del raccoglitore.
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; buona spedizione.
Quindi, in pochi passaggi abbastanza facili, siamo riusciti a percorrere la prima fase della costruzione di un robusto sistema di archiviazione delle email che trattiene i duplicati delle email in S3 e confronta i dati in una tabella MySQL. Questo ci fornirà una base per il resto del progetto che sarà affrontato in diversi post futuri.
In future revisioni di questo progetto mi aspetterei di:
Memorizzare tutti gli eventi di log dell'email originale
Inviare errori di archiviazione a un amministratore quando si verifica un errore nel caricamento o nel log
Minimizzare la complessità del raccoglitore.
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; buona spedizione.
Quindi, in pochi passaggi abbastanza facili, siamo riusciti a percorrere la prima fase della costruzione di un robusto sistema di archiviazione delle email che trattiene i duplicati delle email in S3 e confronta i dati in una tabella MySQL. Questo ci fornirà una base per il resto del progetto che sarà affrontato in diversi post futuri.
In future revisioni di questo progetto mi aspetterei di:
Memorizzare tutti gli eventi di log dell'email originale
Inviare errori di archiviazione a un amministratore quando si verifica un errore nel caricamento o nel log
Minimizzare la complessità del raccoglitore.
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; buona spedizione.



