Construire un système d'archivage d'emails : Stocker le corps de l'email

Oiseau

4 mars 2019

Email

1 min read

Construire un système d'archivage d'emails : Stocker le corps de l'email

Points Clés

    • Objectif : Ce post décrit la première phase de la construction d'un système d'archivage d'e-mails utilisant SparkPost, Amazon S3, et MySQL. Il explique comment dupliquer, capturer et stocker les e-mails pour un accès à long terme et la conformité.

    • Idée principale : Le système stocke automatiquement le corps brut de l'e-mail (format rfc822) dans S3 et journalise les métadonnées (sujet, expéditeur, horodatage, etc.) dans MySQL pour une recherche rapide et une récupération.

    • Éléments essentiels couverts :

      1. Créer des doublons pour l'archivage : Utilisez la Archive feature de SparkPost pour envoyer des copies identiques des e-mails sortants à une adresse d'archive désignée, garantissant que le corps et les liens de suivi restent identiques.

      2. Association de données via UID : Intégrez un identifiant unique (UID) à la fois dans le corps de l'e-mail et dans les métadonnées X-MSYS-API pour lier les messages originaux et archivés.

      3. Traitement entrant : Configurez un domaine entrant et un webhook dans SparkPost pour recevoir les charges utiles JSON des e-mails archivés via un collecteur d'application.

      4. Stockage des e-mails dans S3 : Téléchargez le corps rfc822 analysé dans un bucket S3, en utilisant des règles de cycle de vie (par exemple, transition vers Glacier après un an) pour réduire les coûts de stockage.

      5. Journalisation des métadonnées dans MySQL : Enregistrez des champs clés tels que RCPT_TO, FROM, SUBJECT, et le nom de fichier S3 pour l'indexation des recherches et la récupération future.

      6. Considérations de performance : L'efficacité du code et la journalisation minimale garantissent que le collecteur peut gérer des centaines de demandes par minute avec une latence minimale.

    • Vue d'ensemble : Cette fondation soutient des améliorations futures—comme le stockage des journaux d'événements, les alertes d'échec et la visualisation de l'interface utilisateur—posant les bases d'une solution d'archivage d'e-mails évolutive et auditable.

Points forts des Q&A

  • Quel est l'objectif de ce projet ?

    Créer un système d'archivage d'emails automatisé qui stocke les corps des messages dans Amazon S3 tout en conservant des métadonnées consultables dans une base de données MySQL.

  • Pourquoi utiliser la fonctionnalité Archive de SparkPost ?

    Il vous permet de générer des copies exactes des e-mails sortants, en préservant leur structure et les données de suivi pour la conformité et la révision.

  • Comment chaque email archivé est-il lié à son message d'origine ?

    Un UID unique est intégré à la fois dans le corps de l'email et les métadonnées, permettant un référencement croisé précis entre les copies originales et archivées.

  • Pourquoi utiliser S3 pour le stockage ?

    S3 offre des options de stockage évolutives et de gestion du cycle de vie (comme Glacier), ce qui le rend rentable pour la conservation à long terme des e-mails.

  • Que stocke la base de données MySQL ?

    Il stocke des champs de métadonnées consultables - comme la ligne d'objet, l'expéditeur, les horodatages et le nom de fichier S3 - permettant une requête et une récupération efficaces.

  • Quels sont les prochaines étapes de développement ?

    Ajout du suivi des événements de journalisation, du rapport d'erreurs automatisé, d'un collecteur simplifié et d'une interface utilisateur pour visualiser ou renvoyer des e-mails archivés.

