Tiefer Einblick: Wie wir quantensicher verschlüsselte SQLite-Postfächer für unseren datenschutzorientierten und sicheren E-Mail-Dienst verwenden

Im Gegensatz zu anderen E-Mail-Diensten stellen wir sicher, dass nur Sie jederzeit Zugriff auf Ihr Postfach haben .

Vorwort

tldr; Unser E-Mail-Service ist 100 % Open Source und datenschutzorientiert durch sichere und verschlüsselte SQLite-Postfächer.

Bis wir starteten IMAP-Unterstützung, haben wir MongoDB für unsere persistenten Datenspeicheranforderungen verwendet.

Diese Technologie ist erstaunlich und wir verwenden sie auch heute noch – aber um Verschlüsselung im Ruhezustand mit MongoDB zu haben, müssen Sie einen Anbieter nutzen, der MongoDB Enterprise anbietet, wie z. B. Digital Ocean oder Mongo Atlas – oder für eine Unternehmenslizenz bezahlen (und müssen anschließend mit der Latenz des Vertriebsteams arbeiten).

Unser Team bei Email weiterleiten benötigte eine entwicklerfreundliche, skalierbare, zuverlässige und verschlüsselte Speicherlösung für IMAP-Postfächer. Als Open-Source-Entwickler war es dagegen, eine Technologie zu verwenden, für die man eine Lizenzgebühr zahlen muss, um die Funktion „Encryption-at-Rest“ zu erhalten unsere Prinzipien – und so haben wir experimentiert, geforscht und von Grund auf eine neue Lösung entwickelt, um diese Anforderungen zu erfüllen.

Anstatt eine gemeinsame Datenbank zum Speichern Ihrer Postfächer zu verwenden, speichern und verschlüsseln wir Ihre Postfächer einzeln mit Ihrem Passwort (das nur Sie haben). Unser E-Mail-Service ist so sicher, dass Ihr Postfach verloren geht, wenn Sie Ihr Passwort vergessen (und müssen mit Offline-Backups wiederhergestellt werden oder von vorne beginnen).

Lesen Sie weiter, während wir weiter unten einen tiefen Einblick in a nehmen Vergleich von E-Mail-Dienstleistern, wie unser Service funktioniert, Unser Technologie-Stack, und mehr.

Vergleich von E-Mail-Dienstanbietern

Wir sind der einzige zu 100 % Open-Source- und datenschutzorientierte E-Mail-Dienstanbieter, der individuell verschlüsselte SQLite-Postfächer speichert, unbegrenzte Domänen, Aliase und Benutzer bietet und ausgehende SMTP-, IMAP- und POP3-Unterstützung bietet:

Im Gegensatz zu anderen E-Mail-Anbietern müssen Sie bei Forward Email nicht für die Speicherung pro Domain oder Alias bezahlen. Der Speicher wird für Ihr gesamtes Konto gemeinsam genutzt. Wenn Sie also mehrere benutzerdefinierte Domänennamen und jeweils mehrere Aliase haben, sind wir die perfekte Lösung für Sie. Beachten Sie, dass Sie bei Bedarf weiterhin Speicherbeschränkungen pro Domäne oder Alias erzwingen können.

Lesen Sie den E-Mail-Service-Vergleich

