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 Simple Store Service) e dati accessori in una tabella MySQL per un facile 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 Duplicato dell'Email
In SparkPost il modo migliore per archiviare un'email è creare una copia identica dell'email progettata specificamente per scopi di archiviazione. Questo viene fatto utilizzando la funzionalità di Archive di SparkPost. La funzionalità di Archive di SparkPost offre al mittente la possibilità di inviare un duplicato dell'email a uno o più indirizzi email. Questo duplicato utilizza gli stessi link di tracciamento e di apertura dell'originale. La documentazione di SparkPost definisce la funzionalità di Archive nel seguente modo:
I destinatari nella lista dell'archivio riceveranno una replica esatta del messaggio inviato all'indirizzo RCPT TO. In particolare, i link codificati destinati al destinatario RCPT TO saranno identici nei messaggi di archivio.
L'unica differenza tra questa copia di archivio e l'email originale inviata a 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 sulla creazione di copie duplicate (o di archivio) di un'email. Gli header campione X-MSYS-API per questo progetto sono mostrati più avanti in questo blog.
Esiste una avvertenza per questo approccio; mentre tutte le informazioni sugli eventi nell'email originale sono legate insieme sia da un transmission_id che da un message_id, non vi sono informazioni nell'evento di inbound relay (il meccanismo per ottenere e diffondere l'email di archivio) per l'email duplicata che si ricollega a uno di questi due id e quindi alle 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 SparkPost dall'email originale e da quella 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>>">
Quindi ho creato un codice univoco e 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">
Dopo ho verificato di aver aggiunto il $UID al blocco meta_data dell'header X-MSYS-API. Questo passaggio assicura che l'UID sia inserito in ciascun output di evento per l'email originale:
Ora abbiamo un modo per collegare tutti i dati dall'email originale al corpo dell'email di archivio.
Ottenere la versione Archive
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 a livello elevato 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 definita 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:
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 di header e lo scorre per ottenere i dati che ero interessato a memorizzare:
Ora che ho i dati, sono pronto per memorizzare il corpo in S3.
Memorizzare l'email duplicata in S3
Mi dispiace deluderti, ma non fornirò un tutorial passo-passo su come creare un bucket S3 per archiviare l'email, né descriverò come creare la chiave di accesso necessaria per caricare contenuti sul tuo bucket; ci sono tutorial migliori su questo argomento di quanti potrei mai scriverne. Ecco un paio di articoli che possono 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/
Ciò che farò è evidenziare alcune delle impostazioni che ho scelto che riguardano un progetto come questo.
Controllo Accessi. Non solo è necessario impostare la sicurezza per il bucket, ma è necessario impostare le autorizzazioni per gli elementi stessi. Nel mio progetto, uso una politica molto aperta di public-read perché i dati di esempio non sono personali e volevo avere facile accesso ai dati. Probabilmente vorrai una serie di politiche ACL molto più rigide. Ecco un bell'articolo sulle impostazioni ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Archiviazione dell'Archivio. In S3 esiste qualcosa chiamato Lifecycle Management. Questo ti permette di spostare i dati da un tipo di classe di archiviazione S3 a un'altra. Le diverse classi di archiviazione rappresentano il livello di accesso richiesto ai dati archiviati con costi inferiori associati allo storage che si accede meno. Una buona descrizione delle diverse classi e del passaggio attraverso di esse si trova 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 a Glacier è molto più economico rispetto all'archivio S3 standard e mi farà risparmiare sui costi di archiviazione.
Una volta creato il bucket S3 e impostate le mie impostazioni, S3 è pronto per caricare l'email conforme a rfc822 che ho ottenuto dal flusso di dati SparkPost Relay Webhook. Ma prima di caricare il payload dell'email rfc822 su S3, devo creare un nome file univoco che userò per archiviare quell'email.
Per il nome file univoco, cercherò nel corpo dell'email l'id nascosto che l'applicazione mittente ha inserito nell'email e userò 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:
* stiamo assumendo che $inputField detenga il valore “ArchiveCode” e sia stato trovato nel mio file config.php.
Con l'UID, possiamo quindi creare il nome file che sarà 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 poco codice per caricare il file.
Il mio ultimo passaggio è registrare questa voce nella tabella MYSQL.
Memorizzare i Meta Data in MySQL
Abbiamo raccolto tutti i dati necessari in un passaggio precedente, quindi il passaggio di archiviazione è semplice. In questa prima fase, ho scelto di costruire una tabella con i seguenti campi:
Un campo di inserimento automatico per data/ora
L'indirizzo email di destinazione (RCPT_TO)
Il timestamp dall'intestazione DATA dell'email
L'intestazione SUBJECT
L'intestazione dell'indirizzo email FROM
La directory utilizzata nel bucket S3
Il nome del file S3 per l'email archiviata
La funzione chiamata MySQLLog all'interno del file di applicazione upload.php esegue i passaggi necessari per aprire il collegamento a MySQL, inserire la nuova riga, testare i risultati e chiudere il collegamento. Aggiungo un altro passaggio per buona misura ed è quello di registrare questi dati in un file di testo. Devo eseguire molti più log per gli errori? Sì. Ma voglio mantenere questo codice leggero per permettergli di funzionare estremamente veloce. A volte, questo codice verrà chiamato centinaia di volte al minuto e deve essere il più efficiente possibile. In futuri aggiornamenti, aggiungerò codice ausiliario 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 delle email in S3 e incrocia i dati in una tabella MySQL. Questo ci darà una base per il resto del progetto che verrà 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 di caricamento o di log
Minimizzare la complessità del collettore.
Aggiungere un'interfaccia utente per visualizzare tutti i dati
Supportare la possibilità di rinviare l'email
Nel frattempo, spero che questo progetto sia stato interessante e utile per te; buon invio.