Dans ce blog, je vais décrire le processus que j'ai suivi pour stocker le corps de l'e-mail sur S3 (Service de Stockage Simple d'Amazon) et les données auxiliaires dans une table MySQL pour un référencement croisé facile. En fin de compte, c'est le point de départ pour la base de code qui inclura une application permettant une recherche facile des e-mails archivés, puis l'affichage de ces e-mails avec les données d'événements (journal). Le code de ce projet peut être trouvé dans le repository GitHub suivant : https://github.com/jeff-goldstein/PHPArchivePlatform.

Bien que je vais utiliser S3 et MySQL dans ce projet, ces technologies ne sont en aucun cas les seules qui peuvent être utilisées pour construire une plateforme d'archivage, mais étant donné leur omniprésence, je pensais qu'elles étaient un bon choix pour ce projet. Dans un système à grande échelle et à haut volume, j'utiliserais une base de données plus performante que MySQL, mais pour ce projet d'exemple, MySQL est parfait. Pour les organisations envisageant PostgreSQL comme choix de base de données d'archivage, la mise en œuvre de procédures de sauvegarde et de restauration adéquates est essentielle pour maintenir l'intégrité des données dans les systèmes de production.

J'ai détaillé ci-dessous les étapes que j'ai prises dans cette première phase du projet :

  1. Création de l'e-mail en double pour l'archivage

  2. Utiliser les fonctionnalités d'Archiving et Inbound Relay de SparkPost pour envoyer une copie de l'e-mail original à SparkPost pour traitement dans une structure JSON, puis envoyée à un collecteur de webhook (application)

  3. Démanteler la structure JSON pour obtenir les composants nécessaires

  4. Envoyer le corps de l'e-mail à S3 pour stockage

  5. Enregistrer une entrée dans MySQL pour chaque e-mail pour le référencement croisé

Dans ce blog, je vais décrire le processus que j'ai suivi pour stocker le corps de l'e-mail sur S3 (Service de Stockage Simple d'Amazon) et les données auxiliaires dans une table MySQL pour un référencement croisé facile. En fin de compte, c'est le point de départ pour la base de code qui inclura une application permettant une recherche facile des e-mails archivés, puis l'affichage de ces e-mails avec les données d'événements (journal). Le code de ce projet peut être trouvé dans le repository GitHub suivant : https://github.com/jeff-goldstein/PHPArchivePlatform.

Bien que je vais utiliser S3 et MySQL dans ce projet, ces technologies ne sont en aucun cas les seules qui peuvent être utilisées pour construire une plateforme d'archivage, mais étant donné leur omniprésence, je pensais qu'elles étaient un bon choix pour ce projet. Dans un système à grande échelle et à haut volume, j'utiliserais une base de données plus performante que MySQL, mais pour ce projet d'exemple, MySQL est parfait. Pour les organisations envisageant PostgreSQL comme choix de base de données d'archivage, la mise en œuvre de procédures de sauvegarde et de restauration adéquates est essentielle pour maintenir l'intégrité des données dans les systèmes de production.

J'ai détaillé ci-dessous les étapes que j'ai prises dans cette première phase du projet :

  1. Création de l'e-mail en double pour l'archivage

  2. Utiliser les fonctionnalités d'Archiving et Inbound Relay de SparkPost pour envoyer une copie de l'e-mail original à SparkPost pour traitement dans une structure JSON, puis envoyée à un collecteur de webhook (application)

  3. Démanteler la structure JSON pour obtenir les composants nécessaires

  4. Envoyer le corps de l'e-mail à S3 pour stockage

  5. Enregistrer une entrée dans MySQL pour chaque e-mail pour le référencement croisé

Dans ce blog, je vais décrire le processus que j'ai suivi pour stocker le corps de l'e-mail sur S3 (Service de Stockage Simple d'Amazon) et les données auxiliaires dans une table MySQL pour un référencement croisé facile. En fin de compte, c'est le point de départ pour la base de code qui inclura une application permettant une recherche facile des e-mails archivés, puis l'affichage de ces e-mails avec les données d'événements (journal). Le code de ce projet peut être trouvé dans le repository GitHub suivant : https://github.com/jeff-goldstein/PHPArchivePlatform.

Bien que je vais utiliser S3 et MySQL dans ce projet, ces technologies ne sont en aucun cas les seules qui peuvent être utilisées pour construire une plateforme d'archivage, mais étant donné leur omniprésence, je pensais qu'elles étaient un bon choix pour ce projet. Dans un système à grande échelle et à haut volume, j'utiliserais une base de données plus performante que MySQL, mais pour ce projet d'exemple, MySQL est parfait. Pour les organisations envisageant PostgreSQL comme choix de base de données d'archivage, la mise en œuvre de procédures de sauvegarde et de restauration adéquates est essentielle pour maintenir l'intégrité des données dans les systèmes de production.

J'ai détaillé ci-dessous les étapes que j'ai prises dans cette première phase du projet :

  1. Création de l'e-mail en double pour l'archivage

  2. Utiliser les fonctionnalités d'Archiving et Inbound Relay de SparkPost pour envoyer une copie de l'e-mail original à SparkPost pour traitement dans une structure JSON, puis envoyée à un collecteur de webhook (application)

  3. Démanteler la structure JSON pour obtenir les composants nécessaires

  4. Envoyer le corps de l'e-mail à S3 pour stockage

  5. Enregistrer une entrée dans MySQL pour chaque e-mail pour le référencement croisé

Créer un Duplicate de l'Email

Dans SparkPost, la meilleure façon d'archiver un e-mail est de créer une copie identique de l'e-mail spécialement conçue pour des fins d'archivage. Cela se fait en utilisant la fonctionnalité Archive de SparkPost. La fonctionnalité Archive de SparkPost donne au destinataire la possibilité d'envoyer un doublon de l'e-mail à une ou plusieurs adresses e-mail. Ce doublon utilise les mêmes liens de suivi et de consultation que l'original. La documentation de SparkPost définit la fonctionnalité Archive de la manière suivante :

Les destinataires de la liste d'archivage recevront une réplique exacte du message qui a été envoyé à l'adresse RCPT TO. En particulier, tous les liens encodés destinés au destinataire RCPT TO seront identiques dans les messages d'archive.

La seule différence entre cette copie d'archive et l'e-mail original RCPT TO est que certaines des en-têtes seront différentes puisque l'adresse cible pour l'e-mail d'archivage est différente, mais le corps de l'e-mail sera une réplique exacte !

Si vous souhaitez une explication plus approfondie, voici un lien vers la documentation de SparkPost sur la création de copies en double (ou d'archives) d'un e-mail. Des exemples d'en-têtes X-MSYS-API pour ce projet sont montrés plus tard dans ce blog.

Il y a une mise en garde à cette approche ; bien que toutes les informations d'événement dans l'e-mail original soient liées par un transmission_id et un message_id, il n'y a pas d'information dans l'événement de relais entrant (le mécanisme pour obtenir et diffuser l'e-mail d'archive) pour l'e-mail en double qui se rattache à l'un de ces deux identifiants et donc les informations pour l'e-mail original. Cela signifie que nous devons placer des données dans le corps de l'e-mail et l'en-tête de l'e-mail original comme moyen de rassembler toutes les données de SparkPost depuis l'e-mail original et l'e-mail d'archive.

Pour créer le code qui est placé dans le corps de l'e-mail, j'ai utilisé le processus suivant dans l'application de création d'e-mails.

  1. Quelque part dans le corps de l'e-mail, j'ai placé l'entrée suivante :<input name="ArchiveCode" type="hidden" value="<<UID>>">

  2. Puis j'ai créé un code unique et remplacé le champ <<UID>> :$uid = md5(uniqid(rand(), true)); $emailBody = str_replace("<<UID>>,$uid,$emailBody);

    Voici un exemple de sortie :

    <input name="ArchiveCode" type="hidden" value="00006365263145">

  3. Ensuite, j'ai veillé à ajouter le $UID au bloc meta_data de l'en-tête X-MSYS-API. Cette étape garantit que le UID est intégré dans chaque sortie d'événement pour l'e-mail original :

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>"
  }
}

Maintenant nous avons un moyen de lier toutes les données de l'e-mail original au corps de l'e-mail de l'archive.

Dans SparkPost, la meilleure façon d'archiver un e-mail est de créer une copie identique de l'e-mail spécialement conçue pour des fins d'archivage. Cela se fait en utilisant la fonctionnalité Archive de SparkPost. La fonctionnalité Archive de SparkPost donne au destinataire la possibilité d'envoyer un doublon de l'e-mail à une ou plusieurs adresses e-mail. Ce doublon utilise les mêmes liens de suivi et de consultation que l'original. La documentation de SparkPost définit la fonctionnalité Archive de la manière suivante :

Les destinataires de la liste d'archivage recevront une réplique exacte du message qui a été envoyé à l'adresse RCPT TO. En particulier, tous les liens encodés destinés au destinataire RCPT TO seront identiques dans les messages d'archive.

La seule différence entre cette copie d'archive et l'e-mail original RCPT TO est que certaines des en-têtes seront différentes puisque l'adresse cible pour l'e-mail d'archivage est différente, mais le corps de l'e-mail sera une réplique exacte !

Si vous souhaitez une explication plus approfondie, voici un lien vers la documentation de SparkPost sur la création de copies en double (ou d'archives) d'un e-mail. Des exemples d'en-têtes X-MSYS-API pour ce projet sont montrés plus tard dans ce blog.

Il y a une mise en garde à cette approche ; bien que toutes les informations d'événement dans l'e-mail original soient liées par un transmission_id et un message_id, il n'y a pas d'information dans l'événement de relais entrant (le mécanisme pour obtenir et diffuser l'e-mail d'archive) pour l'e-mail en double qui se rattache à l'un de ces deux identifiants et donc les informations pour l'e-mail original. Cela signifie que nous devons placer des données dans le corps de l'e-mail et l'en-tête de l'e-mail original comme moyen de rassembler toutes les données de SparkPost depuis l'e-mail original et l'e-mail d'archive.

Pour créer le code qui est placé dans le corps de l'e-mail, j'ai utilisé le processus suivant dans l'application de création d'e-mails.

  1. Quelque part dans le corps de l'e-mail, j'ai placé l'entrée suivante :<input name="ArchiveCode" type="hidden" value="<<UID>>">

  2. Puis j'ai créé un code unique et remplacé le champ <<UID>> :$uid = md5(uniqid(rand(), true)); $emailBody = str_replace("<<UID>>,$uid,$emailBody);

    Voici un exemple de sortie :

    <input name="ArchiveCode" type="hidden" value="00006365263145">

  3. Ensuite, j'ai veillé à ajouter le $UID au bloc meta_data de l'en-tête X-MSYS-API. Cette étape garantit que le UID est intégré dans chaque sortie d'événement pour l'e-mail original :

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>"
  }
}

Maintenant nous avons un moyen de lier toutes les données de l'e-mail original au corps de l'e-mail de l'archive.

Dans SparkPost, la meilleure façon d'archiver un e-mail est de créer une copie identique de l'e-mail spécialement conçue pour des fins d'archivage. Cela se fait en utilisant la fonctionnalité Archive de SparkPost. La fonctionnalité Archive de SparkPost donne au destinataire la possibilité d'envoyer un doublon de l'e-mail à une ou plusieurs adresses e-mail. Ce doublon utilise les mêmes liens de suivi et de consultation que l'original. La documentation de SparkPost définit la fonctionnalité Archive de la manière suivante :

Les destinataires de la liste d'archivage recevront une réplique exacte du message qui a été envoyé à l'adresse RCPT TO. En particulier, tous les liens encodés destinés au destinataire RCPT TO seront identiques dans les messages d'archive.

La seule différence entre cette copie d'archive et l'e-mail original RCPT TO est que certaines des en-têtes seront différentes puisque l'adresse cible pour l'e-mail d'archivage est différente, mais le corps de l'e-mail sera une réplique exacte !

Si vous souhaitez une explication plus approfondie, voici un lien vers la documentation de SparkPost sur la création de copies en double (ou d'archives) d'un e-mail. Des exemples d'en-têtes X-MSYS-API pour ce projet sont montrés plus tard dans ce blog.

Il y a une mise en garde à cette approche ; bien que toutes les informations d'événement dans l'e-mail original soient liées par un transmission_id et un message_id, il n'y a pas d'information dans l'événement de relais entrant (le mécanisme pour obtenir et diffuser l'e-mail d'archive) pour l'e-mail en double qui se rattache à l'un de ces deux identifiants et donc les informations pour l'e-mail original. Cela signifie que nous devons placer des données dans le corps de l'e-mail et l'en-tête de l'e-mail original comme moyen de rassembler toutes les données de SparkPost depuis l'e-mail original et l'e-mail d'archive.

Pour créer le code qui est placé dans le corps de l'e-mail, j'ai utilisé le processus suivant dans l'application de création d'e-mails.

  1. Quelque part dans le corps de l'e-mail, j'ai placé l'entrée suivante :<input name="ArchiveCode" type="hidden" value="<<UID>>">

  2. Puis j'ai créé un code unique et remplacé le champ <<UID>> :$uid = md5(uniqid(rand(), true)); $emailBody = str_replace("<<UID>>,$uid,$emailBody);

    Voici un exemple de sortie :

    <input name="ArchiveCode" type="hidden" value="00006365263145">

  3. Ensuite, j'ai veillé à ajouter le $UID au bloc meta_data de l'en-tête X-MSYS-API. Cette étape garantit que le UID est intégré dans chaque sortie d'événement pour l'e-mail original :

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>"
  }
}

