Boîtes aux lettres SQLite cryptées pour votre confidentialité

Contrairement à d'autres services de messagerie , nous veillons à ce que vous seul ayez accès à votre boîte mail à tout moment.

Avant-propos

tldr; Notre service de courrier électronique est 100% open source et axé sur la confidentialité grâce à des boîtes aux lettres SQLite sécurisées et cryptées.

Jusqu'à ce que nous lancions Prise en charge IMAP, nous avons utilisé MongoDB pour nos besoins de stockage de données persistants.

Cette technologie est incroyable et nous l'utilisons encore aujourd'hui – mais pour bénéficier du chiffrement au repos avec MongoDB, vous devez utiliser un fournisseur proposant MongoDB Enterprise, tel que Digital Ocean ou Mongo Atlas – ou payer pour une licence d'entreprise (et devoir ensuite travailler avec la latence de l'équipe commerciale).

Notre équipe à Un courriel transféré avait besoin d'une solution de stockage conviviale, évolutive, fiable et chiffrée pour les boîtes aux lettres IMAP. En tant que développeurs open source, l'utilisation d'une technologie qui nécessite de payer des frais de licence pour bénéficier de la fonctionnalité de chiffrement au repos était contre nos principes – et nous avons donc expérimenté, recherché et développé une nouvelle solution à partir de zéro pour répondre à ces besoins.

Au lieu d'utiliser une base de données partagée pour stocker vos boîtes aux lettres, nous stockons et chiffrons individuellement vos boîtes aux lettres avec votre mot de passe (que vous seul possédez). Notre service de messagerie est tellement sécurisé que si vous oubliez votre mot de passe, vous perdez votre boîte aux lettres (et vous devez récupérer avec des sauvegardes hors ligne ou recommencer).

Continuez à lire pendant que nous approfondissons ci-dessous avec un comparaison des fournisseurs de services de messagerie, comment fonctionne notre service, notre pile technologique, et plus.

Comparaison des fournisseurs de services de messagerie

Nous sommes le seul fournisseur de services de messagerie 100 % open source et axé sur la confidentialité qui stocke les boîtes aux lettres SQLite individuellement chiffrées, offre un nombre illimité de domaines, d'alias et d'utilisateurs et prend en charge les SMTP, IMAP et POP3 sortants :

Contrairement à d'autres fournisseurs de messagerie, vous n'avez pas besoin de payer pour le stockage par domaine ou par alias avec Forward Email. Le stockage est partagé sur l’ensemble de votre compte – donc si vous disposez de plusieurs noms de domaine personnalisés et de plusieurs alias sur chacun, alors nous sommes la solution parfaite pour vous. Notez que vous pouvez toujours appliquer des limites de stockage si vous le souhaitez, par domaine ou par alias.

Lire la comparaison des services de messagerie

