Caixas de correio SQLite criptografadas para sua privacidade
Ao contrário de outros serviços de e-mail , garantimos que apenas você tenha acesso à sua caixa de correio em todos os momentos.
- página de pesquisa
- Índice
Prefácio
tldr; Nosso serviço de e-mail é 100% código aberto e com foco na privacidade por meio de caixas de correio SQLite seguras e criptografadas.
Até lançarmos Suporte IMAP, usamos o MongoDB para nossas necessidades persistentes de armazenamento de dados.
Essa tecnologia é incrível e ainda a usamos hoje – mas para ter criptografia em repouso com o MongoDB você precisa usar um provedor que ofereça MongoDB Enterprise, como Digital Ocean ou Mongo Atlas – ou pagar por uma licença corporativa (e posteriormente terá que trabalhar com a latência da equipe de vendas).
Nossa equipe em Encaminhar email precisava de uma solução de armazenamento criptografada, escalável, confiável e amigável ao desenvolvedor para caixas de correio IMAP. Como desenvolvedores de código aberto, usar uma tecnologia que você precisa pagar uma taxa de licença para obter o recurso de criptografia em repouso era contra nossos princípios – e assim experimentamos, pesquisamos e desenvolvemos uma nova solução do zero para resolver essas necessidades.
Em vez de usar um banco de dados compartilhado para armazenar suas caixas de correio, armazenamos e criptografamos individualmente suas caixas de correio com sua senha (que só você possui). Nosso serviço de e-mail é tão seguro que se você esquecer sua senha, perderá sua caixa de correio (e precisa recuperar com backups offline ou recomeçar).
Continue lendo enquanto nos aprofundamos abaixo com um comparação de provedores de serviços de e-mail, Como nosso serviço funciona, nossa pilha de tecnologia, e mais.
Comparação de provedores de serviços de e-mail
Somos o único provedor de serviços de e-mail 100% de código aberto e focado na privacidade que armazena caixas de correio SQLite criptografadas individualmente, oferece domínios, aliases e usuários ilimitados e tem suporte de saída para SMTP, IMAP e POP3:
Ao contrário de outros provedores de e-mail, você não precisa pagar pelo armazenamento por domínio ou alias com o Forward Email. O armazenamento é compartilhado por toda a sua conta – portanto, se você tiver vários nomes de domínio personalizados e vários aliases em cada um, nós somos a solução perfeita para você. Observe que você ainda pode impor limites de armazenamento, se desejar, por domínio ou alias.
Leia a comparação de serviços de e-mail
Como funciona
-
Usando seu cliente de e-mail, como Apple Mail, Thunderbird, Gmail ou Outlook – você se conecta ao nosso seguro IMAP servidores usando seu nome de usuário e senha:
- Seu nome de usuário é o alias completo do seu domínio, como
hello@example.com
. - Sua senha é gerada aleatoriamente e exibida apenas por 30 segundos quando você clica Gerar senha de Minha conta Domínios Apelido.
- Seu nome de usuário é o alias completo do seu domínio, como
-
Uma vez conectado, seu cliente de e-mail enviará Comandos do protocolo IMAP ao nosso servidor IMAP para manter sua caixa de correio sincronizada. Isso inclui escrever e armazenar rascunhos de e-mails e outras ações que você pode realizar (por exemplo, rotular um e-mail como Importante ou sinalizar um e-mail como Spam/Lixo Eletrônico).
-
Os servidores de troca de correio (comumente conhecidos como servidores "MX") recebem novos e-mails de entrada e os armazenam em sua caixa de correio. Quando isso acontecer, seu cliente de e-mail será notificado e sincronizará sua caixa de correio. Nossos servidores de troca de e-mail podem encaminhar seu e-mail para um ou mais destinatários (incluindo webhooks), armazene seu e-mail em seu armazenamento IMAP criptografado conosco, ou ambos!
Interessado em aprender mais? Ler como configurar o encaminhamento de e-mail, como funciona nosso serviço de troca de correspondênciaou visualizar nossos guias.
-
Nos bastidores, nosso design seguro de armazenamento de e-mail funciona de duas maneiras para manter suas caixas de correio criptografadas e acessíveis apenas para você:
-
Quando novas mensagens são recebidas de um remetente, nossos servidores de troca de mensagens escrevem para você uma caixa de correio individual, temporária e criptografada.
sequenceDiagram autonumber actor Sender Sender->>MX: Inbound message received for your alias (e.g. you@yourdomain.com). MX->>SQLite: Message is stored in a temporary mailbox. Note over MX,SQLite: Forwards to other recipients and webhooks configured. MX->>Sender: Success!
-
Quando você se conecta ao nosso servidor IMAP com seu cliente de e-mail, sua senha é criptografada na memória e usada para ler e escrever em sua caixa de correio. Sua caixa de correio só pode ser lida e gravada com esta senha. Lembre-se de que, como você é o único com essa senha, só você pode ler e escrever em sua caixa de correio quando você a acessa. Na próxima vez que seu cliente de e-mail tentar pesquisar e-mails ou sincronizar, suas novas mensagens serão transferidas desta caixa de correio temporária e armazenadas em seu arquivo de caixa de correio real usando a senha fornecida. Observe que esta caixa de correio temporária é limpa e excluída posteriormente, para que apenas sua caixa de correio protegida por senha tenha as mensagens.
-
Se você estiver conectado ao IMAP (por exemplo, usando um cliente de e-mail como Apple Mail ou Thunderbird), não precisaremos gravar no armazenamento temporário em disco. Sua senha IMAP criptografada na memória é buscada e usada. Em tempo real, quando uma mensagem tenta ser entregue a você, enviamos uma solicitação WebSocket a todos os servidores IMAP perguntando se eles têm uma sessão ativa para você (esta é a parte de busca) e, posteriormente, repassaremos essa senha criptografada na memória – para que não precisemos escrever em uma caixa de correio temporária, podemos escrever em sua caixa de correio criptografada real usando sua senha criptografada.
sequenceDiagram autonumber actor You You->>IMAP: You connect to IMAP server using an email client. IMAP->>SQLite: Transfer message from temporary mailbox to your alias' mailbox. Note over IMAP,SQLite: Your alias' mailbox is only available in-memory using IMAP password. SQLite->>IMAP: Retrieves messages as requested by email client. IMAP->>You: Success!
-
-
Backups de suas caixas de correio criptografadas são feitos diariamente. Você também pode solicitar um novo backup a qualquer momento ou baixar o backup mais recente em Minha conta Domínios Apelido. Se decidir mudar para outro serviço de e-mail, você poderá migrar, baixar, exportar e limpar facilmente suas caixas de correio e backups a qualquer momento.
Tecnologias
Bancos de dados
Exploramos outras possíveis camadas de armazenamento de banco de dados, porém nenhuma atendeu tanto aos nossos requisitos quanto o SQLite:
Base de dados | Criptografia em repouso | Em área restrita Caixas de correio | Licença | Usado em todos os lugares |
---|---|---|---|---|
SQLite ⭐ | ✅ Sim com SQLite3MúltiplasCifras | ✅ | ✅ Domínio Público | ✅ |
MongoDB | ❌ "Disponível apenas no MongoDB Enterprise" | ❌ Banco de dados relacional | ❌ AGPL e SSPL-1.0 | ❌ |
rqlite | ❌ Somente rede | ❌ Banco de dados relacional | ✅ MIT | ❌ |
dqlite | ❌ Não testado e ainda sem suporte? | ❌ Não testado e ainda sem suporte? | ✅ LGPL-3.0-only | ❌ |
PostgreSQL | ✅ sim | ❌ Banco de dados relacional | ✅ PostgreSQL (igual a BSD ou MIT ) | ❌ |
Maria DB | ✅ Apenas para InnoDB | ❌ Banco de dados relacional | ✅ GPLv2 e BUSL-1.1 | ❌ |
BarataDB | ❌ Recurso exclusivo para empresas | ❌ Banco de dados relacional | ❌ BUSL-1.1 e outros | ❌ |
Aqui está um postagem no blog que compara várias opções de armazenamento de banco de dados SQLite na tabela acima.
Segurança
Em todos os momentos usamos criptografia em repouso (AES-256), criptografia em trânsito (TLS), DNS sobre HTTPS ("DoH") usando 🍊 tangerina, e sqleet (ChaCha20-Poly1305) criptografia em caixas de correio. Além disso, usamos autenticação de dois fatores baseada em token (em oposição ao SMS, que é suspeito de ataques man-in-the-middle), chaves SSH rotacionadas com acesso root desabilitado, acesso exclusivo a servidores por meio de endereços IP restritos e muito mais.
No caso de um ataque de empregada malvada ou funcionário desonesto de um fornecedor terceirizado, sua caixa de correio ainda só pode ser aberta com sua senha gerada. Fique tranquilo, não contamos com nenhum fornecedor terceirizado além de nossos fornecedores de servidores de reclamação SOC Tipo 2 da Cloudflare, Digital Ocean e Vultr.
Nosso objetivo é ter o mínimo ponto único de falhas que possível.
Caixas de correio
tldr; Nossos servidores IMAP usam bancos de dados SQLite criptografados individualmente para cada uma de suas caixas de correio.
SQLite é extremamente popular banco de dados incorporado – atualmente em execução no seu telefone e computador – e usado por quase todas as principais tecnologias.
Por exemplo, em nossos servidores criptografados existe uma caixa de correio de banco de dados SQLite para linux@example.com
, info@example.com
, hello@example.com
e assim por diante – um para cada como um .sqlite
arquivo de banco de dados. Também não nomeamos os arquivos de banco de dados com o endereço de e-mail - em vez disso, usamos BSON ObjectID e UUIDs exclusivos gerados que não compartilham a quem a caixa de correio pertence ou em qual endereço de e-mail ela está (por exemplo, 353a03f21e534321f5d6e267.sqlite
).
Cada um desses bancos de dados é criptografado usando sua senha (que só você tem) usando sqleet (ChaCha20-Poly1305). Isso significa que suas caixas de correio são criptografadas individualmente, independentes e em área restritae portátil.
Ajustamos o SQLite com o seguinte PRAGMA:
PRAGMA | Propósito |
---|---|
cipher=chacha20 | Criptografia de banco de dados SQLite ChaCha20-Poly1305. Referência better-sqlite3-multiple-ciphers sob Projetos para mais insights. |
key="****************" | Esta é a sua senha descriptografada apenas na memória, que é transmitida através da conexão IMAP do seu cliente de e-mail para o nosso servidor. Novas instâncias de banco de dados são criadas e fechadas para cada sessão de leitura e gravação (para garantir sandbox e isolamento). |
journal_model=WAL | Registro de gravação antecipada ("WAL") que aumenta o desempenho e permite acesso de leitura simultâneo. |
busy_timeout=5000 | Evita erros de bloqueio de gravação enquanto outras gravações estão ocorrendo. |
synchronous=NORMAL | Aumenta a durabilidade das transações sem risco de corrupção de dados. |
foreign_keys=ON | Impõe que as referências de chave estrangeira (por exemplo, uma relação de uma tabela para outra) sejam aplicadas. Por padrão, isso não está ativado no SQLite, mas para validação e integridade de dados ele deve estar habilitado. |
encoding='UTF-8' | Codificação padrão usar para garantir a sanidade do desenvolvedor. |
Todos os outros padrões são do SQLite conforme especificado no documentação oficial PRAGMA.
Simultaneidade
tldr; Nós usamos
WebSocket
para leituras e gravações simultâneas em suas caixas de correio SQLite criptografadas.
Lê
Seu cliente de e-mail no seu telefone pode resolver imap.forwardemail.net
para um de nossos endereços IP da Digital Ocean – e seu cliente de desktop pode resolver um IP separado de um diferente fornecedor completamente.
Independentemente do servidor IMAP ao qual seu cliente de e-mail se conecta, queremos que a conexão leia seu banco de dados em tempo real com 100% de precisão. Isso é feito através de WebSockets.
Escreve
Escrever em seu banco de dados é um pouco diferente – já que SQLite é um banco de dados incorporado e sua caixa de correio reside em um único arquivo por padrão.
Tínhamos explorado opções como litestream
, rqlite
, e dqlite
abaixo – no entanto, nenhum deles satisfez nossos requisitos.
Para realizar gravações com registro write-ahead ("WAL") habilitado – precisamos garantir que apenas um servidor ("Primário") seja responsável por fazer isso. WAL acelera drasticamente a simultaneidade e permite um escritor e vários leitores.
O Primário está em execução nos servidores de dados com os volumes montados contendo as caixas de correio criptografadas. Do ponto de vista da distribuição, você poderia considerar todos os servidores IMAP individuais por trás imap.forwardemail.net
ser servidores secundários (“Secundários”).
Realizamos comunicação bidirecional com WebSockets:
- Os servidores primários usam uma instância de esde
WebSocketServer
servidor. - Servidores secundários usam uma instância de esde
WebSocket
cliente que está envolvido com websocket conforme prometido e reconectando-websocket. Esses dois invólucros garantem que oWebSocket
reconecta e pode enviar e receber dados para gravações específicas do banco de dados.
Cópias de segurança
tldr; Os backups de suas caixas de correio criptografadas são feitos diariamente. Você também pode solicitar instantaneamente um novo backup ou baixar o backup mais recente a qualquer momento em Minha conta Domínios Apelido.
Para backups, simplesmente executamos o SQLite VACUUM INTO
comando todos os dias durante o processamento do comando IMAP, que aproveita sua senha criptografada de uma conexão IMAP na memória. Os backups são armazenados se nenhum backup existente for detectado ou se o SHA-256 hash mudou no arquivo em comparação com o backup mais recente.
Observe que usamos o VACUUM INTO
comando em oposição ao embutido backup
comando porque se uma página for modificada durante um backup
operação de comando, então ele tem que começar de novo. O VACUUM INTO
O comando tirará um instantâneo. Veja esses comentários em GitHub e Notícias sobre hackers para mais insights.
Além disso usamos VACUUM INTO
em oposição a backup
, porque o backup
comando deixaria o banco de dados sem criptografia por um breve período até rekey
é invocado (veja este GitHub Comente para obter insights).
O Secundário instruirá o Primário sobre o WebSocket
conexão para executar o backup – e o Primário receberá então o comando para fazê-lo e posteriormente:
- Conecte-se à sua caixa de correio criptografada.
- Adquira um bloqueio de gravação.
- Execute um ponto de verificação WAL via
wal_checkpoint(PASSIVE)
. - Execute o
VACUUM INTO
Comando SQLite. - Certifique-se de que o arquivo copiado possa ser aberto com a senha criptografada (salvaguarda/dummyproofing).
- Faça upload para Cloudflare R2 para armazenamento (ou para seu próprio provedor, se especificado).
Lembre-se de que suas caixas de correio são criptografadas – e embora tenhamos restrições de IP e outras medidas de autenticação em vigor para comunicação WebSocket – no caso de um malfeitor, você pode ter certeza de que, a menos que a carga útil do WebSocket tenha sua senha IMAP, ela não poderá abrir seu banco de dados .
No momento, apenas um backup é armazenado por caixa de correio, mas no futuro poderemos oferecer recuperação pontual ("PITR").
Procurar
Nossos servidores IMAP suportam o SEARCH
comando com consultas complexas, expressões regulares e muito mais.
O desempenho rápido da pesquisa se deve a FTS5 e sqlite-regex.
nós armazenamos Date
valores nas caixas de correio SQLite como ISO 8601 cordas via Date.prototype.toISOString (com fuso horário UTC para que as comparações de igualdade funcionem corretamente).
Os índices também são armazenados para todas as propriedades que estão nas consultas de pesquisa.
Projetos
Aqui está uma tabela que descreve os projetos que usamos em nosso código-fonte e processo de desenvolvimento (classificados em ordem alfabética):
Projeto | Propósito |
---|---|
Ansible | Plataforma de automação DevOps para manter, dimensionar e gerenciar toda a nossa frota de servidores com facilidade. |
Bree | Agendador de tarefas para Node.js e JavaScript com cron, datas, ms, posterior e suporte amigável. |
Cabine | Biblioteca de registro JavaScript e Node.js amigável ao desenvolvedor com segurança e privacidade em mente. |
Deixei | Estrutura Node.js que potencializa toda a nossa arquitetura e design de engenharia com MVC e muito mais. |
MongoDB | Solução de banco de dados NoSQL que usamos para armazenar todos os outros dados fora das caixas de correio (por exemplo, sua conta, configurações, domínios e configurações de alias). |
Mangusto | Modelagem de documento de objeto MongoDB ("ODM") que usamos em toda a nossa pilha. Escrevemos ajudantes especiais que nos permitem simplesmente continuar usando Mangusto com SQLite 🎉 |
Node.js | Node.js é o ambiente de tempo de execução JavaScript de plataforma cruzada e código aberto que executa todos os nossos processos de servidor. |
Nodemailer | Pacote Node.js para envio de e-mails, criação de conexões e muito mais. Somos patrocinadores oficiais deste projeto. |
Redis | Banco de dados na memória para armazenamento em cache, canais de publicação/assinatura e solicitações de DNS sobre HTTPS. |
SQLite3MúltiplasCifras | Extensão de criptografia para SQLite para permitir que arquivos inteiros do banco de dados sejam criptografados (incluindo o log write-ahead ("WAL"), diário, reversão, …). |
SQLiteStudio | Editor Visual SQLite (que você também pode usar) para testar, baixar e visualizar caixas de correio de desenvolvimento. |
SQLite | Camada de banco de dados incorporada para armazenamento IMAP escalonável, independente, rápido e resiliente. |
Verificador de spam | Ferramenta Node.js anti-spam, filtragem de e-mail e prevenção de phishing (nossa alternativa para Assassino de Spam e rspamd). |
tangerina | Solicitações de DNS sobre HTTPS com Node.js e cache usando Redis – o que garante consistência global e muito mais. |
Pássaro Trovão | Nossa equipe de desenvolvimento usa isso (e também recomenda) como o cliente de e-mail preferido para usar com Forward Email. |
UTM | Nossa equipe de desenvolvimento utiliza isso para criar máquinas virtuais para iOS e macOS para testar diferentes clientes de e-mail (em paralelo) com nossos servidores IMAP e SMTP. |
Ubuntu | Sistema operacional de servidor moderno baseado em Linux de código aberto que alimenta toda a nossa infraestrutura. |
Pato selvagem | Biblioteca do servidor IMAP – veja suas notas em desduplicação de anexo e Suporte ao protocolo IMAP. |
melhor-sqlite3-cifras múltiplas | Biblioteca API rápida e simples para Node.js interagir com SQLite3 programaticamente. |
modelos de e-mail | Estrutura de e-mail amigável ao desenvolvedor para criar, visualizar e enviar e-mails personalizados (por exemplo, notificações de conta e muito mais). |
json-sql | Construtor de consultas SQL usando sintaxe estilo Mongo. Isso economiza tempo da nossa equipe de desenvolvimento, pois podemos continuar escrevendo no estilo Mongo em toda a pilha com uma abordagem independente de banco de dados. Também ajuda a evitar ataques de injeção de SQL usando parâmetros de consulta. |
inspetor de esquema knex | Utilitário SQL para extrair informações sobre o esquema de banco de dados existente. Isso nos permite validar facilmente se todos os índices, tabelas, colunas, restrições e muito mais são válidos e estão 1:1 com como deveriam ser. Nós até escrevemos auxiliares automatizados para adicionar novas colunas e índices se forem feitas alterações nos esquemas do banco de dados (com alertas de erros extremamente detalhados também). |
knex | Construtor de consultas SQL que usamos apenas para migrações de banco de dados e validação de esquema por meio de knex-schema-inspector . |
mandarim | Automático i18n tradução de frases com suporte para Markdown usando API de tradução do Google Cloud. |
mx-conectar | Pacote Node.js para resolver e estabelecer conexões com servidores MX e lidar com erros. |
pm2 | Gerenciador de processo de produção Node.js com balanceador de carga integrado (ajustado para desempenho). |
servidor smtp | Biblioteca de servidores SMTP – usamos isso para nossos servidores de troca de correio ("MX") e servidores SMTP de saída. |
ImapTest | Ferramenta útil para testar servidores IMAP em relação a benchmarks e compatibilidade de protocolo IMAP com especificação RFC. Este projeto foi criado pela Pombal team (um servidor IMAP e POP3 de código aberto ativo desde julho de 2002). Testamos extensivamente nosso servidor IMAP com esta ferramenta. |
Você pode encontrar outros projetos que usamos em nosso código fonte no GitHub.
Provedores
Fornecedor | Propósito |
---|---|
nuvemflare | Provedor de DNS, verificações de integridade, balanceadores de carga e armazenamento de backup usando Cloudflare R2. |
Oceano Digital | Hospedagem de servidor dedicado, armazenamento em bloco SSD e bancos de dados gerenciados. |
Vultr | Hospedagem de servidor dedicado e armazenamento em bloco SSD. |
Pensamentos
Princípios
O encaminhamento de e-mail é projetado de acordo com estes princípios:
- Seja sempre amigável ao desenvolvedor, focado na segurança e na privacidade e transparente.
- Aderir a MVC, Unix, KISS, DRY, YAGNI, Doze Fatores, Navalha de Occam, e alimentação para cães
- Direcione o fragmentado, inicializado e ramen lucrativo desenvolvedor
Experimentos
tldr; Em última análise, o uso de armazenamento de objetos compatível com S3 e/ou tabelas virtuais não é tecnicamente viável por motivos de desempenho e está sujeito a erros devido a limitações de memória.
Fizemos alguns experimentos que levaram à nossa solução SQLite final, conforme discutido acima.
Uma delas foi tentar usar clone e SQLite junto com uma camada de armazenamento compatível com S3.
Esse experimento nos levou a entender melhor e descobrir casos extremos em torno de rclone, SQLite e VFS uso:
- Se você ativar
--vfs-cache-mode writes
sinalizar com rclone, então as leituras serão OK, porém as gravações serão armazenadas em cache.- Se você tiver vários servidores IMAP distribuídos globalmente, o cache estará desativado entre eles, a menos que você tenha um único gravador e vários ouvintes (por exemplo, uma abordagem pub/sub).
- Isso é incrivelmente complexo e adicionar qualquer complexidade adicional como essa resultará em mais pontos únicos de falha.
- Os provedores de armazenamento compatíveis com S3 não suportam alterações parciais de arquivos – o que significa qualquer alteração do
.sqlite
arquivo resultará em uma alteração completa e reenvio do banco de dados. - Outras soluções como
rsync
existem, mas eles não estão focados em write-ahead-log ("WAL") suporte – então acabamos analisando o Litestream. Felizmente, nosso uso de criptografia já criptografa o WAL arquivos para nós, então não precisamos depender do Litestream para isso. No entanto, ainda não estávamos confiantes no Litestream para uso em produção e temos algumas notas abaixo sobre isso. - Usando esta opção de
--vfs-cache-mode writes
(o apenas maneira de usar o SQLiterclone
para gravações) tentará copiar todo o banco de dados do zero na memória – lidar com uma caixa de correio de 10 GB é aceitável, no entanto, lidar com várias caixas de correio com armazenamento excessivamente alto fará com que os servidores IMAP tenham limitações de memória eENOMEM
erros, falhas de segmentação e corrupção de dados.
- Se você tentar usar SQLite Mesas Virtuais (por exemplo, usando s3db) para ter os dados ativos em uma camada de armazenamento compatível com S3, você enfrentará vários outros problemas:
- A leitura e a gravação serão extremamente lentas, pois os endpoints da API S3 precisarão ser atingidos com HTTP
GET
,PUT
,HEAD
, ePOST
métodos. - Os testes de desenvolvimento mostraram que exceder 500 mil a mais de 1 milhão de registros na Internet de fibra ainda é limitado pela taxa de transferência de gravação e leitura para provedores compatíveis com S3. Por exemplo, nossos desenvolvedores executaram
for
loops para fazer ambos SQL sequencialINSERT
declarações e aquelas que gravaram grandes quantidades de dados em massa. Em ambos os casos, o desempenho foi surpreendentemente lento. - Mesas virtuais não pode ter índices,
ALTER TABLE
declarações, e outro limitações – o que leva a atrasos de mais de 1-2 minutos ou mais, dependendo da quantidade de dados. - Os objetos foram armazenados sem criptografia e nenhum suporte de criptografia nativa está prontamente disponível.
- A leitura e a gravação serão extremamente lentas, pois os endpoints da API S3 precisarão ser atingidos com HTTP
- Também exploramos usando sqlite-s3vfs que é conceitual e tecnicamente semelhante ao ponto anterior (portanto, tem os mesmos problemas). Uma possibilidade seria usar um costume
sqlite3
compilação envolvida com criptografia, como wxSQLite3 (que usamos atualmente em nossa solução acima) por meio editando o arquivo de configuração. - Outra abordagem potencial seria usar o extensão multiplexada, no entanto, isso tem uma limitação de 32 GB e exigiria dores de cabeça complexas de construção e desenvolvimento.
ALTER TABLE
são necessárias (portanto, isso exclui completamente o uso de tabelas virtuais). Nós precisamosALTER TABLE
declarações para que nosso gancho comknex-schema-inspector
funcione corretamente – o que garante que os dados não sejam corrompidos e que as linhas recuperadas possam ser convertidas em documentos válidos de acordo com nossosmongoose
definições de esquema (que incluem restrição, tipo de variável e validação de dados arbitrária).- Quase todos os projetos compatíveis com S3 relacionados ao SQLite na comunidade de código aberto estão em Python (e não em JavaScript que usamos em 100% de nossa pilha).
- Bibliotecas de compactação como sqlite-zstd (ver comentários) parecem promissores, mas pode ainda não estar pronto para uso em produção. Em vez disso, compactação do lado do aplicativo em tipos de dados como
String
,Object
,Map
,Array
,Set
, eBuffer
será uma abordagem mais limpa e fácil (e também é mais fácil de migrar, já que poderíamos armazenar umBoolean
sinalizador ou coluna – ou até mesmo usarPRAGMA
user_version=1
para compressão ouuser_version=0
para nenhuma compactação como metadados do banco de dados).- Felizmente já temos a desduplicação de anexos implementada no armazenamento do nosso servidor IMAP – portanto, cada mensagem com o mesmo anexo não manterá uma cópia do anexo – em vez disso, um único anexo é armazenado para múltiplas mensagens e threads em uma caixa de correio (e um estrangeiro). referência é usada posteriormente).
- O projeto Litestream, que é uma solução de replicação e backup SQLite, é muito promissor e provavelmente o utilizaremos no futuro.
- Para não desacreditar o(s) autor(es) – porque amamos seu trabalho e contribuições para o código aberto há mais de uma década – no entanto, pelo uso no mundo real, parece que há pode ser muita dor de cabeça e potencial perda de dados devido ao uso.
- A restauração de backup precisa ser simples e trivial. Usando uma solução como MongoDB com
mongodump
emongoexport
não é apenas tedioso, mas também demorado e tem complexidade de configuração.- Os bancos de dados SQLite simplificam (é um único arquivo).
- Queríamos projetar uma solução onde os usuários pudessem pegar sua caixa de correio e sair a qualquer momento.
- Comandos simples do Node.js para
fs.unlink('mailbox.sqlite'))
e é permanentemente apagado do armazenamento em disco. - Da mesma forma, podemos usar uma API compatível com S3 com HTTP
DELETE
para remover facilmente instantâneos e backups dos usuários.
- Comandos simples do Node.js para
- SQLite foi a solução mais simples, rápida e econômica.
Falta de alternativas
Até onde sabemos, nenhum outro serviço de e-mail foi projetado dessa forma nem é de código aberto.
Nós acho que isso pode ser devido aos serviços de e-mail existentes com tecnologia legada em produção com código espaguete 🍝.
A maioria, senão todos, dos provedores de serviços de e-mail existentes são de código fechado ou anunciam como código aberto, mas na realidade apenas o seu front-end é de código aberto.
A parte mais sensível do e-mail (a interação real de armazenamento/IMAP/SMTP) tudo é feito no back-end (servidor) e não no front-end (cliente).
Experimente encaminhar e-mail
Inscreva-se hoje em https://forwardemail.net! 🚀