Maintenant nous avons un moyen de lier toutes les données de l'e-mail original au corps de l'e-mail de l'archive.

Obtention de la version Archive

Pour obtenir une copie d'un email pour archivage, vous devez suivre les étapes suivantes :

  1. Créer un sous-domaine vers lequel vous enverrez tous les e-mails (en double) d'archive

  2. Définissez les enregistrements DNS appropriés pour que tous les e-mails envoyés à ce sous-domaine soient dirigés vers SparkPost

  3. Créer un domaine entrant dans SparkPost

  4. Créer un webhook entrant dans SparkPost

  5. Créer une application (collecteur) pour recevoir le flux de données du webhook SparkPost

Les deux liens suivants peuvent être utilisés pour vous guider tout au long de ce processus :

  1. Documentation technique SparkPost : Enabling Inbound Email Relaying & Relay Webhooks

  2. De plus, le blog que j'ai écrit l'année dernière, Archiving Emails: A How-To Guide for Tracking Sent Mail vous guidera dans la création de la transmission entrante avec SparkPost

* Note : depuis octobre 2018, la fonctionnalité Archive ne fonctionne que lorsqu'on envoie des e-mails en utilisant une connexion SMTP à SparkPost, l'API RESTful ne prend pas en charge cette fonctionnalité.  Cela ne pose probablement pas de problème car la plupart des e-mails qui nécessitent ce niveau de contrôle d'audit ont tendance à être des e-mails personnalisés qui sont entièrement construits par une application backend avant que l'envoi de l'e-mail ne soit nécessaire.