Wie funktioniert es

  1. Mit Ihrem E-Mail-Client wie Apple Mail, Thunderbird, Gmail oder Outlook stellen Sie eine Verbindung zu unserem sicheren E-Mail-Programm her IMAP Servern mit Ihrem Benutzernamen und Passwort:

    • Ihr Benutzername ist Ihr vollständiger Alias mit Ihrer Domain, z hello@example.com.
    • Ihr Passwort wird zufällig generiert und Ihnen beim Klicken nur 30 Sekunden lang angezeigt Generiere Passwort aus Mein Konto Domänen Aliase.
  2. Sobald die Verbindung hergestellt ist, sendet Ihr E-Mail-Client IMAP-Protokollbefehle an unseren IMAP-Server, um Ihr Postfach synchron zu halten. Dazu gehören das Schreiben und Speichern von E-Mail-Entwürfen und andere Aktionen, die Sie möglicherweise durchführen (z. B. das Kennzeichnen einer E-Mail als „Wichtig“ oder das Markieren einer E-Mail als Spam/Junk-Mail).

  3. Mail-Exchange-Server (allgemein als „MX“-Server bekannt) empfangen neue eingehende E-Mails und speichern sie in Ihrem Postfach. In diesem Fall wird Ihr E-Mail-Client benachrichtigt und Ihr Postfach synchronisiert. Unsere Mail-Exchange-Server können Ihre E-Mail an einen oder mehrere Empfänger weiterleiten (einschließlich Webhooks), speichern Sie Ihre E-Mails für Sie in Ihrem verschlüsselten IMAP-Speicher bei uns, oder beides!

    Möchten Sie mehr erfahren? Lesen So richten Sie die E-Mail-Weiterleitung ein, wie unser Mail-Exchange-Service funktioniert, oder ansehen unsere Guides.

  4. Hinter den Kulissen funktioniert unser sicheres E-Mail-Speicherdesign auf zwei Arten, damit Ihre Postfächer verschlüsselt bleiben und nur Sie darauf zugreifen können:

    • Wenn für Sie neue E-Mails von einem Absender eingehen, schreiben unsere Mail-Exchange-Server für Sie in ein individuelles, temporäres und verschlüsseltes Postfach.

      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!
      
    • Wenn Sie mit Ihrem E-Mail-Client eine Verbindung zu unserem IMAP-Server herstellen, wird Ihr Passwort im Speicher verschlüsselt und zum Lesen und Schreiben in Ihr Postfach verwendet. Mit diesem Passwort kann Ihr Postfach nur gelesen und beschrieben werden. Denken Sie daran, dass Sie der Einzige mit diesem Passwort sind. nur du Sie können Ihr Postfach lesen und darauf schreiben, wenn Sie darauf zugreifen. Wenn Ihr E-Mail-Client das nächste Mal versucht, E-Mails oder Synchronisierungen abzurufen, werden Ihre neuen Nachrichten aus diesem temporären Postfach übertragen und mit Ihrem angegebenen Passwort in Ihrer eigentlichen Postfachdatei gespeichert. Beachten Sie, dass dieses temporäre Postfach anschließend bereinigt und gelöscht wird, sodass nur Ihr passwortgeschütztes Postfach die Nachrichten enthält.

    • Wenn Sie mit IMAP verbunden sind (z. B. über einen E-Mail-Client wie Apple Mail oder Thunderbird), müssen wir nicht auf den temporären Festplattenspeicher schreiben. Stattdessen wird Ihr im Speicher verschlüsseltes IMAP-Passwort abgerufen und verwendet. Wenn eine Nachricht an Sie zugestellt werden soll, senden wir in Echtzeit eine WebSocket-Anfrage an alle IMAP-Server und fragen sie, ob sie eine aktive Sitzung für Sie haben (dies ist der Abrufteil), und leiten diese anschließend weiter verschlüsseltes In-Memory-Passwort – damit wir nicht in ein temporäres Postfach schreiben müssen, können wir mit Ihrem verschlüsselten Passwort in Ihr tatsächlich verschlüsseltes Postfach schreiben.

      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. Backups Ihrer verschlüsselten Postfächer werden täglich hergestellt. Sie können auch jederzeit ein neues Backup anfordern oder das neueste Backup von herunterladen Mein Konto Domänen Aliase. Wenn Sie sich entscheiden, zu einem anderen E-Mail-Dienst zu wechseln, können Sie Ihre Postfächer und Backups jederzeit problemlos migrieren, herunterladen, exportieren und löschen.

Technologien

Datenbanken

Wir haben andere mögliche Datenbankspeicherschichten untersucht, aber keine entsprach unseren Anforderungen so gut wie SQLite:

DatenbankVerschlüsselung im RuhezustandSandboxed PostfächerLizenzÜberall im Einsatz
SQLite✅ Ja mit SQLite3MultipleCiphers✅ Public Domain
MongoDB„Nur in MongoDB Enterprise verfügbar“❌ Relationale Datenbank❌ AGPL und SSPL-1.0
rqliteNur Netzwerk❌ Relationale DatenbankMIT
dqliteUngetestet und noch nicht unterstützt?Ungetestet und noch nicht unterstützt?LGPL-3.0-only
PostgreSQLJa❌ Relationale DatenbankPostgreSQL (ähnlich zu BSD oder MIT)
MariaDBNur für InnoDB❌ Relationale DatenbankGPLv2 und BUSL-1.1
KakerlakeDBFunktion nur für Unternehmen❌ Relationale DatenbankBUSL-1.1 und andere