Comment ça marche

  1. À l'aide de votre client de messagerie tel qu'Apple Mail, Thunderbird, Gmail ou Outlook, vous vous connectez à notre service sécurisé. IMAP serveurs en utilisant votre nom d'utilisateur et votre mot de passe :

    • Votre nom d'utilisateur est votre alias complet avec votre domaine tel que hello@example.com.
    • Votre mot de passe est généré aléatoirement et ne vous est affiché que pendant 30 secondes lorsque vous cliquez sur Créer un mot de passe depuis Mon compte Domaines Alias.
  2. Une fois connecté, votre client de messagerie enverra Commandes du protocole IMAP à notre serveur IMAP pour garder votre boîte aux lettres synchronisée. Cela inclut la rédaction et le stockage de brouillons d'e-mails et d'autres actions que vous pourriez effectuer (par exemple, étiqueter un e-mail comme important ou marquer un e-mail comme spam/courrier indésirable).

  3. Les serveurs d'échange de courrier (communément appelés serveurs « MX ») reçoivent les nouveaux e-mails entrants et les stockent dans votre boîte aux lettres. Lorsque cela se produit, votre client de messagerie sera averti et synchronisera votre boîte aux lettres. Nos serveurs d'échange de courrier peuvent transmettre votre courrier électronique à un ou plusieurs destinataires (notamment webhooks), stockez votre courrier électronique pour vous dans votre stockage IMAP crypté chez nous, ou les deux!

    Vous souhaitez en savoir plus ? Lire comment configurer le transfert d'e-mails, comment fonctionne notre service d'échange de courrier, ou voir nos guides.

  4. En coulisses, notre conception de stockage sécurisé des e-mails fonctionne de deux manières pour garder vos boîtes aux lettres cryptées et accessibles uniquement par vous :

    • Lorsqu'un nouveau courrier vous est envoyé par un expéditeur, nos serveurs d'échange de courrier écrivent pour vous dans une boîte aux lettres individuelle, temporaire et cryptée.

      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!
      
    • Lorsque vous vous connectez à notre serveur IMAP avec votre client de messagerie, votre mot de passe est ensuite crypté en mémoire et utilisé pour lire et écrire dans votre boîte mail. Votre boîte aux lettres ne peut être lue et écrite qu'avec ce mot de passe. Gardez à l'esprit que puisque vous êtes le seul à posséder ce mot de passe, seulement vous peut lire et écrire dans votre boîte aux lettres lorsque vous y accédez. La prochaine fois que votre client de messagerie tentera d'interroger du courrier ou de synchroniser, vos nouveaux messages seront transférés depuis cette boîte aux lettres temporaire et stockés dans votre fichier de boîte aux lettres actuel à l'aide du mot de passe que vous avez fourni. Notez que cette boîte aux lettres temporaire est purgée et supprimée par la suite afin que seule votre boîte aux lettres protégée par mot de passe contienne les messages.

    • Si vous êtes connecté à IMAP (par exemple en utilisant un client de messagerie tel qu'Apple Mail ou Thunderbird), nous n'avons pas besoin d'écrire sur un disque de stockage temporaire. Votre mot de passe IMAP crypté en mémoire est récupéré et utilisé. En temps réel, lorsqu'un message tente de vous être transmis, nous envoyons une requête WebSocket à tous les serveurs IMAP pour leur demander s'ils ont une session active pour vous (c'est la partie récupération), puis nous transmettons cela par la suite. mot de passe crypté en mémoire – nous n'avons donc pas besoin d'écrire dans une boîte aux lettres temporaire, nous pouvons écrire dans votre boîte aux lettres cryptée réelle en utilisant votre mot de passe crypté.

      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!
      
  5. Sauvegardes de vos boîtes mail cryptées sont réalisés quotidiennement. Vous pouvez également demander une nouvelle sauvegarde à tout moment ou télécharger la dernière sauvegarde depuis Mon compte Domaines Alias. Si vous décidez de passer à un autre service de messagerie, vous pouvez facilement migrer, télécharger, exporter et purger vos boîtes aux lettres et sauvegardes à tout moment.

Les technologies

Bases de données

Nous avons exploré d'autres couches de stockage de base de données possibles, mais aucune ne répondait autant à nos exigences que SQLite :

Base de donnéesChiffrement au reposEn bac à sable Boîtes aux lettresLicenceUtilisé partout
SQLite✅ Oui avec SQLite3MultipleCiphers✅ Domaine public
MongoDB"Disponible uniquement dans MongoDB Enterprise"❌ Base de données relationnelle❌AGPL et SSPL-1.0
rqliteRéseau uniquement❌ Base de données relationnelleMIT
dqliteNon testé et pas encore pris en charge ?Non testé et pas encore pris en charge ?LGPL-3.0-only
PostgreSQLOui❌ Base de données relationnellePostgreSQL (semblable à BSD ou MIT)
MariaDBPour InnoDB uniquement❌ Base de données relationnelleGPLv2 et BUSL-1.1
CafardDBFonctionnalité réservée aux entreprises❌ Base de données relationnelleBUSL-1.1 et d'autres

Voici une article de blog qui compare plusieurs options de stockage de base de données SQLite dans le tableau ci-dessus.

Sécurité

À tout moment, nous utilisons chiffrement au repos (AES-256), chiffrement en transit (TLS), DNS sur HTTPS ("DoH") en utilisant 🍊 Tangerine, et grésil (ChaCha20-Poly1305) cryptage sur les boîtes mail. De plus, nous utilisons une authentification à deux facteurs basée sur des jetons (par opposition aux SMS qui peuvent être suspectés). attaques de l'homme du milieu), clés SSH alternées avec accès root désactivé, accès exclusif aux serveurs via des adresses IP restreintes, et bien plus encore.