Pour obtenir une copie d'un email pour archivage, vous devez suivre les étapes suivantes :

  1. Créer un sous-domaine vers lequel vous enverrez tous les e-mails (en double) d'archive

  2. Définissez les enregistrements DNS appropriés pour que tous les e-mails envoyés à ce sous-domaine soient dirigés vers SparkPost

  3. Créer un domaine entrant dans SparkPost

  4. Créer un webhook entrant dans SparkPost

  5. Créer une application (collecteur) pour recevoir le flux de données du webhook SparkPost

Les deux liens suivants peuvent être utilisés pour vous guider tout au long de ce processus :

  1. Documentation technique SparkPost : Enabling Inbound Email Relaying & Relay Webhooks

  2. De plus, le blog que j'ai écrit l'année dernière, Archiving Emails: A How-To Guide for Tracking Sent Mail vous guidera dans la création de la transmission entrante avec SparkPost

* Note : depuis octobre 2018, la fonctionnalité Archive ne fonctionne que lorsqu'on envoie des e-mails en utilisant une connexion SMTP à SparkPost, l'API RESTful ne prend pas en charge cette fonctionnalité.  Cela ne pose probablement pas de problème car la plupart des e-mails qui nécessitent ce niveau de contrôle d'audit ont tendance à être des e-mails personnalisés qui sont entièrement construits par une application backend avant que l'envoi de l'e-mail ne soit nécessaire.

Pour obtenir une copie d'un email pour archivage, vous devez suivre les étapes suivantes :

  1. Créer un sous-domaine vers lequel vous enverrez tous les e-mails (en double) d'archive

  2. Définissez les enregistrements DNS appropriés pour que tous les e-mails envoyés à ce sous-domaine soient dirigés vers SparkPost

  3. Créer un domaine entrant dans SparkPost

  4. Créer un webhook entrant dans SparkPost

  5. Créer une application (collecteur) pour recevoir le flux de données du webhook SparkPost