Hier ist ein Blogbeitrag, der mehrere SQLite-Datenbankspeicheroptionen vergleicht in der Tabelle oben.

Sicherheit

Zu jeder Zeit verwenden wir Verschlüsselung im Ruhezustand (AES-256), Verschlüsselung während der Übertragung (TLS), DNS über HTTPS („DoH“) mit 🍊 Mandarine, und sqleet (ChaCha20-Poly1305) Verschlüsselung auf Postfächern. Darüber hinaus verwenden wir eine tokenbasierte Zwei-Faktor-Authentifizierung (im Gegensatz zu SMS, die verdächtig ist). Man-in-the-Middle-Angriffe), rotierte SSH-Schlüssel mit deaktiviertem Root-Zugriff, exklusiver Zugriff auf Server über eingeschränkte IP-Adressen und mehr.

Im Falle eines böser Dienstmädchenangriff oder betrügerischer Mitarbeiter eines Drittanbieters, Ihr Postfach kann weiterhin nur mit Ihrem generierten Passwort geöffnet werden. Seien Sie versichert, dass wir uns nicht auf andere Drittanbieter als unsere SOC-Typ-2-Beschwerdeserveranbieter Cloudflare, Digital Ocean und Vultr verlassen.

Unser Ziel ist es, möglichst wenige zu haben Single Point of Failures wie möglich.

Postfächer

tldr; Unsere IMAP-Server nutzen individuell verschlüsselte SQLite-Datenbanken für jedes Ihrer Postfächer.

SQLite ist äußerst beliebt eingebettete Datenbank – sie läuft derzeit auf Ihrem Telefon und Computer – und wird von fast allen wichtigen Technologien verwendet.

Auf unseren verschlüsselten Servern gibt es beispielsweise ein SQLite-Datenbankpostfach für linux@example.com, info@example.com, hello@example.com und so weiter – eine für jeden als .sqlite Datenbankdatei. Wir benennen die Datenbankdateien auch nicht mit der E-Mail-Adresse – stattdessen verwenden wir BSON ObjectID und generierte eindeutige UUIDs, die nicht verraten, wem das Postfach gehört oder unter welcher E-Mail-Adresse es sich befindet (z. B. 353a03f21e534321f5d6e267.sqlite).

Jede dieser Datenbanken wird mit Ihrem Passwort (das nur Sie haben) verschlüsselt sqleet (ChaCha20-Poly1305). Das bedeutet, dass Ihre Postfächer individuell verschlüsselt, in sich geschlossen und Sandkasten, und tragbar.

Wir haben SQLite wie folgt optimiert PRAGMA:

PRAGMAZweck
cipher=chacha20ChaCha20-Poly1305 SQLite-Datenbankverschlüsselung. Referenz better-sqlite3-multiple-ciphers unter Projekte für mehr Einblick.
key="****************"Dabei handelt es sich um Ihr entschlüsseltes In-Memory-Passwort, das über die IMAP-Verbindung Ihres E-Mail-Clients an unseren Server weitergeleitet wird. Für jede Lese- und Schreibsitzung werden neue Datenbankinstanzen erstellt und geschlossen (um Sandboxing und Isolation sicherzustellen).
journal_model=WALWrite-Ahead-Protokoll ("WAL") Dies steigert die Leistung und ermöglicht den gleichzeitigen Lesezugriff.
busy_timeout=5000Verhindert Schreibsperrfehler während andere Schreibvorgänge stattfinden.
synchronous=NORMALErhöht die Haltbarkeit von Transaktionen ohne das Risiko einer Datenkorruption.
foreign_keys=ONErzwingt, dass Fremdschlüsselreferenzen (z. B. eine Beziehung von einer Tabelle zu einer anderen) erzwungen werden. Standardmäßig ist dies in SQLite nicht aktiviert, aber für die Validierung und Datenintegrität sollte es aktiviert sein.
encoding='UTF-8'Standardkodierung zu verwenden, um die Vernunft der Entwickler sicherzustellen.

Alle anderen Standardeinstellungen stammen von SQLite, wie in angegeben offizielle PRAGMA-Dokumentation.

Parallelität