En cas de attaque de femme de chambre maléfique ou un employé malveillant d'un fournisseur tiers, votre boîte mail ne peut toujours être ouverte qu'avec votre mot de passe généré. Rassurez-vous, nous ne dépendons d'aucun fournisseur tiers autre que nos fournisseurs de serveurs de réclamation SOC Type 2 de Cloudflare, Digital Ocean et Vultr.

Notre objectif est d'avoir le moins point unique de défaillance que possible.

Boîtes aux lettres

tldr; Nos serveurs IMAP utilisent des bases de données SQLite cryptées individuellement pour chacune de vos boîtes mail.

SQLite est un logiciel extrêmement populaire base de données intégrée – elle fonctionne actuellement sur votre téléphone et votre ordinateur – et utilisé par presque toutes les principales technologies.

Par exemple, sur nos serveurs chiffrés, il existe une boîte aux lettres de base de données SQLite pour linux@example.com, info@example.com, hello@example.com et ainsi de suite – un pour chacun comme .sqlite fichier de base de données. Nous ne nommons pas non plus les fichiers de base de données avec l'adresse e-mail - à la place, nous utilisons BSON ObjectID et les UUID uniques générés qui ne révèlent pas à qui appartient la boîte aux lettres ni à quelle adresse e-mail elle se trouve (par ex. 353a03f21e534321f5d6e267.sqlite).

Chacune de ces bases de données est elle-même cryptée à l'aide de votre mot de passe (que vous seul possédez) à l'aide de grésil (ChaCha20-Poly1305). Cela signifie que vos boîtes aux lettres sont cryptées individuellement, autonomes, en bac à sable, et portable.

Nous avons affiné SQLite avec ce qui suit PRAGMA:

PRAGMABut
cipher=chacha20ChaCha20-Poly1305 Chiffrement de base de données SQLite. Référence better-sqlite3-multiple-ciphers sous Projets pour plus d'informations.
key="****************"Il s'agit de votre mot de passe déchiffré en mémoire uniquement qui est transmis via la connexion IMAP de votre client de messagerie à notre serveur. De nouvelles instances de base de données sont créées et fermées pour chaque session de lecture et d'écriture (afin de garantir le sandboxing et l'isolation).
journal_model=WALJournal à écriture anticipée ("WAL") ce qui améliore les performances et permet un accès en lecture simultané.
busy_timeout=5000Empêche les erreurs de verrouillage en écriture pendant que d'autres écritures ont lieu.
synchronous=NORMALAugmente la durabilité des transactions sans risque de corruption des données.
foreign_keys=ONImpose que les références de clé étrangère (par exemple, une relation d'une table à une autre) soient appliquées. Par défaut, ceci n'est pas activé dans SQLite, mais pour la validation et l'intégrité des données, il doit être activé.
encoding='UTF-8'Encodage par défaut à utiliser pour garantir la santé mentale du développeur.

Toutes les autres valeurs par défaut proviennent de SQLite, comme spécifié dans le documentation officielle PRAGMA.

Concurrence

tldr; Nous utilisons WebSocket pour les lectures et écritures simultanées dans vos boîtes aux lettres SQLite chiffrées.

Lit

Votre client de messagerie sur votre téléphone peut résoudre imap.forwardemail.net à l’une de nos adresses IP Digital Ocean – et votre client de bureau peut résoudre une adresse IP distincte à partir d’une autre fournisseur tout à fait.

Quel que soit le serveur IMAP auquel votre client de messagerie se connecte, nous souhaitons que la connexion lise votre base de données en temps réel avec une précision de 100 %. Cela se fait via WebSockets.

Écrit

L'écriture dans votre base de données est un peu différente, puisque SQLite est une base de données intégrée et que votre boîte aux lettres réside par défaut dans un seul fichier.

Nous avions exploré des options telles que litestream, rqlite, et dqlite ci-dessous – mais aucun d’entre eux ne répondait à nos exigences.

Pour réaliser des écritures avec journalisation en écriture anticipée ("WAL") activé – nous devons nous assurer qu'un seul serveur ("Primaire") est responsable de cela. WAL accélère considérablement la concurrence et permet à un seul rédacteur et à plusieurs lecteurs.

Le primaire s'exécute sur les serveurs de données avec les volumes montés contenant les boîtes aux lettres chiffrées. Du point de vue de la distribution, vous pouvez considérer tous les serveurs IMAP individuels derrière imap.forwardemail.net être des serveurs secondaires ("Secondaire").

Nous réalisons une communication bidirectionnelle avec WebSockets:

  • Les serveurs principaux utilisent une instance de wsc'est WebSocketServer serveur.
  • Les serveurs secondaires utilisent une instance de wsc'est WebSocket client qui est enveloppé avec websocket-comme-promis et reconnexion-websocket. Ces deux enveloppes garantissent que le WebSocket se reconnecte et peut envoyer et recevoir des données pour des écritures de base de données spécifiques.

Sauvegardes

tldr; Des sauvegardes de vos boîtes mail cryptées sont effectuées quotidiennement. Vous pouvez également demander instantanément une nouvelle sauvegarde ou télécharger la dernière sauvegarde à tout moment depuis Mon compte Domaines Alias.

Pour les sauvegardes, nous exécutons simplement SQLite VACUUM INTO commande tous les jours pendant le traitement des commandes IMAP, qui exploite votre mot de passe crypté à partir d’une connexion IMAP en mémoire. Les sauvegardes sont stockées si aucune sauvegarde existante n'est détectée ou si le SHA-256 le hachage a changé sur le fichier par rapport à la sauvegarde la plus récente.

Notez que nous utilisons le VACUUM INTO commande par opposition à la commande intégrée backup commande car si une page est modifiée lors d'une backup opération de commande, alors il doit recommencer. Le VACUUM INTO La commande prendra un instantané. Voir ces commentaires sur GitHub et Actualités des pirates pour plus d'informations.

De plus, nous utilisons VACUUM INTO par opposition à backup, parce que le backup La commande laisserait la base de données non chiffrée pendant une brève période jusqu'à ce que rekey est invoqué (voir ce GitHub commentaire pour un aperçu).

Le Secondaire instruira le Primaire au cours de la WebSocket connexion pour exécuter la sauvegarde – et le Primaire recevra alors la commande pour le faire et :

  1. Connectez-vous à votre boîte mail cryptée.
  2. Obtenez un verrou en écriture.
  3. Exécutez un point de contrôle WAL via wal_checkpoint(PASSIVE).
  4. Exécutez le VACUUM INTO Commande SQLite.
  5. Assurez-vous que le fichier copié peut être ouvert avec le mot de passe crypté (sauvegarde/dummyproofing).
  6. Téléchargez-le sur Cloudflare R2 pour le stockage (ou sur votre propre fournisseur si spécifié).

N'oubliez pas que vos boîtes aux lettres sont cryptées – et même si nous avons mis en place des restrictions IP et d'autres mesures d'authentification pour les communications WebSocket – en cas d'acteur malveillant, vous pouvez être assuré qu'à moins que la charge utile WebSocket ne dispose de votre mot de passe IMAP, elle ne peut pas ouvrir votre base de données. .

Une seule sauvegarde est stockée par boîte aux lettres pour le moment, mais à l'avenir, nous pourrons proposer une récupération à un moment précis ("PITR").

Nos serveurs IMAP prennent en charge le SEARCH commande avec des requêtes complexes, des expressions régulières, etc.

Les performances de recherche rapides sont dues à FTS5 et sqlite-regex.

Nous stockons Date valeurs dans les boîtes aux lettres SQLite comme ISO 8601 cordes via Date.prototype.toISOString (avec fuseau horaire UTC pour que les comparaisons d'égalité fonctionnent correctement).

Des index sont également stockés pour toutes les propriétés figurant dans les requêtes de recherche.

Projets

Voici un tableau décrivant les projets que nous utilisons dans notre code source et notre processus de développement (triés par ordre alphabétique) :

ProjetBut
AnsiblePlateforme d'automatisation DevOps pour maintenir, faire évoluer et gérer facilement l'ensemble de notre flotte de serveurs.
BréePlanificateur de tâches pour Node.js et JavaScript avec cron, dates, ms, versions ultérieures et prise en charge conviviale.
CabineBibliothèque de journalisation JavaScript et Node.js conviviale pour les développeurs, avec à l'esprit la sécurité et la confidentialité.
GarçonFramework Node.js qui alimente l'ensemble de notre architecture et de notre conception technique avec MVC et plus encore.
MongoDBSolution de base de données NoSQL que nous utilisons pour stocker toutes les autres données en dehors des boîtes aux lettres (par exemple votre compte, vos paramètres, vos domaines et vos configurations d'alias).
MangousteModélisation de documents objets MongoDB (« ODM ») que nous utilisons sur l'ensemble de notre pile. Nous avons écrit des aides spéciales qui nous permettent de continuer simplement à utiliser Mangouste avec SQLite 🎉
Node.jsNode.js est l'environnement d'exécution JavaScript multiplateforme open source qui exécute tous nos processus serveur.
Envoyeur de notesPackage Node.js pour envoyer des e-mails, créer des connexions, etc. Nous sommes sponsor officiel de ce projet.
RédisBase de données en mémoire pour la mise en cache, les canaux de publication/abonnement et les requêtes DNS sur HTTPS.
SQLite3MultipleCiphersExtension de chiffrement pour SQLite permettant de chiffrer des fichiers de base de données entiers (y compris le journal à écriture anticipée ("WAL"), journal, rollback, …).
SQLiteStudioÉditeur Visual SQLite (que vous pouvez également utiliser) pour tester, télécharger et afficher les boîtes aux lettres de développement.
SQLiteCouche de base de données intégrée pour un stockage IMAP évolutif, autonome, rapide et résilient.
Scanner de courrier indésirableOutil anti-spam, de filtrage des e-mails et de prévention du phishing Node.js (notre alternative à Assassin de spam et spamd).
TangerineRequêtes DNS sur HTTPS avec Node.js et mise en cache à l'aide de Redis – ce qui garantit une cohérence globale et bien plus encore.
Oiseau-tonnerreNotre équipe de développement l'utilise (et le recommande également) comme le client de messagerie préféré à utiliser avec Forward Email.
UTMNotre équipe de développement utilise cette création de machines virtuelles pour iOS et macOS afin de tester différents clients de messagerie (en parallèle) avec nos serveurs IMAP et SMTP.
UbuntuSystème d'exploitation de serveur open source moderne basé sur Linux qui alimente toute notre infrastructure.
Canard sauvageBibliothèque du serveur IMAP – voir ses notes sur déduplication des pièces jointes et Prise en charge du protocole IMAP.
meilleurs-sqlite3-chiffres-multiplesBibliothèque API rapide et simple permettant à Node.js d'interagir avec SQLite3 par programmation.
modèles d'e-mailsCadre de messagerie convivial pour les développeurs pour créer, prévisualiser et envoyer des e-mails personnalisés (par exemple, notifications de compte et plus encore).
json-sqlGénérateur de requêtes SQL utilisant la syntaxe de style Mongo. Cela fait gagner du temps à notre équipe de développement puisque nous pouvons continuer à écrire dans le style Mongo sur l'ensemble de la pile avec une approche indépendante de la base de données. Cela permet également d'éviter les attaques par injection SQL en utilisant des paramètres de requête.
knex-schema-inspecteurUtilitaire SQL pour extraire des informations sur le schéma de base de données existant. Cela nous permet de valider facilement que tous les indices, tables, colonnes, contraintes, etc. sont valides et sont 1:1 avec comment ils devraient être. Nous avons même écrit des assistants automatisés pour ajouter de nouvelles colonnes et index si des modifications sont apportées aux schémas de base de données (avec également des alertes d'erreur extrêmement détaillées).
knexGénérateur de requêtes SQL que nous utilisons uniquement pour les migrations de bases de données et la validation de schéma via knex-schema-inspector.
mandarinAutomatique i18n traduction de phrases avec prise en charge de Markdown en utilisant API de traduction Google Cloud.
mx-connecterPackage Node.js pour résoudre et établir des connexions avec les serveurs MX et gérer les erreurs.
pm2Gestionnaire de processus de production Node.js avec équilibreur de charge intégré (affiné pour les performances).
serveur smtpBibliothèque de serveur SMTP – nous l'utilisons pour nos serveurs d'échange de courrier (« MX ») et SMTP sortants.
Test ImapOutil utile pour tester les serveurs IMAP par rapport aux benchmarks et à la compatibilité du protocole IMAP des spécifications RFC. Ce projet a été créé par le Pigeonnier team (un serveur open source actif IMAP et POP3 de juillet 2002). Nous avons largement testé notre serveur IMAP avec cet outil.

Vous pouvez trouver d'autres projets que nous utilisons dans notre code source sur GitHub.

Fournisseurs

FournisseurBut
Flare nuageuseFournisseur DNS, vérifications de l'état, équilibreurs de charge et stockage de sauvegarde utilisant Cloudflare R2.
Océan numériqueHébergement de serveur dédié, stockage en bloc SSD et bases de données gérées.
VultrHébergement sur serveur dédié et stockage en bloc SSD.

Pensées

Des principes

Forward Email est conçu selon ces principes :

  1. Soyez toujours convivial pour les développeurs, axé sur la sécurité et la confidentialité, et transparent.
  2. Adhérer à MVC, Unix, KISS, DRY, YAGNI, Douze facteurs, le rasoir d'Occam, et nourriture pour chiens
  3. Ciblez les utilisateurs décousus, amorcés et ramen-rentable développeur

Expériences

tldr; En fin de compte, l'utilisation du stockage d'objets compatible S3 et/ou des tables virtuelles n'est pas techniquement réalisable pour des raisons de performances et est sujette à des erreurs en raison des limitations de mémoire.

Nous avons effectué quelques expériences menant à notre solution SQLite finale, comme indiqué ci-dessus.

L'une d'entre elles consistait à essayer d'utiliser rclone et SQLite avec une couche de stockage compatible S3.

Cette expérience nous a amené à mieux comprendre et à découvrir des cas extrêmes autour de rclone, SQLite et VFS usage:

  • Si vous activez --vfs-cache-mode writes flag avec rclone, alors les lectures seront OK, mais les écritures seront mises en cache.
    • Si vous disposez de plusieurs serveurs IMAP répartis dans le monde, le cache sera désactivé sur chacun d'eux, sauf si vous disposez d'un seul rédacteur et de plusieurs écouteurs (par exemple, une approche pub/sub).
    • C'est incroyablement complexe et l'ajout de toute complexité supplémentaire comme celle-ci entraînera davantage de points de défaillance uniques.
    • Les fournisseurs de stockage compatibles S3 ne prennent pas en charge les modifications partielles de fichiers, ce qui signifie toute modification du fichier. .sqlite Le fichier entraînera une modification complète et un nouveau téléchargement de la base de données.
    • D'autres solutions comme rsync existent, mais ils ne sont pas axés sur le journal à écriture anticipée ("WAL") support – nous avons donc fini par examiner Litestream. Heureusement, notre utilisation du cryptage crypte déjà le WAL fichiers pour nous, nous n'avons donc pas besoin de compter sur Litestream pour cela. Cependant, nous n'avions pas encore confiance dans Litestream pour une utilisation en production et nous avons quelques notes ci-dessous à ce sujet.
    • En utilisant cette option de --vfs-cache-mode writes (le seulement façon d'utiliser SQLite sur rclone pour les écritures) tentera de copier l'intégralité de la base de données à partir de zéro en mémoire - la gestion d'une boîte aux lettres de 10 Go est acceptable, mais la gestion de plusieurs boîtes aux lettres avec un stockage extrêmement élevé entraînera des limitations de mémoire sur les serveurs IMAP et ENOMEM erreurs, erreurs de segmentation et corruption des données.
  • Si vous essayez d'utiliser SQLite Tables virtuelles (par exemple en utilisant s3db) afin de conserver les données sur une couche de stockage compatible S3, vous rencontrerez plusieurs autres problèmes :
    • La lecture et l'écriture seront extrêmement lentes car les points de terminaison de l'API S3 devront être atteints avec HTTP GET, PUT, HEAD, et POST méthodes.
    • Les tests de développement ont montré que le dépassement de 500 000 à plus d'un million d'enregistrements sur Internet par fibre optique est toujours limité par le débit d'écriture et de lecture vers les fournisseurs compatibles S3. Par exemple, nos développeurs ont exécuté for boucles pour faire à la fois du SQL séquentiel INSERT déclarations et celles qui écrivent en masse de grandes quantités de données. Dans les deux cas, la performance a été incroyablement lente.
    • Tables virtuelles ne peut pas avoir d'index, ALTER TABLE déclarations, et autre limites – ce qui entraîne des retards de plus de 1 à 2 minutes ou plus selon la quantité de données.
    • Les objets ont été stockés non chiffrés et aucune prise en charge de chiffrement natif n’est disponible.
  • Nous avons également exploré l'utilisation sqlite-s3vfs qui est similaire conceptuellement et techniquement au point précédent (il présente donc les mêmes problèmes). Une possibilité serait d'utiliser un personnalisé sqlite3 construire enveloppé avec un cryptage tel que wxSQLite3 (que nous utilisons actuellement dans notre solution ci-dessus) via modifier le fichier d'installation.
  • Une autre approche potentielle consistait à utiliser le extension multiplexée, cependant, cela a une limitation de 32 Go et nécessiterait des problèmes de construction et de développement complexes.
  • ALTER TABLE des instructions sont requises (cela exclut donc complètement l'utilisation de tables virtuelles). Nous avons besoin ALTER TABLE déclarations pour que notre crochet avec knex-schema-inspector pour fonctionner correctement – ce qui garantit que les données ne sont pas corrompues et que les lignes récupérées peuvent être converties en documents valides selon notre mongoose définitions de schéma (qui incluent la contrainte, le type de variable et la validation de données arbitraires).
  • Presque tous les projets compatibles S3 liés à SQLite dans la communauté open source sont en Python (et non en JavaScript que nous utilisons pour 100 % de notre stack).
  • Bibliothèques de compression telles que sqlite-zstd (voir commentaires) semble prometteur, mais n'est peut-être pas encore prêt pour une utilisation en production. Au lieu de cela, la compression côté application sur les types de données tels que String, Object, Map, Array, Set, et Buffer va être une approche plus propre et plus simple (et est également plus facile à migrer, puisque nous pourrions stocker un Boolean drapeau ou colonne – ou même utiliser PRAGMA user_version=1 pour la compression ou user_version=0 pour aucune compression en tant que métadonnées de base de données).
    • Heureusement, nous avons déjà implémenté la déduplication des pièces jointes dans le stockage de notre serveur IMAP – par conséquent, chaque message avec la même pièce jointe ne conservera pas de copie de la pièce jointe – au lieu de cela, une seule pièce jointe est stockée pour plusieurs messages et fils de discussion dans une boîte aux lettres (et une pièce jointe étrangère). référence est ensuite utilisée).
  • Le projet Litestream, qui est une solution de réplication et de sauvegarde SQLite, est très prometteur et nous l'utiliserons très probablement dans le futur.
  • La restauration des sauvegardes doit être fluide et triviale. Utiliser une solution telle que MongoDB avec mongodump et mongoexport est non seulement fastidieux, mais prend du temps et présente une complexité de configuration.
    • Les bases de données SQLite simplifient les choses (c'est un seul fichier).
    • Nous souhaitions concevoir une solution où les utilisateurs pourraient prendre leur boîte mail et repartir à tout moment.
      • Commandes Node.js simples pour fs.unlink('mailbox.sqlite')) et il est définitivement effacé du stockage sur disque.
      • Nous pouvons de la même manière utiliser une API compatible S3 avec HTTP DELETE pour supprimer facilement les instantanés et les sauvegardes des utilisateurs.
    • SQLite était la solution la plus simple, la plus rapide et la plus rentable.

Manque d'alternatives

À notre connaissance, aucun autre service de messagerie n’est conçu de cette façon et n’est pas open source.

Nous je pense que cela pourrait être dû aux services de messagerie existants ayant une technologie héritée en production avec code spaghetti 🍝.

La plupart, sinon la totalité, des fournisseurs de services de messagerie existants sont soit à source fermée, soit annoncés comme open source, mais en réalité, seul leur front-end est open source.

La partie la plus sensible du courrier électronique (l'interaction stockage/IMAP/SMTP réelle) tout se fait sur le back-end (serveur), et pas sur le front-end (client).

Essayez le transfert d'e-mail

Inscrivez-vous aujourd'hui sur https://forwardemail.net! 🚀