Les deux liens suivants peuvent être utilisés pour vous guider tout au long de ce processus :

  1. Documentation technique SparkPost : Enabling Inbound Email Relaying & Relay Webhooks

  2. De plus, le blog que j'ai écrit l'année dernière, Archiving Emails: A How-To Guide for Tracking Sent Mail vous guidera dans la création de la transmission entrante avec SparkPost

* Note : depuis octobre 2018, la fonctionnalité Archive ne fonctionne que lorsqu'on envoie des e-mails en utilisant une connexion SMTP à SparkPost, l'API RESTful ne prend pas en charge cette fonctionnalité.  Cela ne pose probablement pas de problème car la plupart des e-mails qui nécessitent ce niveau de contrôle d'audit ont tendance à être des e-mails personnalisés qui sont entièrement construits par une application backend avant que l'envoi de l'e-mail ne soit nécessaire.

Obtention de l'email en double dans une structure JSON

Dans la première phase de ce projet, tout ce que je stocke est le format d'email rfc822 dans S3 et certains champs de description de haut niveau dans une table SQL pour la recherche.  Puisque SparkPost enverra les données des emails dans une structure JSON à ma plateforme d'archivage via des flux de données webhook, j'ai construit une application (souvent appelée un collecteur) qui accepte le flux de données Relay_Webhook.

Chaque paquet du SparkPost Relay_Webhook contiendra les informations d'un email dupliqué à la fois, donc décomposer la structure JSON en composants ciblés pour ce projet est assez simple.  Dans mon code PHP, récupérer l'email formaté en rfc822 était aussi simple que les quelques lignes de code suivantes :

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'];
}

Certaines des informations que je souhaite stocker dans ma table SQL résident dans un tableau de champs d'en-tête.  J'ai donc écrit une petite fonction qui acceptait le tableau d'en-têtes et parcourait le tableau pour obtenir les données que je souhaitais stocker :

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;
            }
        }
    }
}

Maintenant que j'ai les données, je suis prêt à stocker le corps dans S3.

Dans la première phase de ce projet, tout ce que je stocke est le format d'email rfc822 dans S3 et certains champs de description de haut niveau dans une table SQL pour la recherche.  Puisque SparkPost enverra les données des emails dans une structure JSON à ma plateforme d'archivage via des flux de données webhook, j'ai construit une application (souvent appelée un collecteur) qui accepte le flux de données Relay_Webhook.

Chaque paquet du SparkPost Relay_Webhook contiendra les informations d'un email dupliqué à la fois, donc décomposer la structure JSON en composants ciblés pour ce projet est assez simple.  Dans mon code PHP, récupérer l'email formaté en rfc822 était aussi simple que les quelques lignes de code suivantes :

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'];
}

Certaines des informations que je souhaite stocker dans ma table SQL résident dans un tableau de champs d'en-tête.  J'ai donc écrit une petite fonction qui acceptait le tableau d'en-têtes et parcourait le tableau pour obtenir les données que je souhaitais stocker :

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;
            }
        }
    }
}

Maintenant que j'ai les données, je suis prêt à stocker le corps dans S3.

Dans la première phase de ce projet, tout ce que je stocke est le format d'email rfc822 dans S3 et certains champs de description de haut niveau dans une table SQL pour la recherche.  Puisque SparkPost enverra les données des emails dans une structure JSON à ma plateforme d'archivage via des flux de données webhook, j'ai construit une application (souvent appelée un collecteur) qui accepte le flux de données Relay_Webhook.

Chaque paquet du SparkPost Relay_Webhook contiendra les informations d'un email dupliqué à la fois, donc décomposer la structure JSON en composants ciblés pour ce projet est assez simple.  Dans mon code PHP, récupérer l'email formaté en rfc822 était aussi simple que les quelques lignes de code suivantes :

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'];
}

Certaines des informations que je souhaite stocker dans ma table SQL résident dans un tableau de champs d'en-tête.  J'ai donc écrit une petite fonction qui acceptait le tableau d'en-têtes et parcourait le tableau pour obtenir les données que je souhaitais stocker :

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;
            }
        }
    }
}

Maintenant que j'ai les données, je suis prêt à stocker le corps dans S3.

Stockage de l'email dupliqué dans S3

Je suis désolé de vous décevoir mais je ne vais pas vous donner un tutoriel étape par étape sur la création d'un bucket S3 pour stocker les emails, ni décrire comment créer la clé d'accès nécessaire que vous devrez utiliser dans votre application pour télécharger du contenu vers votre bucket ; il existe de meilleurs tutoriels sur ce sujet que je ne pourrais jamais écrire.  Voici quelques articles qui pourraient vous aider :

https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/