tldr; Wir gebrauchen rclone und WebSocket für gleichzeitige Lese- und Schreibvorgänge in Ihren verschlüsselten SQLite-Postfächern.

Liest

Möglicherweise löst sich Ihr E-Mail-Client auf Ihrem Telefon auf imap.forwardemail.net zu einer unserer Digital Ocean IP-Adressen – und Ihr Desktop-Client löst möglicherweise eine separate IP von einer anderen auf Anbieter insgesamt.

Unabhängig davon, mit welchem IMAP-Server Ihr E-Mail-Client eine Verbindung herstellt, möchten wir, dass die Verbindung in Echtzeit mit 100 %iger Genauigkeit aus Ihrer Datenbank liest:

  • Dies wird durch die Verwendung erreicht rclone mit --vfs-cache-mode off (der Standard).

  • Anstatt den lokalen Festplatten-Cache zu verwenden, wird der Cache in Echtzeit direkt vom Remote-Mount (Ihrer Datenbank) gelesen.

  • Falls die lokale Datei nicht gefunden werden kann, weist dies darauf hin rclone Die Bereitstellung ist fehlgeschlagen oder es liegt ein Problem vor. In diesem Fall verwenden wir a WebSocket Fallback für Lesevorgänge (was die Leistung leicht verringert, aber dennoch die Integrität des Dienstes aufrechterhält).

  • Jeder unserer Server ist für eine konsistente Bereitstellung konfiguriert und benachrichtigt uns in Echtzeit über etwaige Fehler.

Schreibt

Das Schreiben in Ihre Datenbank ist etwas anders – da SQLite eine eingebettete Datenbank ist und Ihr Postfach standardmäßig in einer einzigen Datei gespeichert ist.

Wir hatten Optionen erkundet wie litestream, rqlite, und dqlite unten – jedoch entsprach keines davon unseren Anforderungen.

Um Schreibvorgänge mit Write-Ahead-Logging durchzuführen ("WAL") aktiviert – wir müssen sicherstellen, dass nur ein Server ("Primär") dafür verantwortlich ist. WAL beschleunigt die Parallelität drastisch und ermöglicht einen Autor und mehrere Leser.

Der Primärserver wird auf den Datenservern ausgeführt, wobei die bereitgestellten Volumes die verschlüsselten Postfächer enthalten. Aus Sicht der Verteilung könnten Sie alle einzelnen IMAP-Server dahinter berücksichtigen imap.forwardemail.net sekundäre Server zu sein („Sekundär“).

Wir erreichen eine wechselseitige Kommunikation mit WebSockets:

  • Primärserver verwenden eine Instanz von ws'S WebSocketServer Server.
  • Sekundärserver verwenden eine Instanz von ws'S WebSocket Client, der umschlossen ist websocket-wie-versprochen und reconnecting-websocket. Diese beiden Wrapper sorgen dafür, dass die WebSocket stellt die Verbindung wieder her und kann Daten für bestimmte Datenbankschreibvorgänge senden und empfangen.

Backups

tldr; Es werden täglich Backups Ihrer verschlüsselten Postfächer erstellt. Sie können auch sofort ein neues Backup anfordern oder jederzeit das neueste Backup herunterladen Mein Konto Domänen Aliase.

Für Backups führen wir einfach SQLite aus VACUUM INTO Befehl jeden Tag während der IMAP-Befehlsverarbeitung, die Ihr verschlüsseltes Passwort aus einer speicherinternen IMAP-Verbindung nutzt. Backups werden gespeichert, wenn kein vorhandenes Backup erkannt wird oder wenn die SHA-256 Der Hash der Datei hat sich im Vergleich zur letzten Sicherung geändert.

Beachten Sie, dass wir die verwenden VACUUM INTO Befehl im Gegensatz zum integrierten backup Befehl, denn wenn eine Seite während a geändert wird backup Befehlsoperation, dann muss es von vorne beginnen. Der VACUUM INTO Der Befehl erstellt einen Schnappschuss. Siehe diese Kommentare auf GitHub und Hacker-News für mehr Einblick.

Zusätzlich verwenden wir VACUUM INTO im Gegensatz zu backup, weil das backup Der Befehl würde die Datenbank für kurze Zeit unverschlüsselt lassen, bis rekey aufgerufen wird (siehe diesen GitHub Kommentar zur Einsicht).

