Correo Electrónico Resistente a la Computación Cuántica: Cómo usamos buzones SQLite cifrados para mantener seguro tu correo electrónico
Prólogo
Important
Nuestro servicio de correo electrónico es 100% de código abierto y enfocado en la privacidad mediante buzones SQLite seguros y cifrados.
Hasta que lanzamos el soporte IMAP, usábamos MongoDB para nuestras necesidades de almacenamiento persistente de datos.
Esta tecnología es increíble y todavía la usamos hoy en día, pero para tener cifrado en reposo con MongoDB necesitas usar un proveedor que ofrezca MongoDB Enterprise, como Digital Ocean o Mongo Atlas, o pagar una licencia empresarial (y posteriormente lidiar con la latencia del equipo de ventas).
Nuestro equipo en Forward Email necesitaba una solución de almacenamiento cifrada, escalable, confiable y amigable para desarrolladores para buzones IMAP. Como desarrolladores de código abierto, usar una tecnología que requiere pagar una licencia para obtener la función de cifrado en reposo iba en contra de nuestros principios, por lo que experimentamos, investigamos y desarrollamos una nueva solución desde cero para resolver estas necesidades.
En lugar de usar una base de datos compartida para almacenar tus buzones, almacenamos y ciframos individualmente tus buzones con tu contraseña (que solo tú tienes). Nuestro servicio de correo electrónico es tan seguro que si olvidas tu contraseña, pierdes tu buzón (y necesitas recuperarlo con copias de seguridad offline o empezar de nuevo).
Sigue leyendo mientras profundizamos a continuación con una comparación de proveedores de servicios de correo electrónico, cómo funciona nuestro servicio, nuestra pila tecnológica y más.
Comparación de proveedores de servicios de correo electrónico
Somos el único proveedor de servicios de correo electrónico 100% de código abierto y enfocado en la privacidad que almacena buzones SQLite cifrados individualmente, ofrece dominios, alias y usuarios ilimitados, y tiene soporte para SMTP saliente, IMAP y POP3:
A diferencia de otros proveedores de correo electrónico, no necesitas pagar por almacenamiento por dominio o alias con Forward Email. El almacenamiento se comparte en toda tu cuenta, así que si tienes múltiples nombres de dominio personalizados y múltiples alias en cada uno, somos la solución perfecta para ti. Ten en cuenta que aún puedes imponer límites de almacenamiento si lo deseas por dominio o alias.
Leer Comparación de Servicios de Correo
¿Cómo funciona?
-
Usando tu cliente de correo como Apple Mail, Thunderbird, Gmail o Outlook, te conectas a nuestros servidores seguros IMAP usando tu nombre de usuario y contraseña:
- Tu nombre de usuario es tu alias completo con tu dominio, como
hello@example.com. - Tu contraseña se genera aleatoriamente y solo se muestra durante 30 segundos cuando haces clic en Generar Contraseña desde Mi Cuenta Dominios Alias.
- Tu nombre de usuario es tu alias completo con tu dominio, como
-
Una vez conectado, tu cliente de correo enviará comandos del protocolo IMAP a nuestro servidor IMAP para mantener tu buzón sincronizado. Esto incluye escribir y almacenar correos electrónicos en borrador y otras acciones que puedas realizar (por ejemplo, etiquetar un correo como Importante o marcar un correo como Spam/Correo no deseado).
-
Los servidores de intercambio de correo (comúnmente conocidos como servidores "MX") reciben nuevos correos entrantes y los almacenan en tu buzón. Cuando esto sucede, tu cliente de correo será notificado y sincronizará tu buzón. Nuestros servidores de intercambio de correo pueden reenviar tu correo a uno o más destinatarios (incluyendo webhooks), almacenar tu correo para ti en tu almacenamiento IMAP cifrado con nosotros, ¡o ambos!
Tip
¿Interesado en aprender más? Lee cómo configurar el reenvío de correo, cómo funciona nuestro servicio de intercambio de correo, o consulta nuestras guías.
-
Detrás de escena, nuestro diseño seguro de almacenamiento de correo funciona de dos maneras para mantener tus buzones cifrados y accesibles solo por ti:
-
Cuando se recibe un correo nuevo para ti de un remitente, nuestros servidores de intercambio de correo escriben en un buzón individual, temporal y cifrado para ti.
-
Cuando te conectas a nuestro servidor IMAP con tu cliente de correo, tu contraseña se cifra en memoria y se usa para leer y escribir en tu buzón. Tu buzón solo puede ser leído y escrito con esta contraseña. Ten en cuenta que, dado que eres el único con esta contraseña, solo tú puedes leer y escribir en tu buzón cuando lo estás accediendo. La próxima vez que tu cliente de correo intente consultar correo o sincronizar, tus nuevos mensajes serán transferidos desde este buzón temporal y almacenados en tu archivo de buzón real usando la contraseña que proporcionaste. Ten en cuenta que este buzón temporal se purga y elimina después para que solo tu buzón protegido con contraseña tenga los mensajes.
-
Si estás conectado a IMAP (por ejemplo, usando un cliente de correo como Apple Mail o Thunderbird), entonces no necesitamos escribir en almacenamiento temporal en disco. En su lugar, se obtiene y usa tu contraseña IMAP cifrada en memoria. En tiempo real, cuando se intenta entregar un mensaje para ti, enviamos una solicitud WebSocket a todos los servidores IMAP preguntándoles si tienen una sesión activa para ti (esta es la parte de obtención), y luego se pasa esa contraseña cifrada en memoria – así que no necesitamos escribir en un buzón temporal, podemos escribir en tu buzón cifrado real usando tu contraseña cifrada.
-
-
Las copias de seguridad de tus buzones cifrados se realizan diariamente. También puedes solicitar una nueva copia de seguridad en cualquier momento o descargar la última copia desde Mi Cuenta Dominios Alias. Si decides cambiar a otro servicio de correo, entonces puedes migrar, descargar, exportar y purgar fácilmente tus buzones y copias de seguridad en cualquier momento.
Tecnologías
Bases de datos
Exploramos otras posibles capas de almacenamiento de bases de datos, sin embargo ninguna satisfizo nuestros requisitos tanto como SQLite:
| Base de datos | Cifrado en reposo | Buzones aislados | Licencia | Usado en todas partes |
|---|---|---|---|---|
| SQLite ⭐ | ✅ Sí con SQLite3MultipleCiphers | ✅ | ✅ Dominio Público | ✅ |
| MongoDB | ❌ "Disponible solo en MongoDB Enterprise" | ❌ Base de datos relacional | ❌ AGPL y SSPL-1.0 |
❌ |
| rqlite | ❌ Solo en red | ❌ Base de datos relacional | ✅ MIT |
❌ |
| dqlite | ❌ ¿No probado y aún no soportado? | ❌ ¿No probado y aún no soportado? | ✅ LGPL-3.0-only |
❌ |
| PostgreSQL | ✅ Sí | ❌ Base de datos relacional | ✅ PostgreSQL (similar a BSD o MIT) |
❌ |
| MariaDB | ✅ Solo para InnoDB | ❌ Base de datos relacional | ✅ GPLv2 y BUSL-1.1 |
❌ |
| CockroachDB | ❌ Función solo para Enterprise | ❌ Base de datos relacional | ❌ BUSL-1.1 y otros |
❌ |
Aquí hay un artículo de blog que compara varias opciones de almacenamiento de bases de datos SQLite en la tabla anterior.
Seguridad
En todo momento usamos cifrado en reposo (AES-256), cifrado en tránsito (TLS), DNS sobre HTTPS ("DoH") usando 🍊 Tangerine, y cifrado sqleet (ChaCha20-Poly1305) en los buzones. Además usamos autenticación de dos factores basada en tokens (en lugar de SMS, que es susceptible a ataques de intermediario), claves SSH rotativas con acceso root deshabilitado, acceso exclusivo a servidores mediante direcciones IP restringidas, y más. En caso de un ataque de mucama malvada o un empleado deshonesto de un proveedor externo, su buzón de correo solo puede abrirse con su contraseña generada. Tenga la seguridad de que no dependemos de ningún proveedor externo aparte de nuestros servidores con certificación SOC Tipo 2 de Cloudflare, DataPacket, Digital Ocean, GitHub y Vultr.
Nuestro objetivo es tener la menor cantidad posible de puntos únicos de fallo.
Buzones
resumen; Nuestros servidores IMAP usan bases de datos SQLite cifradas individualmente para cada uno de sus buzones.
SQLite es una base de datos embebida extremadamente popular: actualmente está funcionando en su teléfono y computadora, y es usada por casi todas las tecnologías principales.
Por ejemplo, en nuestros servidores cifrados hay una base de datos SQLite para el buzón linux@example.com, info@example.com, hello@example.com y así sucesivamente – una para cada uno como un archivo de base de datos .sqlite. Tampoco nombramos los archivos de base de datos con la dirección de correo electrónico – en su lugar usamos BSON ObjectID y UUID únicos generados que no revelan a quién pertenece el buzón ni cuál es la dirección de correo electrónico (por ejemplo, 353a03f21e534321f5d6e267.sqlite).
Cada una de estas bases de datos está cifrada usando su contraseña (que solo usted tiene) mediante sqleet (ChaCha20-Poly1305). Esto significa que sus buzones están cifrados individualmente, son autónomos, aislados y portátiles.
Hemos ajustado SQLite con el siguiente PRAGMA:
PRAGMA |
Propósito |
|---|---|
cipher=chacha20 |
Cifrado de base de datos SQLite ChaCha20-Poly1305. Consulte better-sqlite3-multiple-ciphers en Proyectos para más detalles. |
key="****************" |
Esta es su contraseña descifrada solo en memoria que se pasa a través de la conexión IMAP de su cliente de correo a nuestro servidor. Se crean y cierran nuevas instancias de base de datos para cada sesión de lectura y escritura (para asegurar aislamiento). |
journal_mode=WAL |
Write-ahead-log ("WAL") que mejora el rendimiento y permite acceso concurrente de lectura. |
busy_timeout=5000 |
Previene errores de bloqueo de escritura mientras se realizan otras escrituras. |
synchronous=NORMAL |
Incrementa la durabilidad de las transacciones sin riesgo de corrupción de datos. |
foreign_keys=ON |
Hace cumplir que las referencias de claves foráneas (por ejemplo, una relación de una tabla a otra) sean respetadas. Por defecto esto no está activado en SQLite, pero para validación e integridad de datos debe estar habilitado. |
encoding='UTF-8' |
Codificación predeterminada para usar y asegurar la coherencia del desarrollador. |
Todos los demás valores predeterminados son de SQLite según lo especificado en la documentación oficial de PRAGMA.
Concurrencia
resumen; Usamos
WebSocketpara lecturas y escrituras concurrentes en tus buzones de correo SQLite cifrados.
Lecturas
Tu cliente de correo en tu teléfono puede resolver imap.forwardemail.net a una de nuestras direcciones IP de Digital Ocean, y tu cliente de escritorio puede resolver una IP diferente de otro proveedor por completo.
Independientemente de a qué servidor IMAP se conecte tu cliente de correo, queremos que la conexión lea de tu base de datos en tiempo real con un 100% de precisión. Esto se hace a través de WebSockets.
Escrituras
Escribir en tu base de datos es un poco diferente, ya que SQLite es una base de datos embebida y tu buzón vive en un solo archivo por defecto.
Exploramos opciones como litestream, rqlite y dqlite a continuación, pero ninguna satisfizo nuestros requisitos.
Para realizar escrituras con el registro adelantado ("WAL") habilitado, necesitamos asegurar que solo un servidor ("Primario") sea responsable de hacerlo. WAL acelera drásticamente la concurrencia y permite un escritor y múltiples lectores.
El Primario se ejecuta en los servidores de datos con los volúmenes montados que contienen los buzones cifrados. Desde un punto de vista de distribución, puedes considerar que todos los servidores IMAP individuales detrás de imap.forwardemail.net son servidores secundarios ("Secundarios").
Logramos comunicación bidireccional con WebSockets:
- Los servidores primarios usan una instancia del servidor
WebSocketServerde ws. - Los servidores secundarios usan una instancia del cliente
WebSocketde ws que está envuelta con websocket-as-promised y reconnecting-websocket. Estos dos envoltorios aseguran que elWebSocketse reconecte y pueda enviar y recibir datos para escrituras específicas en la base de datos.
Copias de seguridad
resumen; Se hacen copias de seguridad diarias de tus buzones cifrados. También puedes solicitar instantáneamente una nueva copia de seguridad o descargar la última copia en cualquier momento desde Mi Cuenta Dominios Alias.
Para las copias de seguridad, simplemente ejecutamos el comando SQLite VACUUM INTO cada día durante el procesamiento de comandos IMAP, que aprovecha tu contraseña cifrada desde una conexión IMAP en memoria. Las copias se almacenan si no se detecta una copia existente o si el hash SHA-256 ha cambiado en el archivo en comparación con la copia más reciente.
Ten en cuenta que usamos el comando VACUUM INTO en lugar del comando incorporado backup porque si una página se modifica durante una operación de comando backup, entonces tiene que comenzar de nuevo. El comando VACUUM INTO tomará una instantánea. Consulta estos comentarios en GitHub y Hacker News para más información.
Además, usamos VACUUM INTO en lugar de backup, porque el comando backup dejaría la base de datos sin cifrar por un breve período hasta que se invoque rekey (consulta este comentario en GitHub para más detalles).
El Secundario instruirá al Primario a través de la conexión WebSocket para ejecutar la copia de seguridad, y el Primario recibirá el comando para hacerlo y posteriormente:
- Conectarse a tu buzón cifrado.
- Adquirir un bloqueo de escritura.
- Ejecutar un punto de control WAL mediante
wal_checkpoint(PASSIVE). - Ejecutar el comando SQLite
VACUUM INTO. - Asegurarse de que el archivo copiado pueda abrirse con la contraseña cifrada (medida de seguridad).
- Subirlo a Cloudflare R2 para almacenamiento (o a tu propio proveedor si está especificado).
Recuerda que tus buzones están cifrados – y aunque tenemos restricciones de IP y otras medidas de autenticación para la comunicación WebSocket – en caso de un actor malintencionado, puedes estar seguro de que a menos que la carga útil del WebSocket tenga tu contraseña IMAP, no podrá abrir tu base de datos.
Solo se almacena una copia de seguridad por buzón en este momento, pero en el futuro podríamos ofrecer recuperación en un punto en el tiempo ("PITR").
Búsqueda
Nuestros servidores IMAP soportan el comando SEARCH con consultas complejas, expresiones regulares y más.
El rendimiento rápido de búsqueda se debe a FTS5 y sqlite-regex.
Almacenamos valores Date en los buzones SQLite como cadenas ISO 8601 mediante Date.prototype.toISOString (con zona horaria UTC para que las comparaciones de igualdad funcionen correctamente).
También se almacenan índices para todas las propiedades que están en las consultas de búsqueda.
Proyectos
Aquí hay una tabla que describe los proyectos que usamos en nuestro código fuente y proceso de desarrollo (ordenados alfabéticamente):
| Proyecto | Propósito |
|---|---|
| Ansible | Plataforma de automatización DevOps para mantener, escalar y gestionar toda nuestra flota de servidores con facilidad. |
| Bree | Planificador de tareas para Node.js y JavaScript con soporte para cron, fechas, ms, later y amigable para humanos. |
| Cabin | Biblioteca de registro para JavaScript y Node.js amigable para desarrolladores con seguridad y privacidad en mente. |
| Lad | Framework de Node.js que impulsa toda nuestra arquitectura y diseño de ingeniería con MVC y más. |
| MongoDB | Solución de base de datos NoSQL que usamos para almacenar todos los demás datos fuera de los buzones (por ejemplo, tu cuenta, configuraciones, dominios y configuraciones de alias). |
| Mongoose | Modelado de documentos de objetos ("ODM") para MongoDB que usamos en toda nuestra pila. Escribimos ayudantes especiales que nos permiten simplemente continuar usando Mongoose con SQLite 🎉 |
| Node.js | Node.js es el entorno de ejecución de JavaScript multiplataforma y de código abierto que ejecuta todos nuestros procesos de servidor. |
| Nodemailer | Paquete de Node.js para enviar correos electrónicos, crear conexiones y más. Somos patrocinadores oficiales de este proyecto. |
| Redis | Base de datos en memoria para caché, canales de publicación/suscripción y solicitudes DNS sobre HTTPS. |
| SQLite3MultipleCiphers | Extensión de cifrado para SQLite que permite cifrar archivos completos de bases de datos (incluyendo el write-ahead-log ("WAL"), journal, rollback, …). |
| SQLiteStudio | Editor visual de SQLite (que también podrías usar) para probar, descargar y ver buzones de desarrollo. |
| SQLite | Capa de base de datos embebida para almacenamiento IMAP escalable, autónomo, rápido y resistente. |
| Spam Scanner | Herramienta anti-spam, filtrado de correo electrónico y prevención de phishing para Node.js (nuestra alternativa a Spam Assassin y rspamd). |
| Tangerine | Solicitudes DNS sobre HTTPS con Node.js y caché usando Redis – que asegura consistencia global y mucho más. |
| Thunderbird | Nuestro equipo de desarrollo usa esto (y también lo recomienda) como el cliente de correo preferido para usar con Forward Email. |
| UTM | Nuestro equipo de desarrollo usa esto para crear máquinas virtuales para iOS y macOS con el fin de probar diferentes clientes de correo (en paralelo) con nuestros servidores IMAP y SMTP. |
| Ubuntu | Sistema operativo moderno basado en Linux de código abierto que impulsa toda nuestra infraestructura. |
| WildDuck | Biblioteca de servidor IMAP – consulta sus notas sobre desduplicación de adjuntos y soporte del protocolo IMAP. |
| better-sqlite3-multiple-ciphers | Biblioteca API rápida y simple para Node.js para interactuar programáticamente con SQLite3. |
| email-templates | Framework de correo electrónico amigable para desarrolladores para crear, previsualizar y enviar correos personalizados (por ejemplo, notificaciones de cuenta y más). |
| json-sql-enhanced | Constructor de consultas SQL usando sintaxis estilo Mongo. Esto ahorra tiempo a nuestro equipo de desarrollo ya que podemos seguir escribiendo en estilo Mongo en toda la pila con un enfoque agnóstico a la base de datos. También ayuda a evitar ataques de inyección SQL usando parámetros en las consultas. |
| knex-schema-inspector | Utilidad SQL para extraer información sobre el esquema de base de datos existente. Esto nos permite validar fácilmente que todos los índices, tablas, columnas, restricciones y más son válidos y están 1:1 con cómo deberían ser. Incluso escribimos ayudantes automatizados para agregar nuevas columnas e índices si se hacen cambios en los esquemas de base de datos (con alertas de error extremadamente detalladas también). |
| knex | Constructor de consultas SQL que usamos solo para migraciones de base de datos y validación de esquemas a través de knex-schema-inspector. |
| mandarin | Traducción automática de frases i18n con soporte para Markdown usando Google Cloud Translation API. |
| mx-connect | Paquete de Node.js para resolver y establecer conexiones con servidores MX y manejar errores. |
| pm2 | Administrador de procesos de producción para Node.js con balanceador de carga incorporado (ajustado finamente para rendimiento). |
| smtp-server | Biblioteca de servidor SMTP – la usamos para nuestros servidores de intercambio de correo ("MX") y SMTP salientes. |
| ImapTest | Herramienta útil para probar servidores IMAP contra puntos de referencia y compatibilidad con la especificación RFC del protocolo IMAP. Este proyecto fue creado por el equipo de Dovecot (un servidor IMAP y POP3 de código abierto activo desde julio de 2002). Probamos extensamente nuestro servidor IMAP con esta herramienta. |
Puedes encontrar otros proyectos que usamos en nuestro código fuente en GitHub.
Proveedores
| Proveedor | Propósito |
|---|---|
| Cloudflare | Proveedor DNS, chequeos de salud, balanceadores de carga y almacenamiento de respaldo usando Cloudflare R2. |
| GitHub | Hospedaje de código fuente, CI/CD y gestión de proyectos. |
| Digital Ocean | Hospedaje de servidores dedicados y bases de datos gestionadas. |
| Vultr | Hospedaje de servidores dedicados. |
| DataPacket | Hospedaje de servidores dedicados. |
Reflexiones
Principios
Forward Email está diseñado según estos principios:
- Siempre ser amigable para desarrolladores, enfocado en seguridad y privacidad, y transparente.
- Adherirse a MVC, Unix, KISS, DRY, YAGNI, Twelve Factor, Navaja de Occam, y dogfooding
- Apuntar al desarrollador emprendedor, autofinanciado y rentable con ramen
Experimentos
resumen; En última instancia, usar almacenamiento de objetos compatible con S3 y/o Tablas Virtuales no es técnicamente factible por razones de rendimiento y es propenso a errores debido a limitaciones de memoria.
Hemos realizado algunos experimentos que nos llevaron a nuestra solución final con SQLite como se discutió arriba.
Uno de ellos fue intentar usar rclone y SQLite junto con una capa de almacenamiento compatible con S3.
Ese experimento nos llevó a entender y descubrir casos límite relacionados con rclone, SQLite y el uso de VFS:
- Si habilitas la bandera
--vfs-cache-mode writescon rclone, entonces las lecturas estarán bien, sin embargo las escrituras se almacenarán en caché.- Si tienes múltiples servidores IMAP distribuidos globalmente, entonces la caché estará desincronizada entre ellos a menos que tengas un único escritor y múltiples oyentes (por ejemplo, un enfoque pub/sub).
- Esto es increíblemente complejo y añadir cualquier complejidad adicional como esta resultará en más puntos únicos de fallo.
- Los proveedores de almacenamiento compatibles con S3 no soportan cambios parciales de archivos, lo que significa que cualquier cambio en el archivo
.sqliteresultará en un cambio completo y re-subida de la base de datos. - Existen otras soluciones como
rsync, pero no están enfocadas en el soporte de write-ahead-log ("WAL"), por lo que terminamos revisando Litestream. Afortunadamente, nuestro uso de cifrado ya cifra los archivos WAL para nosotros, por lo que no necesitamos depender de Litestream para eso. Sin embargo, aún no estábamos seguros de Litestream para uso en producción y tenemos algunas notas al respecto abajo. - Usar esta opción de
--vfs-cache-mode writes(la única forma de usar SQLite sobrerclonepara escrituras) intentará copiar toda la base de datos desde cero en memoria – manejar un buzón de 10 GB está bien, pero manejar múltiples buzones con almacenamiento extremadamente alto causará que los servidores IMAP tengan limitaciones de memoria y erroresENOMEM, fallos de segmentación y corrupción de datos.
- Si intentas usar las Tablas Virtuales de SQLite (por ejemplo usando s3db) para tener datos en vivo en una capa de almacenamiento compatible con S3, entonces te encontrarás con varios problemas más:
- Las lecturas y escrituras serán extremadamente lentas ya que los endpoints API de S3 deberán ser accedidos con métodos HTTP
GET,PUT,HEADyPOST. - Las pruebas de desarrollo mostraron que superar los 500K-1M+ registros con internet de fibra aún está limitado por el rendimiento de escritura y lectura a proveedores compatibles con S3. Por ejemplo, nuestros desarrolladores ejecutaron bucles
forpara hacer tanto sentencias SQLINSERTsecuenciales como escrituras masivas de grandes cantidades de datos. En ambos casos el rendimiento fue asombrosamente lento. - Las tablas virtuales no pueden tener índices, sentencias
ALTER TABLE, y otras limitaciones – lo que lleva a retrasos de 1-2 minutos o más dependiendo de la cantidad de datos. - Los objetos se almacenaban sin cifrar y no hay soporte nativo de cifrado disponible fácilmente.
- Las lecturas y escrituras serán extremadamente lentas ya que los endpoints API de S3 deberán ser accedidos con métodos HTTP
- También exploramos usar sqlite-s3vfs que es similar conceptual y técnicamente al punto anterior (por lo que tiene los mismos problemas). Una posibilidad sería usar una compilación personalizada de
sqlite3envuelta con cifrado como wxSQLite3 (que usamos actualmente en nuestra solución arriba) mediante editar el archivo de configuración. - Otro enfoque potencial era usar la extensión multiplex, sin embargo esto tiene una limitación de 32 GB y requeriría compilación compleja y dolores de cabeza en desarrollo.
- Se requieren sentencias
ALTER TABLE(por lo que esto descarta completamente usar Tablas Virtuales). Necesitamos sentenciasALTER TABLEpara que nuestro hook conknex-schema-inspectorfuncione correctamente – lo que asegura que los datos no se corrompan y las filas recuperadas puedan convertirse en documentos válidos según nuestras definiciones de esquemamongoose(que incluyen validación de restricciones, tipo de variable y validación arbitraria de datos). - Casi todos los proyectos compatibles con S3 relacionados con SQLite en la comunidad open-source están en Python (y no en JavaScript que usamos para el 100% de nuestra pila).
- Las librerías de compresión como sqlite-zstd (ver comentarios) parecen prometedoras, pero quizás aún no estén listas para uso en producción. En cambio, la compresión del lado de la aplicación en tipos de datos como
String,Object,Map,Array,SetyBufferserá un enfoque más limpio y fácil (y también más fácil de migrar, ya que podríamos almacenar una bandera o columnaBoolean– o incluso usarPRAGMAuser_version=1para compresión ouser_version=0para sin compresión como metadatos de la base de datos).- Afortunadamente ya tenemos implementada la desduplicación de adjuntos en el almacenamiento de nuestro servidor IMAP – por lo tanto cada mensaje con el mismo adjunto no mantiene una copia del adjunto – en cambio un solo adjunto se almacena para múltiples mensajes y hilos en un buzón (y se usa una referencia externa posteriormente).
- El proyecto Litestream, que es una solución de replicación y respaldo para SQLite, es muy prometedor y probablemente lo usaremos en el futuro.
- No para desacreditar al autor(es) – porque amamos su trabajo y contribuciones al open-source por más de una década – sin embargo por uso en el mundo real parece que puede haber muchos dolores de cabeza y pérdida potencial de datos por su uso.
- La restauración de respaldos debe ser sencilla y trivial. Usar una solución como MongoDB con
mongodumpymongoexportno solo es tedioso, sino que consume mucho tiempo y tiene complejidad de configuración.- Las bases de datos SQLite lo hacen simple (es un solo archivo).
- Queríamos diseñar una solución donde los usuarios pudieran tomar su buzón y marcharse en cualquier momento.
- Comandos simples de Node.js para
fs.unlink('mailbox.sqlite'))y se borra permanentemente del almacenamiento en disco. - Podemos usar de manera similar una API compatible con S3 con HTTP
DELETEpara eliminar fácilmente snapshots y respaldos para los usuarios.
- Comandos simples de Node.js para
- SQLite fue la solución más simple, rápida y rentable.
Falta de alternativas
Hasta donde sabemos, ningún otro servicio de correo electrónico está diseñado de esta manera ni es de código abierto.
Creemos que esto podría deberse a que los servicios de correo electrónico existentes tienen tecnología heredada en producción con código espagueti 🍝.
La mayoría, si no todos, los proveedores de servicios de correo electrónico existentes son o bien de código cerrado o se anuncian como de código abierto, pero en realidad solo su front-end es de código abierto.
La parte más sensible del correo electrónico (el almacenamiento real/interacción IMAP/SMTP) se realiza completamente en el back-end (servidor), y no en el front-end (cliente).
Prueba Forward Email
¡Regístrate hoy en https://forwardemail.net! 🚀