Ce que je vais faire est de souligner certains des paramètres que j'ai choisis qui se rapportent à un projet comme celui-ci.

  1. Contrôle d'accès.  Vous devez non seulement définir la sécurité pour le bucket, mais aussi définir les autorisations pour les éléments eux-mêmes.  Dans mon projet, j'utilise une politique très ouverte de lecture publique parce que les données d'exemple ne sont pas personnelles et je voulais un accès facile aux données.  Vous voudrez probablement un ensemble de politiques ACL bien plus strict. Voici un bon article sur les paramètres ACL : https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html

  2. Archivage de l'Archive. Dans S3, il existe quelque chose appelé Gestion du cycle de vie.  Cela vous permet de déplacer des données d'un type de classe de stockage S3 à une autre.  Les différentes classes de stockage représentent la quantité d'accès dont vous avez besoin aux données stockées, avec des coûts inférieurs associés au stockage que vous accédez le moins. Une bonne description des différentes classes et de leur transition se trouve dans un guide AWS appelé, Transitioning Objects. Dans mon cas, j'ai choisi de créer un cycle de vie qui a déplacé chaque objet de Standard à Glacier après un an. L'accès Glacier est beaucoup moins cher que l'archive S3 standard et me permettra d'économiser de l'argent en frais de stockage.

Une fois que j'ai créé le bucket S3 et que mes paramètres sont en place, S3 est prêt à recevoir l'email conforme à la rfc822 que j'ai obtenu à partir du flux de données SparkPost Relay Webhook. Mais avant de télécharger la charge utile de l'email rfc822 vers S3, je dois créer un nom de fichier unique que j'utiliserai pour stocker cet email.

Pour le nom de fichier unique, je vais rechercher dans le corps de l'email l'identifiant caché que l'application d'envoi a inséré dans l'email et utiliser cet identifiant comme nom du fichier. Il existe des moyens plus élégants pour extraire le connectorId du corps HTML, mais pour la simplicité et la clarté, je vais utiliser le code suivant :

$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);
        }
    }
}

* nous supposons que $inputField contient la valeur « ArchiveCode » et a été trouvé dans mon fichier config.php.

Avec l'UID, nous pouvons alors créer le nom de fichier qui sera utilisé dans S3 :

$fileName = $ArchiveDirectory . '/' . $UID . '.eml';

Maintenant, je peux ouvrir ma connexion à S3 et télécharger le fichier. Si vous regardez dans le fichier s3.php du dépôt GitHub, vous verrez qu'il faut très peu de code pour télécharger le fichier.

Ma dernière étape est d'enregistrer cette entrée dans la table MYSQL.

Je suis désolé de vous décevoir mais je ne vais pas vous donner un tutoriel étape par étape sur la création d'un bucket S3 pour stocker les emails, ni décrire comment créer la clé d'accès nécessaire que vous devrez utiliser dans votre application pour télécharger du contenu vers votre bucket ; il existe de meilleurs tutoriels sur ce sujet que je ne pourrais jamais écrire.  Voici quelques articles qui pourraient vous aider :

https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/

Ce que je vais faire est de souligner certains des paramètres que j'ai choisis qui se rapportent à un projet comme celui-ci.

  1. Contrôle d'accès.  Vous devez non seulement définir la sécurité pour le bucket, mais aussi définir les autorisations pour les éléments eux-mêmes.  Dans mon projet, j'utilise une politique très ouverte de lecture publique parce que les données d'exemple ne sont pas personnelles et je voulais un accès facile aux données.  Vous voudrez probablement un ensemble de politiques ACL bien plus strict. Voici un bon article sur les paramètres ACL : https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html

  2. Archivage de l'Archive. Dans S3, il existe quelque chose appelé Gestion du cycle de vie.  Cela vous permet de déplacer des données d'un type de classe de stockage S3 à une autre.  Les différentes classes de stockage représentent la quantité d'accès dont vous avez besoin aux données stockées, avec des coûts inférieurs associés au stockage que vous accédez le moins. Une bonne description des différentes classes et de leur transition se trouve dans un guide AWS appelé, Transitioning Objects. Dans mon cas, j'ai choisi de créer un cycle de vie qui a déplacé chaque objet de Standard à Glacier après un an. L'accès Glacier est beaucoup moins cher que l'archive S3 standard et me permettra d'économiser de l'argent en frais de stockage.

Une fois que j'ai créé le bucket S3 et que mes paramètres sont en place, S3 est prêt à recevoir l'email conforme à la rfc822 que j'ai obtenu à partir du flux de données SparkPost Relay Webhook. Mais avant de télécharger la charge utile de l'email rfc822 vers S3, je dois créer un nom de fichier unique que j'utiliserai pour stocker cet email.

Pour le nom de fichier unique, je vais rechercher dans le corps de l'email l'identifiant caché que l'application d'envoi a inséré dans l'email et utiliser cet identifiant comme nom du fichier. Il existe des moyens plus élégants pour extraire le connectorId du corps HTML, mais pour la simplicité et la clarté, je vais utiliser le code suivant :

$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);
        }
    }
}

* nous supposons que $inputField contient la valeur « ArchiveCode » et a été trouvé dans mon fichier config.php.

Avec l'UID, nous pouvons alors créer le nom de fichier qui sera utilisé dans S3 :

$fileName = $ArchiveDirectory . '/' . $UID . '.eml';

Maintenant, je peux ouvrir ma connexion à S3 et télécharger le fichier. Si vous regardez dans le fichier s3.php du dépôt GitHub, vous verrez qu'il faut très peu de code pour télécharger le fichier.