Die Sekundarstufe wird die Primarstufe über das informieren WebSocket Verbindung, um das Backup auszuführen – und der Primary erhält dann den Befehl dazu und wird anschließend:

  1. Stellen Sie eine Verbindung zu Ihrem verschlüsselten Postfach her.
  2. Erwerben Sie eine Schreibsperre.
  3. Führen Sie einen WAL-Checkpoint über aus wal_checkpoint(PASSIVE).
  4. Führen Sie das aus VACUUM INTO SQLite-Befehl.
  5. Stellen Sie sicher, dass die kopierte Datei mit dem verschlüsselten Passwort geöffnet werden kann (Sicherung/Dummyproofing).
  6. Laden Sie es zur Speicherung auf Cloudflare R2 hoch (oder auf Ihren eigenen Anbieter, falls angegeben).
  7. Komprimieren Sie die resultierende Sicherungsdatei mit gzip.
  8. Laden Sie es zur Speicherung auf Cloudflare R2 hoch (oder auf Ihren eigenen Anbieter, falls angegeben).

Denken Sie daran, dass Ihre Postfächer verschlüsselt sind – und obwohl wir IP-Beschränkungen und andere Authentifizierungsmaßnahmen für die WebSocket-Kommunikation eingerichtet haben – können Sie im Falle eines böswilligen Akteurs sicher sein, dass Ihre Datenbank nicht geöffnet werden kann, wenn die WebSocket-Payload nicht über Ihr IMAP-Passwort verfügt .

Derzeit wird nur ein Backup pro Postfach gespeichert, aber in Zukunft bieten wir möglicherweise eine Point-in-Time-Wiederherstellung an ("PITR").

Unsere IMAP-Server unterstützen das SEARCH Befehl mit komplexen Abfragen, regulären Ausdrücken und mehr.

Eine schnelle Suchleistung ist zu verdanken FTS5 und sqlite-regex.

Wir speichern Date Werte in den SQLite-Postfächern als ISO 8601 Saiten über Date.prototype.toISOString (mit UTC-Zeitzone, damit Gleichheitsvergleiche ordnungsgemäß funktionieren).

Für alle Eigenschaften, die in Suchanfragen enthalten sind, werden auch Indizes gespeichert.

Projekte

Hier ist eine Tabelle mit Projekten, die wir in unserem Quellcode und Entwicklungsprozess verwenden (alphabetisch sortiert):

