Construindo um Sistema de Arquivamento de E-mails: Armazenando o Corpo do E-mail
Pássaro
4 de mar. de 2019
1 min read

Principais Conclusões
Propósito: Esta postagem descreve a primeira fase de construção de um sistema de arquivamento de e-mails usando SparkPost, Amazon S3 e MySQL. Ela explica como duplicar, capturar e armazenar e-mails para acesso e conformidade de longo prazo.
Ideia central: O sistema armazena automaticamente o corpo do e-mail em formato bruto (rfc822) no S3 e registra metadados (assunto, remetente, timestamp, etc.) no MySQL para busca e recuperação rápidas.
Essenciais abordados:
Criando duplicatas para arquivamento: Use o Recurso de Arquivo do SparkPost para enviar cópias idênticas de e-mails enviados para um endereço de arquivamento designado, garantindo que o corpo e os links de rastreamento permaneçam idênticos.
Vinculação de dados via UID: Incorpore um identificador exclusivo (UID) tanto no corpo do e-mail quanto nos metadados X-MSYS-API para vincular as mensagens originais e arquivadas.
Processamento de entrada: Configure um domínio de entrada e webhook no SparkPost para receber as cargas JSON de e-mails arquivados através de um coletor de aplicativo.
Armazenando e-mails no S3: Carregue o corpo rfc822 analisado em um bucket S3, usando regras de ciclo de vida (por exemplo, transição para Glacier após um ano) para reduzir os custos de armazenamento.
Registrando metadados no MySQL: Salve campos chave como RCPT_TO, FROM, SUBJECT e nome do arquivo S3 para indexação de busca e recuperação futura.
Considerações de desempenho: A eficiência do código e o registro mínimo garantem que o coletor possa lidar com centenas de requisições por minuto com latência mínima.
Visão geral: Esta base suporta melhorias futuras – como armazenamento de eventos de log, alertas de falha e visualização de UI – estabelecendo as bases para uma solução de arquivamento de e-mails escalável e auditável.
Destaques de Perguntas e Respostas
Qual é o objetivo deste projeto?
Para criar um sistema de arquivamento de e-mails automatizado que armazena os corpos das mensagens no Amazon S3, mantendo metadados pesquisáveis em um banco de dados MySQL.
Por que usar o recurso de Arquivo do SparkPost?
Ele permite que você gere duplicatas exatas de e-mails enviados, preservando sua estrutura e dados de rastreamento para conformidade e revisão.
Como cada e-mail arquivado está vinculado à sua mensagem original?
Um UID exclusivo está incorporado tanto no corpo do email quanto nos metadados, permitindo uma referência cruzada precisa entre as cópias originais e arquivadas.
Por que usar o S3 para armazenamento?
S3 oferece opções de armazenamento escalável e gerenciamento de ciclo de vida (como Glacier), tornando-o econômico para retenção de emails a longo prazo.
O que o banco de dados MySQL armazena?
Ele armazena campos de metadados pesquisáveis—como linha de assunto, remetente, carimbos de data/hora e o nome do arquivo S3—permitindo consultas e recuperações eficientes.
Quais são os próximos passos de desenvolvimento?
Adicionando rastreamento de eventos de log, relatórios automatizados de erros, um coletor simplificado e uma interface de usuário para visualizar ou reenviar e-mails arquivados.
Neste blog, descreverei o processo que passei para armazenar o corpo do email no S3 (Serviço de Armazenamento Simples da Amazon) e dados auxiliares em uma tabela MySQL para fácil referência cruzada. Em última análise, este é o ponto de partida para a base de código que incluirá um aplicativo que permitirá uma pesquisa fácil de e-mails arquivados e, em seguida, exibir esses e-mails juntamente com os dados de eventos (log). O código deste projeto pode ser encontrado no seguinte repositório do GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Embora eu vá utilizar o S3 e o MySQL neste projeto, de forma alguma essas são as únicas tecnologias que podem ser usadas para construir uma plataforma de arquivamento, mas dado a ubiquidade delas, pensei que eram uma boa escolha para este projeto. Em um sistema de alta escala e alto volume, eu usaria um banco de dados de desempenho superior ao MySQL, mas para este projeto de amostra, o MySQL é perfeito. Para organizações que consideram o PostgreSQL como sua escolha de banco de dados para arquivamento, implementar procedimentos adequados de backup e recuperação é essencial para manter a integridade dos dados em sistemas de produção.
Detalhei abaixo os passos que segui nesta primeira fase do projeto:
Criar o email duplicado para arquivamento
Usar os recursos de Arquivamento e Relay de Entrada do SparkPost para enviar uma cópia do email original de volta ao SparkPost para processamento em uma estrutura JSON, que será enviada para um coletor de webhook (aplicativo)
Desmantelar a estrutura JSON para obter os componentes necessários
Enviar o corpo do email para o S3 para armazenamento
Registrar uma entrada no MySQL para cada email para referência cruzada
Neste blog, descreverei o processo que passei para armazenar o corpo do email no S3 (Serviço de Armazenamento Simples da Amazon) e dados auxiliares em uma tabela MySQL para fácil referência cruzada. Em última análise, este é o ponto de partida para a base de código que incluirá um aplicativo que permitirá uma pesquisa fácil de e-mails arquivados e, em seguida, exibir esses e-mails juntamente com os dados de eventos (log). O código deste projeto pode ser encontrado no seguinte repositório do GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Embora eu vá utilizar o S3 e o MySQL neste projeto, de forma alguma essas são as únicas tecnologias que podem ser usadas para construir uma plataforma de arquivamento, mas dado a ubiquidade delas, pensei que eram uma boa escolha para este projeto. Em um sistema de alta escala e alto volume, eu usaria um banco de dados de desempenho superior ao MySQL, mas para este projeto de amostra, o MySQL é perfeito. Para organizações que consideram o PostgreSQL como sua escolha de banco de dados para arquivamento, implementar procedimentos adequados de backup e recuperação é essencial para manter a integridade dos dados em sistemas de produção.
Detalhei abaixo os passos que segui nesta primeira fase do projeto:
Criar o email duplicado para arquivamento
Usar os recursos de Arquivamento e Relay de Entrada do SparkPost para enviar uma cópia do email original de volta ao SparkPost para processamento em uma estrutura JSON, que será enviada para um coletor de webhook (aplicativo)
Desmantelar a estrutura JSON para obter os componentes necessários
Enviar o corpo do email para o S3 para armazenamento
Registrar uma entrada no MySQL para cada email para referência cruzada
Neste blog, descreverei o processo que passei para armazenar o corpo do email no S3 (Serviço de Armazenamento Simples da Amazon) e dados auxiliares em uma tabela MySQL para fácil referência cruzada. Em última análise, este é o ponto de partida para a base de código que incluirá um aplicativo que permitirá uma pesquisa fácil de e-mails arquivados e, em seguida, exibir esses e-mails juntamente com os dados de eventos (log). O código deste projeto pode ser encontrado no seguinte repositório do GitHub: https://github.com/jeff-goldstein/PHPArchivePlatform.
Embora eu vá utilizar o S3 e o MySQL neste projeto, de forma alguma essas são as únicas tecnologias que podem ser usadas para construir uma plataforma de arquivamento, mas dado a ubiquidade delas, pensei que eram uma boa escolha para este projeto. Em um sistema de alta escala e alto volume, eu usaria um banco de dados de desempenho superior ao MySQL, mas para este projeto de amostra, o MySQL é perfeito. Para organizações que consideram o PostgreSQL como sua escolha de banco de dados para arquivamento, implementar procedimentos adequados de backup e recuperação é essencial para manter a integridade dos dados em sistemas de produção.
Detalhei abaixo os passos que segui nesta primeira fase do projeto:
Criar o email duplicado para arquivamento
Usar os recursos de Arquivamento e Relay de Entrada do SparkPost para enviar uma cópia do email original de volta ao SparkPost para processamento em uma estrutura JSON, que será enviada para um coletor de webhook (aplicativo)
Desmantelar a estrutura JSON para obter os componentes necessários
Enviar o corpo do email para o S3 para armazenamento
Registrar uma entrada no MySQL para cada email para referência cruzada
Criando uma Cópia do E-mail
No SparkPost, a melhor maneira de arquivar um e-mail é criar uma cópia idêntica do e-mail projetada especificamente para fins de arquivamento. Isso é feito usando o recurso de Arquivamento do SparkPost. O recurso de Arquivamento do SparkPost dá ao remetente a capacidade de enviar uma duplicata do e-mail para um ou mais endereços de e-mail. Essa duplicata utiliza os mesmos links de rastreamento e abertura que o original. A documentação do SparkPost define o recurso de Arquivamento da seguinte maneira:
Os destinatários na lista de arquivamento receberão uma réplica exata da mensagem que foi enviada para o endereço RCPT TO. Em particular, quaisquer links codificados destinados ao destinatário RCPT TO serão idênticos nas mensagens de arquivamento
A única diferença entre essa cópia de arquivamento e o e-mail original RCPT TO é que alguns dos cabeçalhos serão diferentes, uma vez que o endereço de destino do e-mail de arquivamento é diferente, mas o corpo do e-mail será uma réplica exata!
Se você quiser uma explicação mais profunda, aqui está um link para a documentação do SparkPost sobre como criar cópias duplicadas (ou de arquivamento) de um e-mail. Amostras de cabeçalhos X-MSYS-API para este projeto são mostradas mais adiante neste blog.
Há uma advertência sobre essa abordagem; enquanto todas as informações de eventos no e-mail original estão ligadas por um transmission_id e um message_id, não há informações no evento de retransmissão de entrada (o mecanismo para obter e disseminar o e-mail de arquivamento) para o e-mail duplicado que se conectam a um desses dois IDs e, portanto, às informações do e-mail original. Isso significa que precisamos colocar dados no corpo do e-mail e no cabeçalho do e-mail original como uma forma de unir todos os dados do SparkPost do e-mail original e do arquivamento.
Para criar o código que é colocado no corpo do e-mail, utilizei o seguinte processo no aplicativo de criação de e-mails.
Em algum lugar no corpo do e-mail, coloquei a seguinte entrada de input:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Em seguida, criei um código único e substituí o campo <<UID>>:$uid = md5(uniqid(rand(), true)); $emailBody = str_replace(“<<UID>>,$uid,$emailBody);
Aqui está um exemplo de saída:
<input name="ArchiveCode" type="hidden" value="00006365263145">
Em seguida, assegurei-me de adicionar o $UID ao bloco meta_data do cabeçalho X-MSYS-API. Esta etapa garante que o UID seja incorporado em cada saída de evento do 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>" } }
Agora temos uma maneira de vincular todos os dados do e-mail original ao corpo do e-mail de arquivamento.
No SparkPost, a melhor maneira de arquivar um e-mail é criar uma cópia idêntica do e-mail projetada especificamente para fins de arquivamento. Isso é feito usando o recurso de Arquivamento do SparkPost. O recurso de Arquivamento do SparkPost dá ao remetente a capacidade de enviar uma duplicata do e-mail para um ou mais endereços de e-mail. Essa duplicata utiliza os mesmos links de rastreamento e abertura que o original. A documentação do SparkPost define o recurso de Arquivamento da seguinte maneira:
Os destinatários na lista de arquivamento receberão uma réplica exata da mensagem que foi enviada para o endereço RCPT TO. Em particular, quaisquer links codificados destinados ao destinatário RCPT TO serão idênticos nas mensagens de arquivamento
A única diferença entre essa cópia de arquivamento e o e-mail original RCPT TO é que alguns dos cabeçalhos serão diferentes, uma vez que o endereço de destino do e-mail de arquivamento é diferente, mas o corpo do e-mail será uma réplica exata!
Se você quiser uma explicação mais profunda, aqui está um link para a documentação do SparkPost sobre como criar cópias duplicadas (ou de arquivamento) de um e-mail. Amostras de cabeçalhos X-MSYS-API para este projeto são mostradas mais adiante neste blog.
Há uma advertência sobre essa abordagem; enquanto todas as informações de eventos no e-mail original estão ligadas por um transmission_id e um message_id, não há informações no evento de retransmissão de entrada (o mecanismo para obter e disseminar o e-mail de arquivamento) para o e-mail duplicado que se conectam a um desses dois IDs e, portanto, às informações do e-mail original. Isso significa que precisamos colocar dados no corpo do e-mail e no cabeçalho do e-mail original como uma forma de unir todos os dados do SparkPost do e-mail original e do arquivamento.
Para criar o código que é colocado no corpo do e-mail, utilizei o seguinte processo no aplicativo de criação de e-mails.
Em algum lugar no corpo do e-mail, coloquei a seguinte entrada de input:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Em seguida, criei um código único e substituí o campo <<UID>>:$uid = md5(uniqid(rand(), true)); $emailBody = str_replace(“<<UID>>,$uid,$emailBody);
Aqui está um exemplo de saída:
<input name="ArchiveCode" type="hidden" value="00006365263145">
Em seguida, assegurei-me de adicionar o $UID ao bloco meta_data do cabeçalho X-MSYS-API. Esta etapa garante que o UID seja incorporado em cada saída de evento do 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>" } }
Agora temos uma maneira de vincular todos os dados do e-mail original ao corpo do e-mail de arquivamento.
No SparkPost, a melhor maneira de arquivar um e-mail é criar uma cópia idêntica do e-mail projetada especificamente para fins de arquivamento. Isso é feito usando o recurso de Arquivamento do SparkPost. O recurso de Arquivamento do SparkPost dá ao remetente a capacidade de enviar uma duplicata do e-mail para um ou mais endereços de e-mail. Essa duplicata utiliza os mesmos links de rastreamento e abertura que o original. A documentação do SparkPost define o recurso de Arquivamento da seguinte maneira:
Os destinatários na lista de arquivamento receberão uma réplica exata da mensagem que foi enviada para o endereço RCPT TO. Em particular, quaisquer links codificados destinados ao destinatário RCPT TO serão idênticos nas mensagens de arquivamento
A única diferença entre essa cópia de arquivamento e o e-mail original RCPT TO é que alguns dos cabeçalhos serão diferentes, uma vez que o endereço de destino do e-mail de arquivamento é diferente, mas o corpo do e-mail será uma réplica exata!
Se você quiser uma explicação mais profunda, aqui está um link para a documentação do SparkPost sobre como criar cópias duplicadas (ou de arquivamento) de um e-mail. Amostras de cabeçalhos X-MSYS-API para este projeto são mostradas mais adiante neste blog.
Há uma advertência sobre essa abordagem; enquanto todas as informações de eventos no e-mail original estão ligadas por um transmission_id e um message_id, não há informações no evento de retransmissão de entrada (o mecanismo para obter e disseminar o e-mail de arquivamento) para o e-mail duplicado que se conectam a um desses dois IDs e, portanto, às informações do e-mail original. Isso significa que precisamos colocar dados no corpo do e-mail e no cabeçalho do e-mail original como uma forma de unir todos os dados do SparkPost do e-mail original e do arquivamento.
Para criar o código que é colocado no corpo do e-mail, utilizei o seguinte processo no aplicativo de criação de e-mails.
Em algum lugar no corpo do e-mail, coloquei a seguinte entrada de input:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Em seguida, criei um código único e substituí o campo <<UID>>:$uid = md5(uniqid(rand(), true)); $emailBody = str_replace(“<<UID>>,$uid,$emailBody);
Aqui está um exemplo de saída:
<input name="ArchiveCode" type="hidden" value="00006365263145">
Em seguida, assegurei-me de adicionar o $UID ao bloco meta_data do cabeçalho X-MSYS-API. Esta etapa garante que o UID seja incorporado em cada saída de evento do 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>" } }
Agora temos uma maneira de vincular todos os dados do e-mail original ao corpo do e-mail de arquivamento.
Obtendo a versão do Arquivo
Para obter uma cópia de um email para arquivar, você precisa seguir os seguintes passos:
Crie um subdomínio para o qual você enviará todos os emails de arquivo (duplicados)
Defina os registros DNS apropriados para enviar todos os emails desse subdomínio para o SparkPost
Crie um domínio de entrada no SparkPost
Crie um webhook de entrada no SparkPost
Crie um aplicativo (coletor) para receber o fluxo de dados do webhook do SparkPost
Os seguintes dois links podem ser usados para ajudá-lo a passar por esse processo:
Documento técnico do SparkPost: Habilitando o Envio de Emails e Webhooks de Relay de Entrada
Além disso, o blog que escrevi no ano passado, Arquivando Emails: Um Guia Prático para Rastrear Emails Enviados irá guiá-lo na criação do relay de entrada dentro do SparkPost
* Observação: a partir de outubro de 2018, o recurso de Arquivo funciona apenas ao enviar emails usando uma conexão SMTP para o SparkPost, a API RESTful não dá suporte a esse recurso. Isso provavelmente não é um problema, pois a maioria dos emails que precisam desse nível de controle de auditoria tende a ser emails personalizados que são totalmente construídos por um aplicativo de backend antes que a entrega do email seja necessária.
Para obter uma cópia de um email para arquivar, você precisa seguir os seguintes passos:
Crie um subdomínio para o qual você enviará todos os emails de arquivo (duplicados)
Defina os registros DNS apropriados para enviar todos os emails desse subdomínio para o SparkPost
Crie um domínio de entrada no SparkPost
Crie um webhook de entrada no SparkPost
Crie um aplicativo (coletor) para receber o fluxo de dados do webhook do SparkPost
Os seguintes dois links podem ser usados para ajudá-lo a passar por esse processo:
Documento técnico do SparkPost: Habilitando o Envio de Emails e Webhooks de Relay de Entrada
Além disso, o blog que escrevi no ano passado, Arquivando Emails: Um Guia Prático para Rastrear Emails Enviados irá guiá-lo na criação do relay de entrada dentro do SparkPost
* Observação: a partir de outubro de 2018, o recurso de Arquivo funciona apenas ao enviar emails usando uma conexão SMTP para o SparkPost, a API RESTful não dá suporte a esse recurso. Isso provavelmente não é um problema, pois a maioria dos emails que precisam desse nível de controle de auditoria tende a ser emails personalizados que são totalmente construídos por um aplicativo de backend antes que a entrega do email seja necessária.
Para obter uma cópia de um email para arquivar, você precisa seguir os seguintes passos:
Crie um subdomínio para o qual você enviará todos os emails de arquivo (duplicados)
Defina os registros DNS apropriados para enviar todos os emails desse subdomínio para o SparkPost
Crie um domínio de entrada no SparkPost
Crie um webhook de entrada no SparkPost
Crie um aplicativo (coletor) para receber o fluxo de dados do webhook do SparkPost
Os seguintes dois links podem ser usados para ajudá-lo a passar por esse processo:
Documento técnico do SparkPost: Habilitando o Envio de Emails e Webhooks de Relay de Entrada
Além disso, o blog que escrevi no ano passado, Arquivando Emails: Um Guia Prático para Rastrear Emails Enviados irá guiá-lo na criação do relay de entrada dentro do SparkPost
* Observação: a partir de outubro de 2018, o recurso de Arquivo funciona apenas ao enviar emails usando uma conexão SMTP para o SparkPost, a API RESTful não dá suporte a esse recurso. Isso provavelmente não é um problema, pois a maioria dos emails que precisam desse nível de controle de auditoria tende a ser emails personalizados que são totalmente construídos por um aplicativo de backend antes que a entrega do email seja necessária.
Obtendo o e-mail duplicado em uma estrutura JSON
Na primeira fase deste projeto, tudo que estou armazenando é o formato de email rfc822 no S3 e alguns campos de descrição de alto nível em uma tabela SQL para pesquisa. Como o SparkPost enviará os dados do email em uma estrutura JSON para minha plataforma de arquivamento via fluxos de dados webhook, eu criei um aplicativo (frequentemente chamado de coletor) que aceita o fluxo de dados Relay_Webhook.
Cada pacote do Relay_Webhook do SparkPost conterá as informações de um email duplicado por vez, então dividir a estrutura JSON em componentes direcionados para este projeto é bastante simples. No meu código PHP, obter o email formatado em rfc822 era tão fácil quanto as seguintes poucas linhas de código:
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']; }
Algumas das informações que eu quero armazenar na minha tabela SQL residem em um array de campos de cabeçalho. Então eu escrevi uma pequena função que aceitou o array de cabeçalhos e percorreu o array para obter os dados que eu estava interessado em armazenar:
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; } } } }
Agora que tenho os dados, estou pronto para armazenar o corpo no S3.
Na primeira fase deste projeto, tudo que estou armazenando é o formato de email rfc822 no S3 e alguns campos de descrição de alto nível em uma tabela SQL para pesquisa. Como o SparkPost enviará os dados do email em uma estrutura JSON para minha plataforma de arquivamento via fluxos de dados webhook, eu criei um aplicativo (frequentemente chamado de coletor) que aceita o fluxo de dados Relay_Webhook.
Cada pacote do Relay_Webhook do SparkPost conterá as informações de um email duplicado por vez, então dividir a estrutura JSON em componentes direcionados para este projeto é bastante simples. No meu código PHP, obter o email formatado em rfc822 era tão fácil quanto as seguintes poucas linhas de código:
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']; }
Algumas das informações que eu quero armazenar na minha tabela SQL residem em um array de campos de cabeçalho. Então eu escrevi uma pequena função que aceitou o array de cabeçalhos e percorreu o array para obter os dados que eu estava interessado em armazenar:
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; } } } }
Agora que tenho os dados, estou pronto para armazenar o corpo no S3.
Na primeira fase deste projeto, tudo que estou armazenando é o formato de email rfc822 no S3 e alguns campos de descrição de alto nível em uma tabela SQL para pesquisa. Como o SparkPost enviará os dados do email em uma estrutura JSON para minha plataforma de arquivamento via fluxos de dados webhook, eu criei um aplicativo (frequentemente chamado de coletor) que aceita o fluxo de dados Relay_Webhook.
Cada pacote do Relay_Webhook do SparkPost conterá as informações de um email duplicado por vez, então dividir a estrutura JSON em componentes direcionados para este projeto é bastante simples. No meu código PHP, obter o email formatado em rfc822 era tão fácil quanto as seguintes poucas linhas de código:
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']; }
Algumas das informações que eu quero armazenar na minha tabela SQL residem em um array de campos de cabeçalho. Então eu escrevi uma pequena função que aceitou o array de cabeçalhos e percorreu o array para obter os dados que eu estava interessado em armazenar:
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; } } } }
Agora que tenho os dados, estou pronto para armazenar o corpo no S3.
Armazenando o e-mail duplicado no S3
Desculpe desapontá-lo, mas não vou dar um tutorial passo a passo sobre como criar um bucket S3 para armazenar o email, nem vou descrever como criar a chave de acesso necessária que você precisará em sua aplicação para fazer upload de conteúdo para o seu bucket; há tutoriais melhores sobre este assunto do que eu poderia escrever. Aqui estão alguns artigos que podem ajudar:
https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/
O que vou fazer é apontar algumas das configurações que escolhi que dizem respeito a um projeto como este.
Controle de Acesso. Você não só precisa definir a segurança do bucket, mas precisa definir as permissões para os itens em si. No meu projeto, uso uma política muito aberta de leitura pública porque os dados de amostra não são pessoais e eu queria acesso fácil aos dados. Você provavelmente quererá um conjunto de políticas de ACL muito mais rigoroso. Aqui está um bom artigo sobre configurações de ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Arquivando o Arquivo. No S3, há algo chamado Gerenciamento de Ciclo de Vida. Isso permite que você mova dados de um tipo de classe de armazenamento S3 para outra. As diferentes classes de armazenamento representam a quantidade de acesso que você precisa aos dados armazenados, com custos mais baixos associados ao armazenamento que você acessa menos. Um bom relatório sobre as diferentes classes e a transição entre elas pode ser encontrado em um guia da AWS chamado, Transição de Objetos. No meu caso, escolhi criar um ciclo de vida que movia cada objeto do Padrão para o Glacier após um ano. O acesso ao Glacier é muito mais barato do que o arquivo S3 padrão e me economizará dinheiro em custos de armazenamento.
Uma vez que eu tenha o bucket S3 criado e minhas configurações em ordem, o S3 está pronto para que eu faça upload do email compatível com rfc822 que obtive do fluxo de dados do Webhook do SparkPost Relay. Mas antes de fazer o upload da carga do email rfc822 para o S3, preciso criar um nome de arquivo único que usarei para armazenar esse email.
Para o nome de arquivo único, vou pesquisar o corpo do email pelo id oculto que a aplicação de envio colocou no email e usar esse id como o nome do arquivo. Existem maneiras mais elegantes de extrair o connectorId do corpo HTML, mas para simplicidade e clareza, vou usar o seguinte código:
$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); } } }
* estamos assumindo que $inputField contém o valor “ArchiveCode” e foi encontrado no meu arquivo config.php.
Com o UID, podemos então criar o nome do arquivo que será usado no S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Agora posso abrir minha conexão com o S3 e fazer o upload do arquivo. Se você olhar o arquivo s3.php no repositório do GitHub, verá que leva muito pouco código para fazer o upload do arquivo.
Meu último passo é registrar esta entrada na tabela MYSQL.
Desculpe desapontá-lo, mas não vou dar um tutorial passo a passo sobre como criar um bucket S3 para armazenar o email, nem vou descrever como criar a chave de acesso necessária que você precisará em sua aplicação para fazer upload de conteúdo para o seu bucket; há tutoriais melhores sobre este assunto do que eu poderia escrever. Aqui estão alguns artigos que podem ajudar:
https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/
O que vou fazer é apontar algumas das configurações que escolhi que dizem respeito a um projeto como este.
Controle de Acesso. Você não só precisa definir a segurança do bucket, mas precisa definir as permissões para os itens em si. No meu projeto, uso uma política muito aberta de leitura pública porque os dados de amostra não são pessoais e eu queria acesso fácil aos dados. Você provavelmente quererá um conjunto de políticas de ACL muito mais rigoroso. Aqui está um bom artigo sobre configurações de ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Arquivando o Arquivo. No S3, há algo chamado Gerenciamento de Ciclo de Vida. Isso permite que você mova dados de um tipo de classe de armazenamento S3 para outra. As diferentes classes de armazenamento representam a quantidade de acesso que você precisa aos dados armazenados, com custos mais baixos associados ao armazenamento que você acessa menos. Um bom relatório sobre as diferentes classes e a transição entre elas pode ser encontrado em um guia da AWS chamado, Transição de Objetos. No meu caso, escolhi criar um ciclo de vida que movia cada objeto do Padrão para o Glacier após um ano. O acesso ao Glacier é muito mais barato do que o arquivo S3 padrão e me economizará dinheiro em custos de armazenamento.
Uma vez que eu tenha o bucket S3 criado e minhas configurações em ordem, o S3 está pronto para que eu faça upload do email compatível com rfc822 que obtive do fluxo de dados do Webhook do SparkPost Relay. Mas antes de fazer o upload da carga do email rfc822 para o S3, preciso criar um nome de arquivo único que usarei para armazenar esse email.
Para o nome de arquivo único, vou pesquisar o corpo do email pelo id oculto que a aplicação de envio colocou no email e usar esse id como o nome do arquivo. Existem maneiras mais elegantes de extrair o connectorId do corpo HTML, mas para simplicidade e clareza, vou usar o seguinte código:
$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); } } }
* estamos assumindo que $inputField contém o valor “ArchiveCode” e foi encontrado no meu arquivo config.php.
Com o UID, podemos então criar o nome do arquivo que será usado no S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Agora posso abrir minha conexão com o S3 e fazer o upload do arquivo. Se você olhar o arquivo s3.php no repositório do GitHub, verá que leva muito pouco código para fazer o upload do arquivo.
Meu último passo é registrar esta entrada na tabela MYSQL.
Desculpe desapontá-lo, mas não vou dar um tutorial passo a passo sobre como criar um bucket S3 para armazenar o email, nem vou descrever como criar a chave de acesso necessária que você precisará em sua aplicação para fazer upload de conteúdo para o seu bucket; há tutoriais melhores sobre este assunto do que eu poderia escrever. Aqui estão alguns artigos que podem ajudar:
https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/
O que vou fazer é apontar algumas das configurações que escolhi que dizem respeito a um projeto como este.
Controle de Acesso. Você não só precisa definir a segurança do bucket, mas precisa definir as permissões para os itens em si. No meu projeto, uso uma política muito aberta de leitura pública porque os dados de amostra não são pessoais e eu queria acesso fácil aos dados. Você provavelmente quererá um conjunto de políticas de ACL muito mais rigoroso. Aqui está um bom artigo sobre configurações de ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Arquivando o Arquivo. No S3, há algo chamado Gerenciamento de Ciclo de Vida. Isso permite que você mova dados de um tipo de classe de armazenamento S3 para outra. As diferentes classes de armazenamento representam a quantidade de acesso que você precisa aos dados armazenados, com custos mais baixos associados ao armazenamento que você acessa menos. Um bom relatório sobre as diferentes classes e a transição entre elas pode ser encontrado em um guia da AWS chamado, Transição de Objetos. No meu caso, escolhi criar um ciclo de vida que movia cada objeto do Padrão para o Glacier após um ano. O acesso ao Glacier é muito mais barato do que o arquivo S3 padrão e me economizará dinheiro em custos de armazenamento.
Uma vez que eu tenha o bucket S3 criado e minhas configurações em ordem, o S3 está pronto para que eu faça upload do email compatível com rfc822 que obtive do fluxo de dados do Webhook do SparkPost Relay. Mas antes de fazer o upload da carga do email rfc822 para o S3, preciso criar um nome de arquivo único que usarei para armazenar esse email.
Para o nome de arquivo único, vou pesquisar o corpo do email pelo id oculto que a aplicação de envio colocou no email e usar esse id como o nome do arquivo. Existem maneiras mais elegantes de extrair o connectorId do corpo HTML, mas para simplicidade e clareza, vou usar o seguinte código:
$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); } } }
* estamos assumindo que $inputField contém o valor “ArchiveCode” e foi encontrado no meu arquivo config.php.
Com o UID, podemos então criar o nome do arquivo que será usado no S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Agora posso abrir minha conexão com o S3 e fazer o upload do arquivo. Se você olhar o arquivo s3.php no repositório do GitHub, verá que leva muito pouco código para fazer o upload do arquivo.
Meu último passo é registrar esta entrada na tabela MYSQL.
Armazenando os Metadados no MySQL
Coletamos todos os dados necessários em uma etapa anterior, então a etapa de armazenamento é fácil. Nesta primeira fase, escolhi construir uma tabela com os seguintes campos:
Campos de Metadados MySQL
Campo | Propósito |
Data/hora (auto) | Timestamp quando a entrada foi registrada |
Endereço RCPT_TO | Endereço de e-mail alvo para a mensagem arquivada |
Timestamp do cabeçalho DATE | Hora de envio do e-mail original |
Cabeçalho SUBJECT | Linha de assunto para indexação e pesquisa |
Cabeçalho FROM | Identificador do remetente para consulta |
Diretório S3 | Caminho do diretório dentro do bucket S3 |
Nome de arquivo S3 | Arquivo .eml único armazenado no S3 |
A função chamada MySQLLog dentro do arquivo da aplicação upload.php passa pelos passos necessários para abrir o link para o MySQL, inserir a nova linha, testar os resultados e fechar o link. Eu adiciono mais um passo para garantir que esses dados sejam registrados em um arquivo de texto. Devo fazer muito mais registros de erros? Sim. Mas eu quero manter este código leve para permitir que ele seja executado extremamente rápido. Às vezes, esse código será chamado centenas de vezes por minuto e precisa ser o mais eficiente possível. Em atualizações futuras, adicionarei um código auxiliar que processará falhas e enviará essas falhas para um administrador para monitoramento.
Coletamos todos os dados necessários em uma etapa anterior, então a etapa de armazenamento é fácil. Nesta primeira fase, escolhi construir uma tabela com os seguintes campos:
Campos de Metadados MySQL
Campo | Propósito |
Data/hora (auto) | Timestamp quando a entrada foi registrada |
Endereço RCPT_TO | Endereço de e-mail alvo para a mensagem arquivada |
Timestamp do cabeçalho DATE | Hora de envio do e-mail original |
Cabeçalho SUBJECT | Linha de assunto para indexação e pesquisa |
Cabeçalho FROM | Identificador do remetente para consulta |
Diretório S3 | Caminho do diretório dentro do bucket S3 |
Nome de arquivo S3 | Arquivo .eml único armazenado no S3 |
A função chamada MySQLLog dentro do arquivo da aplicação upload.php passa pelos passos necessários para abrir o link para o MySQL, inserir a nova linha, testar os resultados e fechar o link. Eu adiciono mais um passo para garantir que esses dados sejam registrados em um arquivo de texto. Devo fazer muito mais registros de erros? Sim. Mas eu quero manter este código leve para permitir que ele seja executado extremamente rápido. Às vezes, esse código será chamado centenas de vezes por minuto e precisa ser o mais eficiente possível. Em atualizações futuras, adicionarei um código auxiliar que processará falhas e enviará essas falhas para um administrador para monitoramento.
Coletamos todos os dados necessários em uma etapa anterior, então a etapa de armazenamento é fácil. Nesta primeira fase, escolhi construir uma tabela com os seguintes campos:
Campos de Metadados MySQL
Campo | Propósito |
Data/hora (auto) | Timestamp quando a entrada foi registrada |
Endereço RCPT_TO | Endereço de e-mail alvo para a mensagem arquivada |
Timestamp do cabeçalho DATE | Hora de envio do e-mail original |
Cabeçalho SUBJECT | Linha de assunto para indexação e pesquisa |
Cabeçalho FROM | Identificador do remetente para consulta |
Diretório S3 | Caminho do diretório dentro do bucket S3 |
Nome de arquivo S3 | Arquivo .eml único armazenado no S3 |
A função chamada MySQLLog dentro do arquivo da aplicação upload.php passa pelos passos necessários para abrir o link para o MySQL, inserir a nova linha, testar os resultados e fechar o link. Eu adiciono mais um passo para garantir que esses dados sejam registrados em um arquivo de texto. Devo fazer muito mais registros de erros? Sim. Mas eu quero manter este código leve para permitir que ele seja executado extremamente rápido. Às vezes, esse código será chamado centenas de vezes por minuto e precisa ser o mais eficiente possível. Em atualizações futuras, adicionarei um código auxiliar que processará falhas e enviará essas falhas para um administrador para monitoramento.
Concluindo
Então, em alguns passos bastante fáceis, conseguimos passar pela primeira fase de construção de um sistema robusto de arquivamento de e-mails que armazena o e-mail duplicado no S3 e faz a referência cruzada dos dados em uma tabela MySQL. Isso nos dará uma base para o restante do projeto que será abordado em várias postagens futuras.
Nas revisões futuras deste projeto, espero:
Armazenar todos os eventos de log do e-mail original
Enviar erros de armazenamento para um administrador quando ocorrer uma falha ao fazer upload ou registrar
Minimizar a complexidade do coletor.
Adicionar uma interface de usuário para visualizar todos os dados
Suportar a capacidade de reenvio do e-mail
Enquanto isso, espero que este projeto tenha sido interessante e útil para você; feliz envio.
Então, em alguns passos bastante fáceis, conseguimos passar pela primeira fase de construção de um sistema robusto de arquivamento de e-mails que armazena o e-mail duplicado no S3 e faz a referência cruzada dos dados em uma tabela MySQL. Isso nos dará uma base para o restante do projeto que será abordado em várias postagens futuras.
Nas revisões futuras deste projeto, espero:
Armazenar todos os eventos de log do e-mail original
Enviar erros de armazenamento para um administrador quando ocorrer uma falha ao fazer upload ou registrar
Minimizar a complexidade do coletor.
Adicionar uma interface de usuário para visualizar todos os dados
Suportar a capacidade de reenvio do e-mail
Enquanto isso, espero que este projeto tenha sido interessante e útil para você; feliz envio.
Então, em alguns passos bastante fáceis, conseguimos passar pela primeira fase de construção de um sistema robusto de arquivamento de e-mails que armazena o e-mail duplicado no S3 e faz a referência cruzada dos dados em uma tabela MySQL. Isso nos dará uma base para o restante do projeto que será abordado em várias postagens futuras.
Nas revisões futuras deste projeto, espero:
Armazenar todos os eventos de log do e-mail original
Enviar erros de armazenamento para um administrador quando ocorrer uma falha ao fazer upload ou registrar
Minimizar a complexidade do coletor.
Adicionar uma interface de usuário para visualizar todos os dados
Suportar a capacidade de reenvio do e-mail
Enquanto isso, espero que este projeto tenha sido interessante e útil para você; feliz envio.