Ma dernière étape est d'enregistrer cette entrée dans la table MYSQL.

Je suis désolé de vous décevoir mais je ne vais pas vous donner un tutoriel étape par étape sur la création d'un bucket S3 pour stocker les emails, ni décrire comment créer la clé d'accès nécessaire que vous devrez utiliser dans votre application pour télécharger du contenu vers votre bucket ; il existe de meilleurs tutoriels sur ce sujet que je ne pourrais jamais écrire.  Voici quelques articles qui pourraient vous aider :

https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/

Ce que je vais faire est de souligner certains des paramètres que j'ai choisis qui se rapportent à un projet comme celui-ci.

  1. Contrôle d'accès.  Vous devez non seulement définir la sécurité pour le bucket, mais aussi définir les autorisations pour les éléments eux-mêmes.  Dans mon projet, j'utilise une politique très ouverte de lecture publique parce que les données d'exemple ne sont pas personnelles et je voulais un accès facile aux données.  Vous voudrez probablement un ensemble de politiques ACL bien plus strict. Voici un bon article sur les paramètres ACL : https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html

  2. Archivage de l'Archive. Dans S3, il existe quelque chose appelé Gestion du cycle de vie.  Cela vous permet de déplacer des données d'un type de classe de stockage S3 à une autre.  Les différentes classes de stockage représentent la quantité d'accès dont vous avez besoin aux données stockées, avec des coûts inférieurs associés au stockage que vous accédez le moins. Une bonne description des différentes classes et de leur transition se trouve dans un guide AWS appelé, Transitioning Objects. Dans mon cas, j'ai choisi de créer un cycle de vie qui a déplacé chaque objet de Standard à Glacier après un an. L'accès Glacier est beaucoup moins cher que l'archive S3 standard et me permettra d'économiser de l'argent en frais de stockage.

Une fois que j'ai créé le bucket S3 et que mes paramètres sont en place, S3 est prêt à recevoir l'email conforme à la rfc822 que j'ai obtenu à partir du flux de données SparkPost Relay Webhook. Mais avant de télécharger la charge utile de l'email rfc822 vers S3, je dois créer un nom de fichier unique que j'utiliserai pour stocker cet email.

Pour le nom de fichier unique, je vais rechercher dans le corps de l'email l'identifiant caché que l'application d'envoi a inséré dans l'email et utiliser cet identifiant comme nom du fichier. Il existe des moyens plus élégants pour extraire le connectorId du corps HTML, mais pour la simplicité et la clarté, je vais utiliser le code suivant :

$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);
        }
    }
}

* nous supposons que $inputField contient la valeur « ArchiveCode » et a été trouvé dans mon fichier config.php.

Avec l'UID, nous pouvons alors créer le nom de fichier qui sera utilisé dans S3 :

$fileName = $ArchiveDirectory . '/' . $UID . '.eml';

Maintenant, je peux ouvrir ma connexion à S3 et télécharger le fichier. Si vous regardez dans le fichier s3.php du dépôt GitHub, vous verrez qu'il faut très peu de code pour télécharger le fichier.

Ma dernière étape est d'enregistrer cette entrée dans la table MYSQL.

Stockage des Meta Data dans MySQL

Nous avons récupéré toutes les données nécessaires à une étape précédente, donc l'étape du stockage est facile.  Dans cette première phase, j'ai choisi de construire une table avec les champs suivants:

Champs de Métadonnées MySQL

Champ

Objectif

Date/heure (auto)

Horodatage lorsque l'entrée a été enregistrée

Adresse RCPT_TO

Adresse email cible pour le message archivé

Horodatage de l'en-tête DATE

Heure d'envoi d'origine de l'email

En-tête SUBJECT

Ligne de sujet pour l'indexation et la recherche

En-tête FROM

Identifiant de l'expéditeur pour la recherche

Répertoire S3

Chemin du répertoire à l'intérieur du seau S3

Nom de fichier S3

Fichier .eml unique stocké dans S3

La fonction appelée, MySQLLog, dans le fichier d'application upload.php, passe par les étapes nécessaires pour ouvrir le lien vers MySQL, injecter la nouvelle ligne, tester les résultats et fermer le lien. J'ajoute une autre étape par précaution, qui est de consigner ces données dans un fichier texte. Devrais-je faire beaucoup plus de journalisation pour les erreurs ? Oui. Mais je veux garder ce code léger pour lui permettre de fonctionner extrêmement rapidement. Parfois, ce code sera appelé des centaines de fois par minute et doit être aussi efficace que possible. Dans les futures mises à jour, j'ajouterai du code auxiliaire qui traitera les échecs et enverra par email ces échecs à un administrateur pour surveillance.

Nous avons récupéré toutes les données nécessaires à une étape précédente, donc l'étape du stockage est facile.  Dans cette première phase, j'ai choisi de construire une table avec les champs suivants:

Champs de Métadonnées MySQL

Champ

Objectif

Date/heure (auto)

Horodatage lorsque l'entrée a été enregistrée

Adresse RCPT_TO

Adresse email cible pour le message archivé

Horodatage de l'en-tête DATE

Heure d'envoi d'origine de l'email

En-tête SUBJECT