ProjektZweck
AnsibleDevOps-Automatisierungsplattform für die einfache Wartung, Skalierung und Verwaltung unserer gesamten Serverflotte.
BreeJobplaner für Node.js und JavaScript mit Cron, Dates, MS, Later und benutzerfreundlicher Unterstützung.
KabineEntwicklerfreundliche JavaScript- und Node.js-Protokollierungsbibliothek mit Blick auf Sicherheit und Datenschutz.
JungeNode.js-Framework, das unsere gesamte Architektur und unser technisches Design mit MVC und mehr unterstützt.
MongoDBNoSQL-Datenbanklösung, die wir zum Speichern aller anderen Daten außerhalb von Postfächern verwenden (z. B. Ihr Konto, Ihre Einstellungen, Domänen und Alias-Konfigurationen).
MungoMongoDB-Objektdokumentmodellierung („ODM“), die wir in unserem gesamten Stack verwenden. Wir haben spezielle Helfer geschrieben, die es uns ermöglichen, einfach weiter zu verwenden Mungo mit SQLite 🎉
Node.jsNode.js ist die plattformübergreifende Open-Source-JavaScript-Laufzeitumgebung, die alle unsere Serverprozesse ausführt.
NotizmailerNode.js-Paket zum Senden von E-Mails, Erstellen von Verbindungen und mehr. Wir sind offizieller Sponsor dieses Projekts.
RedisIn-Memory-Datenbank für Caching, Publish/Subscribe-Kanäle und DNS-über-HTTPS-Anfragen.
SQLite3MultipleCiphersVerschlüsselungserweiterung für SQLite, um die Verschlüsselung ganzer Datenbankdateien zu ermöglichen (einschließlich des Write-Ahead-Protokolls ("WAL"), Journal, Rollback, …).
SQLiteStudioVisueller SQLite-Editor (den Sie auch verwenden können) zum Testen, Herunterladen und Anzeigen von Entwicklungspostfächern.
SQLiteEingebettete Datenbankschicht für skalierbare, eigenständige, schnelle und belastbare IMAP-Speicherung.
Spam-ScannerNode.js Anti-Spam-, E-Mail-Filter- und Phishing-Präventionstool (unsere Alternative zu Spam-Attentäter und rspamd).
MandarineDNS-über-HTTPS-Anfragen mit Node.js und Caching mit Redis – das sorgt für globale Konsistenz und vieles mehr.
DonnervogelUnser Entwicklungsteam verwendet dies (und empfiehlt es auch) als Der bevorzugte E-Mail-Client zur Verwendung mit Forward Email.
UTMUnser Entwicklungsteam nutzt diese Erstellung virtueller Maschinen für iOS und macOS, um verschiedene E-Mail-Clients (parallel) mit unseren IMAP- und SMTP-Servern zu testen.
UbuntuModernes Open-Source-Serverbetriebssystem auf Linux-Basis, das unsere gesamte Infrastruktur antreibt.
Wilde EnteIMAP-Serverbibliothek – siehe Hinweise dazu Deduplizierung von Anhängen und Unterstützung des IMAP-Protokolls.
better-sqlite3-multiple-ciphersSchnelle und einfache API-Bibliothek für Node.js zur programmgesteuerten Interaktion mit SQLite3.
E-Mail-VorlagenEntwicklerfreundliches E-Mail-Framework zum Erstellen, Vorschau und Senden benutzerdefinierter E-Mails (z. B. Kontobenachrichtigungen und mehr).
json-sqlSQL-Abfrage-Builder mit Syntax im Mongo-Stil. Dies spart unserem Entwicklungsteam Zeit, da wir mit einem datenbankunabhängigen Ansatz weiterhin im Mongo-Stil über den gesamten Stack schreiben können. Es hilft auch, SQL-Injection-Angriffe durch die Verwendung von Abfrageparametern zu vermeiden.
knex-schema-inspectorSQL-Dienstprogramm zum Extrahieren von Informationen über das vorhandene Datenbankschema. Dadurch können wir ganz einfach überprüfen, ob alle Indizes, Tabellen, Spalten, Einschränkungen und mehr gültig sind und sind 1:1 damit, wie sie sein sollten. Wir haben sogar automatisierte Hilfsprogramme geschrieben, um neue Spalten und Indizes hinzuzufügen, wenn Änderungen an Datenbankschemata vorgenommen werden (auch mit äußerst detaillierter Fehlerwarnung).
knexSQL-Abfrage-Builder, den wir nur für Datenbankmigrationen und Schemavalidierungen verwenden knex-schema-inspector.
MandarinAutomatisch i18n Phrasenübersetzung mit Unterstützung für Markdown Google Cloud Translation API.
mx-connectNode.js-Paket zum Auflösen und Herstellen von Verbindungen mit MX-Servern und zum Behandeln von Fehlern.
Uhr2Node.js-Produktionsprozessmanager mit integriertem Load Balancer (fein abgestimmt für Leistung).
SMTP-ServerSMTP-Serverbibliothek – wir verwenden diese für unseren Mail-Austausch („MX“) und ausgehende SMTP-Server.
ImapTestNützliches Tool zum Testen von IMAP-Servern anhand von Benchmarks und zur Kompatibilität des IMAP-Protokolls der RFC-Spezifikation. Dieses Projekt wurde von erstellt Taubenschlag Team (ein aktiver Open-Source-IMAP- und POP3-Server seit Juli 2002). Wir haben unseren IMAP-Server mit diesem Tool ausgiebig getestet.

Hier finden Sie weitere Projekte, in denen wir zum Einsatz kommen Unser Quellcode auf GitHub.

Anbieter

AnbieterZweck
WolkenflareVerwendung von DNS-Anbietern, Gesundheitsprüfungen, Lastausgleichsdiensten und Sicherungsspeicher Cloudflare R2.
Digitaler OzeanDediziertes Server-Hosting, SSD-Blockspeicher und verwaltete Datenbanken.
VultrDediziertes Server-Hosting und SSD-Blockspeicher.

Gedanken

Prinzipien

„E-Mail weiterleiten“ ist nach diesen Grundsätzen konzipiert:

  1. Seien Sie stets entwicklerfreundlich, sicherheits- und datenschutzorientiert und transparent.
  2. Sich an etw. halten MVC, Unix, KISS, DRY, YAGNI, Zwölf Faktor, Ockhams Rasiermesser, und Hundefutter
  3. Zielen Sie auf die Scrappy-, Bootstrapped- und Ramen-profitabel Entwickler

Experimente

tldr; Letztendlich ist die Verwendung von S3-kompatiblem Objektspeicher und/oder virtuellen Tabellen aus Leistungsgründen technisch nicht machbar und aufgrund von Speicherbeschränkungen fehleranfällig.

Wir haben einige Experimente durchgeführt, die zu unserer endgültigen SQLite-Lösung führten, wie oben beschrieben.

Eine davon war, es mit zu versuchen rclone und SQLite zusammen mit einer S3-kompatiblen Speicherschicht.

Dieses Experiment führte uns dazu, Randfälle rund um rclone, SQLite und besser zu verstehen und zu entdecken VFS Verwendung:

  • Wenn Sie aktivieren --vfs-cache-mode writes Flag mit rclone, dann sind Lesevorgänge in Ordnung, Schreibvorgänge werden jedoch zwischengespeichert.
    • Wenn Sie mehrere global verteilte IMAP-Server haben, ist der Cache auf allen Servern deaktiviert, es sei denn, Sie haben einen einzelnen Writer und mehrere Listener (z. B. einen Pub/Sub-Ansatz).
    • Das ist unglaublich komplex und das Hinzufügen zusätzlicher Komplexität wie dieser führt zu mehr Single Points of Failure.
    • S3-kompatible Speicheranbieter unterstützen keine teilweisen Dateiänderungen – also jede Änderung der Datei .sqlite Die Datei führt zu einer vollständigen Änderung und einem erneuten Hochladen der Datenbank.
    • Andere Lösungen wie rsync existieren, aber sie konzentrieren sich nicht auf Write-Ahead-Log ("WAL")-Unterstützung – also haben wir uns letztendlich für Litestream entschieden. Glücklicherweise verschlüsselt unsere Verschlüsselungsnutzung bereits die WAL Dateien für uns, sodass wir uns hierfür nicht auf Litestream verlassen müssen. Wir waren jedoch noch nicht davon überzeugt, dass Litestream für den Produktionseinsatz geeignet ist, und haben unten ein paar Anmerkungen dazu.
    • Mit dieser Option von --vfs-cache-mode writes (Die nur Möglichkeit, SQLite zu verwenden rclone für Schreibvorgänge) versucht, die gesamte Datenbank von Grund auf in den Arbeitsspeicher zu kopieren – die Handhabung eines 10-GB-Postfachs ist in Ordnung, die Handhabung mehrerer Postfächer mit übermäßig hohem Speicher führt jedoch dazu, dass die IMAP-Server an Speicherbeschränkungen stoßen und ENOMEM Fehler, Segmentierungsfehler und Datenbeschädigung.
  • Wenn Sie versuchen, SQLite zu verwenden Virtuelle Tische (z.B. mit s3db), um Daten live auf einer S3-kompatiblen Speicherschicht zu haben, werden Sie auf mehrere weitere Probleme stoßen:
    • Lese- und Schreibvorgänge werden extrem langsam sein, da S3-API-Endpunkte mit HTTP erreicht werden müssen GET, PUT, HEAD, und POST Methoden.
    • Entwicklungstests haben gezeigt, dass mehr als 500.000 bis 1 Mio. Datensätze im Glasfaser-Internet immer noch durch den Schreib- und Lesedurchsatz bei S3-kompatiblen Anbietern begrenzt sind. Zum Beispiel sind unsere Entwickler gelaufen for Schleifen, um sowohl sequentielles SQL auszuführen INSERT Anweisungen und solche, die große Datenmengen in großen Mengen schreiben. In beiden Fällen war die Leistung erstaunlich langsam.
    • Virtuelle Tische kann keine Indizes haben, ALTER TABLE Aussagen und andere Einschränkungen – was je nach Datenmenge zu Verzögerungen von mehr als 1-2 Minuten oder mehr führt.
    • Objekte wurden unverschlüsselt gespeichert und es ist keine native Verschlüsselungsunterstützung verfügbar.
  • Wir haben auch die Verwendung untersucht sqlite-s3vfs Dies ähnelt konzeptionell und technisch dem vorherigen Aufzählungspunkt (hat also die gleichen Probleme). Eine Möglichkeit wäre die Verwendung eines Customs sqlite3 Build mit Verschlüsselung verpackt, z wxSQLite3 (die wir derzeit in unserer Lösung oben verwenden) durch Bearbeiten der Setup-Datei.
  • Ein weiterer möglicher Ansatz wäre die Verwendung von Multiplex-ErweiterungDies ist jedoch auf 32 GB begrenzt und würde komplexe Bau- und Entwicklungsprobleme erfordern.
  • ALTER TABLE Anweisungen sind erforderlich (dies schließt die Verwendung virtueller Tabellen vollständig aus). Wir brauchen ALTER TABLE Anweisungen, damit unser Haken mit knex-schema-inspector ordnungsgemäß funktionieren – wodurch sichergestellt wird, dass die Daten nicht beschädigt werden und die abgerufenen Zeilen in gültige Dokumente gemäß unseren Richtlinien umgewandelt werden können mongoose Schemadefinitionen (einschließlich Einschränkungen, Variablentypen und willkürlicher Datenvalidierung).
  • Fast alle S3-kompatiblen Projekte im Zusammenhang mit SQLite in der Open-Source-Community sind in Python (und nicht in JavaScript, das wir für 100 % unseres Stacks verwenden).
  • Komprimierungsbibliotheken wie z sqlite-zstd (sehen Kommentare) sehen vielversprechend aus, aber ist möglicherweise noch nicht für den Produktionseinsatz bereit. Stattdessen erfolgt eine anwendungsseitige Komprimierung von Datentypen wie z String, Object, Map, Array, Set, und Buffer wird ein saubererer und einfacherer Ansatz sein (und ist auch einfacher zu migrieren, da wir eine speichern könnten Boolean Flagge oder Säule – oder sogar nutzen PRAGMA user_version=1 zur Komprimierung bzw user_version=0 für keine Komprimierung als Datenbankmetadaten).
    • Glücklicherweise haben wir in unserem IMAP-Serverspeicher bereits die Deduplizierung von Anhängen implementiert – daher behält nicht jede Nachricht mit demselben Anhang eine Kopie des Anhangs – stattdessen wird ein einzelner Anhang für mehrere Nachrichten und Threads in einem Postfach (und einem fremden Postfach) gespeichert Referenz wird anschließend verwendet).
  • Das Projekt Litestream, eine SQLite-Replikations- und Backup-Lösung, ist sehr vielversprechend und wir werden es höchstwahrscheinlich in Zukunft nutzen.
  • Die Backup-Wiederherstellung muss reibungslos und einfach sein. Verwenden einer Lösung wie MongoDB mit mongodump und mongoexport ist nicht nur mühsam, sondern auch zeitintensiv und weist eine komplexe Konfiguration auf.
    • SQLite-Datenbanken machen es einfach (es ist eine einzelne Datei).
    • Wir wollten eine Lösung entwickeln, bei der Benutzer ihren Briefkasten jederzeit mitnehmen und verlassen können.
      • Einfache Node.js-Befehle für fs.unlink('mailbox.sqlite')) und es wird dauerhaft aus dem Festplattenspeicher gelöscht.
      • Ebenso können wir eine S3-kompatible API mit HTTP verwenden DELETE um Snapshots und Backups für Benutzer einfach zu entfernen.
    • SQLite war die einfachste, schnellste und kostengünstigste Lösung.

Mangel an Alternativen

Unseres Wissens nach sind keine anderen E-Mail-Dienste auf diese Weise konzipiert und auch nicht Open Source.

Wir Ich denke, das könnte daran liegen zu bestehenden E-Mail-Diensten mit veralteter Technologie in der Produktion Spaghetti-Code 🍝.

Die meisten, wenn nicht alle bestehenden E-Mail-Dienstanbieter sind entweder Closed-Source-Anbieter oder werben als Open-Source-Anbieter. aber in Wirklichkeit ist nur ihr Frontend Open Source.

Der sensibelste Teil einer E-Mail (die eigentliche Speicher/IMAP/SMTP-Interaktion) wird alles auf dem Back-End (Server) erledigt und nicht auf dem Frontend (Client).

Probieren Sie „E-Mail weiterleiten“ aus

Melden Sie sich noch heute an unter https://forwardemail.net! 🚀