Ligne de sujet pour l'indexation et la recherche

En-tête FROM

Identifiant de l'expéditeur pour la recherche

Répertoire S3

Chemin du répertoire à l'intérieur du seau S3

Nom de fichier S3

Fichier .eml unique stocké dans S3

La fonction appelée, MySQLLog, dans le fichier d'application upload.php, passe par les étapes nécessaires pour ouvrir le lien vers MySQL, injecter la nouvelle ligne, tester les résultats et fermer le lien. J'ajoute une autre étape par précaution, qui est de consigner ces données dans un fichier texte. Devrais-je faire beaucoup plus de journalisation pour les erreurs ? Oui. Mais je veux garder ce code léger pour lui permettre de fonctionner extrêmement rapidement. Parfois, ce code sera appelé des centaines de fois par minute et doit être aussi efficace que possible. Dans les futures mises à jour, j'ajouterai du code auxiliaire qui traitera les échecs et enverra par email ces échecs à un administrateur pour surveillance.

Nous avons récupéré toutes les données nécessaires à une étape précédente, donc l'étape du stockage est facile.  Dans cette première phase, j'ai choisi de construire une table avec les champs suivants:

Champs de Métadonnées MySQL

Champ

Objectif

Date/heure (auto)

Horodatage lorsque l'entrée a été enregistrée

Adresse RCPT_TO

Adresse email cible pour le message archivé

Horodatage de l'en-tête DATE

Heure d'envoi d'origine de l'email

En-tête SUBJECT

Ligne de sujet pour l'indexation et la recherche

En-tête FROM

Identifiant de l'expéditeur pour la recherche

Répertoire S3

Chemin du répertoire à l'intérieur du seau S3

Nom de fichier S3

Fichier .eml unique stocké dans S3

La fonction appelée, MySQLLog, dans le fichier d'application upload.php, passe par les étapes nécessaires pour ouvrir le lien vers MySQL, injecter la nouvelle ligne, tester les résultats et fermer le lien. J'ajoute une autre étape par précaution, qui est de consigner ces données dans un fichier texte. Devrais-je faire beaucoup plus de journalisation pour les erreurs ? Oui. Mais je veux garder ce code léger pour lui permettre de fonctionner extrêmement rapidement. Parfois, ce code sera appelé des centaines de fois par minute et doit être aussi efficace que possible. Dans les futures mises à jour, j'ajouterai du code auxiliaire qui traitera les échecs et enverra par email ces échecs à un administrateur pour surveillance.

En résumé

Donc, en quelques étapes assez faciles, nous avons pu parcourir la première phase de la création d'un système d'archivage des e-mails robuste qui conserve le duplicata de l'email dans S3 et croise les données dans une table MySQL.  Cela nous fournira une base pour le reste du projet qui sera abordé dans plusieurs publications futures.

Dans les futures révisions de ce projet, je m'attends à :

  1. Stocker tous les événements de journal de l'email original

  2. Envoyer les erreurs de stockage à un administrateur lorsqu'un échec de téléchargement ou d'enregistrement se produit

  3. Minimiser la complexité du collecteur.

  4. Ajouter une interface utilisateur pour visualiser toutes les données

  5. Prendre en charge la possibilité de renvoyer l'email

En attendant, j'espère que ce projet a été intéressant et utile pour vous ; bon envoi.

Donc, en quelques étapes assez faciles, nous avons pu parcourir la première phase de la création d'un système d'archivage des e-mails robuste qui conserve le duplicata de l'email dans S3 et croise les données dans une table MySQL.  Cela nous fournira une base pour le reste du projet qui sera abordé dans plusieurs publications futures.

Dans les futures révisions de ce projet, je m'attends à :

  1. Stocker tous les événements de journal de l'email original

  2. Envoyer les erreurs de stockage à un administrateur lorsqu'un échec de téléchargement ou d'enregistrement se produit

  3. Minimiser la complexité du collecteur.

  4. Ajouter une interface utilisateur pour visualiser toutes les données

  5. Prendre en charge la possibilité de renvoyer l'email

En attendant, j'espère que ce projet a été intéressant et utile pour vous ; bon envoi.

Donc, en quelques étapes assez faciles, nous avons pu parcourir la première phase de la création d'un système d'archivage des e-mails robuste qui conserve le duplicata de l'email dans S3 et croise les données dans une table MySQL.  Cela nous fournira une base pour le reste du projet qui sera abordé dans plusieurs publications futures.

Dans les futures révisions de ce projet, je m'attends à :

  1. Stocker tous les événements de journal de l'email original

  2. Envoyer les erreurs de stockage à un administrateur lorsqu'un échec de téléchargement ou d'enregistrement se produit

  3. Minimiser la complexité du collecteur.

  4. Ajouter une interface utilisateur pour visualiser toutes les données

  5. Prendre en charge la possibilité de renvoyer l'email

En attendant, j'espère que ce projet a été intéressant et utile pour vous ; bon envoi.

Autres news

Lire la suite de cette catégorie

A person is standing at a desk while typing on a laptop.

La plateforme native AI complète qui évolue avec votre business.

A person is standing at a desk while typing on a laptop.

La plateforme native AI complète qui évolue avec votre business.