Diepe duik: hoe we kwantumveilige gecodeerde SQLite-mailboxen gebruiken voor onze op privacy gerichte en veilige e-mailservice

In tegenstelling tot andere e-maildiensten zorgen wij ervoor dat alleen u te allen tijde toegang heeft tot uw mailbox .

Voorwoord

tldr; Onze e-mailservice is 100% open source en privacygericht via veilige en gecodeerde SQLite-mailboxen.

Totdat we lanceerden IMAP-ondersteuning, gebruikten we MongoDB voor onze aanhoudende behoeften op het gebied van gegevensopslag.

Deze technologie is geweldig en we gebruiken deze nog steeds – maar om encryptie-at-rest te hebben met MongoDB moet je een provider gebruiken die MongoDB Enterprise aanbiedt, zoals Digital Ocean of Mongo Atlas – of betalen voor een bedrijfslicentie (en vervolgens moeten werken met latentie van het verkoopteam).

Ons team van E-mail doorsturen had behoefte aan een ontwikkelaarsvriendelijke, schaalbare, betrouwbare en gecodeerde opslagoplossing voor IMAP-mailboxen. Als open-sourceontwikkelaars was het gebruik van een technologie waarvoor je licentiekosten moet betalen om de functie voor versleuteling in rust te krijgen, tegen onze principes – en dus hebben we vanaf het begin geëxperimenteerd, onderzocht en een nieuwe oplossing ontwikkeld om aan deze behoeften te voldoen.

In plaats van een gedeelde database te gebruiken om uw mailboxen op te slaan, slaan wij uw mailboxen afzonderlijk op en coderen we deze met uw wachtwoord (dat alleen u heeft). Onze e-mailservice is zo veilig dat als u uw wachtwoord vergeet, u uw mailbox verliest (en moet herstellen met offline back-ups of opnieuw beginnen).

Blijf lezen terwijl we hieronder een diepe duik nemen met a vergelijking van e-mailserviceproviders, hoe onze dienstverlening werkt, onze technologiestapel, en meer.

Vergelijking van e-mailproviders

Wij zijn de enige 100% open source en op privacy gerichte e-mailserviceprovider die individueel gecodeerde SQLite-mailboxen opslaat, een onbeperkt aantal domeinen, aliassen en gebruikers biedt, en uitgaande SMTP-, IMAP- en POP3-ondersteuning biedt:

In tegenstelling tot andere e-mailproviders hoeft u bij Forward Email niet per domein of alias voor opslag te betalen. De opslag wordt gedeeld over uw hele account. Als u dus meerdere aangepaste domeinnamen en meerdere aliassen op elk account heeft, dan zijn wij de perfecte oplossing voor u. Houd er rekening mee dat u desgewenst nog steeds opslaglimieten kunt afdwingen per domein of alias.

Lees de vergelijking van e-mailservices

Hoe werkt het

  1. Met uw e-mailclient zoals Apple Mail, Thunderbird, Gmail of Outlook maakt u verbinding met onze beveiligde IMAP servers die uw gebruikersnaam en wachtwoord gebruiken:

    • Uw gebruikersnaam is uw volledige alias met uw domein, zoals hello@example.com.
    • Uw wachtwoord wordt willekeurig gegenereerd en wordt slechts 30 seconden aan u weergegeven als u klikt Genereer wachtwoord van Mijn Account Domeinen Aliassen.
  2. Eenmaal verbonden, zal uw e-mailclient verzenden IMAP-protocolopdrachten naar onze IMAP-server om uw mailbox gesynchroniseerd te houden. Dit omvat het schrijven en opslaan van concept-e-mails en andere acties die u kunt ondernemen (bijvoorbeeld een e-mail labelen als belangrijk of een e-mail markeren als spam/ongewenste e-mail).

  3. Mailuitwisselingsservers (algemeen bekend als "MX"-servers) ontvangen nieuwe inkomende e-mail en slaan deze op in uw mailbox. Wanneer dit gebeurt, ontvangt uw e-mailclient een melding en wordt uw mailbox gesynchroniseerd. Onze mailuitwisselingsservers kunnen uw e-mail doorsturen naar een of meer ontvangers (inclusief webhaken), bewaar uw e-mail voor u in uw gecodeerde IMAP-opslag bij ons, of allebei!

    Wilt u meer weten? Lezen hoe u het doorsturen van e-mail instelt, hoe onze postuitwisselingsservice werkt, of bekijken onze gidsen.

  4. Achter de schermen werkt ons veilige e-mailopslagontwerp op twee manieren om uw mailboxen gecodeerd te houden en alleen voor u toegankelijk:

    • Wanneer er nieuwe e-mail voor u wordt ontvangen van een afzender, schrijven onze mailuitwisselingsservers voor u naar een individuele, tijdelijke en gecodeerde mailbox.

      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!
      
    • Wanneer u met uw e-mailclient verbinding maakt met onze IMAP-server, wordt uw wachtwoord gecodeerd in het geheugen en gebruikt om te lezen en te schrijven naar uw mailbox. Alleen met dit wachtwoord kan uw mailbox worden gelezen en geschreven. Houd er rekening mee dat, aangezien u de enige bent met dit wachtwoord, alleen jij kunt lezen en schrijven naar uw mailbox wanneer u deze opent. De volgende keer dat uw e-mailclient probeert te peilen naar e-mail of synchronisaties, worden uw nieuwe berichten overgebracht vanuit deze tijdelijke mailbox en opgeslagen in uw daadwerkelijke mailboxbestand met behulp van het door u opgegeven wachtwoord. Houd er rekening mee dat deze tijdelijke mailbox achteraf wordt opgeschoond en verwijderd, zodat alleen uw met een wachtwoord beveiligde mailbox de berichten bevat.

    • Als u verbonden bent met IMAP (bijvoorbeeld met behulp van een e-mailclient zoals Apple Mail of Thunderbird), hoeven we niet naar tijdelijke schijfopslag te schrijven. In plaats daarvan wordt uw in het geheugen gecodeerde IMAP-wachtwoord opgehaald en gebruikt. Wanneer een bericht bij u probeert te worden afgeleverd, sturen we in realtime een WebSocket-verzoek naar alle IMAP-servers met de vraag of ze een actieve sessie voor u hebben (dit is het ophaalgedeelte), en geven dat vervolgens door gecodeerd wachtwoord in het geheugen – we hoeven dus niet naar een tijdelijke mailbox te schrijven; we kunnen met uw gecodeerde wachtwoord naar uw daadwerkelijke gecodeerde mailbox schrijven.

      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. Back-ups van uw gecodeerde mailboxen worden dagelijks gemaakt. U kunt ook op elk moment een nieuwe back-up aanvragen of de nieuwste back-up downloaden van Mijn Account Domeinen Aliassen. Als u besluit over te stappen naar een andere e-mailservice, kunt u uw mailboxen en back-ups op elk gewenst moment eenvoudig migreren, downloaden, exporteren en opschonen.

Technologieën

Databases

We hebben andere mogelijke lagen voor databaseopslag onderzocht, maar geen enkele voldeed zo goed aan onze eisen als SQLite:

DatabaseVersleuteling in rustIn de zandbak BrievenbussenLicentieOveral gebruikt
SQLiet✅Ja met SQLite3Meerdere cijfers✅ Publiek domein
MongoDB"Alleen beschikbaar in MongoDB Enterprise"❌ Relationele database❌AGPL en SSPL-1.0
rqlietAlleen netwerk❌ Relationele databaseMIT
dqlietNiet getest en nog niet ondersteund?Niet getest en nog niet ondersteund?LGPL-3.0-only
PostgreSQLJa❌ Relationele databasePostgreSQL (gelijkwaardig aan BSD of MIT)
MariaDBAlleen voor InnoDB❌ Relationele databaseGPLv2 en BUSL-1.1
KakkerlakDBFunctie alleen voor bedrijven❌ Relationele databaseBUSL-1.1 en anderen

Hier is een blogpost waarin verschillende SQLite-databaseopslagopties worden vergeleken in de tabel hierboven.

Veiligheid

Wij gebruiken te allen tijde encryptie-in-rust (AES-256), encryptie-in-transit (TLS), DNS via HTTPS ("DoH") met 🍊 Mandarijn, en vierkant (ChaCha20-Poly1305) encryptie op mailboxen. Daarnaast maken we gebruik van op tokens gebaseerde twee-factor-authenticatie (in tegenstelling tot sms, wat verdacht is). man-in-the-middle-aanvallen), geroteerde SSH-sleutels met root-toegang uitgeschakeld, exclusieve toegang tot servers via beperkte IP-adressen, en meer.

In het geval van een boze meid aanval of een malafide werknemer van een externe leverancier, uw mailbox kan nog steeds alleen worden geopend met uw gegenereerde wachtwoord. Wees gerust, we vertrouwen niet op andere externe leveranciers dan onze SOC Type 2-klachtenserverproviders van Cloudflare, Digital Ocean en Vultr.

Ons doel is om er zo weinig mogelijk te hebben enig punt van mislukkingen als mogelijk.

Brievenbussen

tldr; Onze IMAP-servers gebruiken individueel gecodeerde SQLite-databases voor elk van uw mailboxen.

SQLite is extreem populair ingebouwde database – deze draait momenteel op uw telefoon en computer – en gebruikt door bijna alle belangrijke technologieën.

Op onze gecodeerde servers is er bijvoorbeeld een SQLite-databasemailbox voor linux@example.com, info@example.com, hello@example.com enzovoort – één voor elk als a .sqlite databasebestand. We geven de databasebestanden ook geen naam met het e-mailadres – in plaats daarvan gebruiken we BSON ObjectID en unieke gegenereerde UUID's die niet delen van wie de mailbox is of onder welk e-mailadres deze staat (bijv. 353a03f21e534321f5d6e267.sqlite).

Elk van deze databases wordt zelf gecodeerd met uw wachtwoord (dat alleen u heeft). vierkant (ChaCha20-Poly1305). Dit betekent dat uw mailboxen individueel gecodeerd, op zichzelf staand, in de zandbaken draagbaar.

We hebben SQLite verfijnd met het volgende PRAGMA:

PRAGMADoel
cipher=chacha20ChaCha20-Poly1305 SQLite-database-encryptie. Referentie better-sqlite3-multiple-ciphers onder Projecten voor meer inzicht.
key="****************"Dit is uw gedecodeerde, alleen in het geheugen opgeslagen wachtwoord dat via de IMAP-verbinding van uw e-mailclient met onze server wordt doorgegeven. Voor elke lees- en schrijfsessie worden nieuwe database-instances gemaakt en gesloten (om sandboxing en isolatie te garanderen).
journal_model=WALVooruitschrijven-log ("WAL") wat de prestaties verbetert en gelijktijdige leestoegang mogelijk maakt.
busy_timeout=5000Voorkomt schrijfvergrendelingsfouten terwijl er andere schrijfacties plaatsvinden.
synchronous=NORMALVerhoogt de duurzaamheid van transacties zonder risico op gegevenscorruptie.
foreign_keys=ONDwingt af dat verwijzingen naar externe sleutels (bijvoorbeeld een relatie van de ene tabel naar de andere) worden afgedwongen. Standaard is dit niet ingeschakeld in SQLite, maar voor validatie en gegevensintegriteit moet dit ingeschakeld zijn.
encoding='UTF-8'Standaardcodering te gebruiken om het gezond verstand van de ontwikkelaar te garanderen.

Alle andere standaardinstellingen zijn afkomstig van SQLite zoals opgegeven in de officiële PRAGMA-documentatie.

Gelijktijdigheid

tldr; We gebruiken rclone en WebSocket voor gelijktijdige lees- en schrijfbewerkingen naar uw gecodeerde SQLite-mailboxen.

Leest

Mogelijk wordt het probleem opgelost door uw e-mailclient op uw telefoon imap.forwardemail.net naar een van onze Digital Ocean IP-adressen – en uw desktopclient kan een afzonderlijk IP-adres van een ander IP-adres omzetten aanbieder allemaal samen.

Ongeacht met welke IMAP-server uw e-mailclient verbinding maakt, we willen dat de verbinding in realtime en met 100% nauwkeurigheid uit uw database leest:

  • Dit wordt bereikt door gebruik te maken van rclone met --vfs-cache-mode off (de standaard).

  • In plaats van de lokale schijfcache te gebruiken, wordt de cache in realtime rechtstreeks vanaf de externe mount (uw database) gelezen.

  • In het geval dat het lokale bestand niet kan worden gevonden, geeft dit dat aan rclone Kan niet worden geactiveerd of heeft een probleem. In dit geval gebruiken we een WebSocket fallback voor leesbewerkingen (waardoor de prestaties enigszins afnemen, maar nog steeds de integriteit van de service behouden blijft).

  • Al onze servers zijn zo geconfigureerd dat ze consistent worden geactiveerd en waarschuwen ons in realtime bij eventuele fouten.

Schrijft

Schrijven naar uw database is een beetje anders – aangezien SQLite een ingebedde database is en uw mailbox standaard in één bestand staat.

We hadden opties onderzocht zoals litestream, rqlite, en dqlite hieronder – maar geen van deze voldeed aan onze eisen.

Om schrijfbewerkingen uit te voeren met write-ahead-logging ("WAL") ingeschakeld – we moeten ervoor zorgen dat slechts één server ("Primair") hiervoor verantwoordelijk is. WAL versnelt de gelijktijdigheid drastisch en maakt één schrijver en meerdere lezers mogelijk.

De Primary draait op de dataservers met de gekoppelde volumes die de gecodeerde mailboxen bevatten. Vanuit distributieoogpunt zou je alle individuele IMAP-servers erachter kunnen overwegen imap.forwardemail.net als secundaire servers ("Secundair").

Wij realiseren tweerichtingscommunicatie met WebSockets:

  • Primaire servers gebruiken een exemplaar van ws'S WebSocketServer server.
  • Secundaire servers gebruiken een exemplaar van ws'S WebSocket cliënt waarmee is omwikkeld websocket-zoals beloofd en opnieuw verbinden-websocket. Deze twee wikkels zorgen ervoor dat de WebSocket maakt opnieuw verbinding en kan gegevens verzenden en ontvangen voor specifieke databaseschrijfbewerkingen.

Back-ups

tldr; Er worden dagelijks back-ups gemaakt van uw gecodeerde mailboxen. U kunt ook direct een nieuwe back-up aanvragen of op elk gewenst moment de nieuwste back-up downloaden Mijn Account Domeinen Aliassen.

Voor back-ups gebruiken we eenvoudigweg SQLite VACUUM INTO elke dag een opdracht uitvoeren tijdens de verwerking van IMAP-opdrachten, waarbij gebruik wordt gemaakt van uw gecodeerde wachtwoord via een IMAP-verbinding in het geheugen. Back-ups worden opgeslagen als er geen bestaande back-up wordt gedetecteerd of als de SHA-256 hash van het bestand is gewijzigd in vergelijking met de meest recente back-up.

Merk op dat we de gebruiken VACUUM INTO commando in tegenstelling tot het ingebouwde backup opdracht omdat als een pagina wordt gewijzigd tijdens een backup commandobewerking, dan moet het opnieuw beginnen. De VACUUM INTO commando maakt een momentopname. Zie deze opmerkingen op GitHub en Hackernieuws voor meer inzicht.

Daarnaast gebruiken wij VACUUM INTO in tegenstelling tot backup, omdat de backup commando zou de database gedurende een korte periode onversleuteld laten rekey wordt aangeroepen (zie dit GitHub opmerking voor inzicht).

De secundaire zal de primaire instrueren over de WebSocket verbinding om de back-up uit te voeren – en de Primary ontvangt dan de opdracht om dit te doen en zal vervolgens:

  1. Maak verbinding met uw gecodeerde mailbox.
  2. Schaf een schrijfvergrendeling aan.
  3. Voer een WAL-controlepunt uit via wal_checkpoint(PASSIVE).
  4. Voer de ... uit VACUUM INTO SQLite-opdracht.
  5. Zorg ervoor dat het gekopieerde bestand kan worden geopend met het gecodeerde wachtwoord (safeguard/dummyproofing).
  6. Upload het naar Cloudflare R2 voor opslag (of uw eigen provider indien gespecificeerd).
  7. Comprimeer het resulterende back-upbestand met gzip.
  8. Upload het naar Cloudflare R2 voor opslag (of uw eigen provider indien gespecificeerd).

Houd er rekening mee dat uw mailboxen gecodeerd zijn – en hoewel we IP-beperkingen en andere authenticatiemaatregelen hebben getroffen voor WebSocket-communicatie – kunt u er in het geval van een slechte actor zeker van zijn dat, tenzij de WebSocket-payload uw IMAP-wachtwoord heeft, deze uw database niet kan openen .

Er wordt momenteel slechts één back-up per mailbox opgeslagen, maar in de toekomst kunnen we herstel op een bepaald tijdstip aanbieden ("PITR").

Onze IMAP-servers ondersteunen de SEARCH commando met complexe query's, reguliere expressies en meer.

Snelle zoekprestaties zijn te danken aan FTS5 en sqlite-regex.

Wij slaan op Date waarden in de SQLite-mailboxen als ISO 8601 snaren via Date.prototype.toISOString (met UTC-tijdzone zodat gelijkheidsvergelijkingen correct functioneren).

Er worden ook indexen opgeslagen voor alle eigendommen die in zoekopdrachten voorkomen.

Projecten

Hier is een tabel met de projecten die we gebruiken in onze broncode en ons ontwikkelingsproces (alfabetisch gesorteerd):

ProjectDoel
AnsibelDevOps-automatiseringsplatform voor het eenvoudig onderhouden, schalen en beheren van onze volledige servervloot.
BreeTaakplanner voor Node.js en JavaScript met cron, dates, ms, later en mensvriendelijke ondersteuning.
CabineOntwikkelaarsvriendelijke JavaScript- en Node.js-logboekbibliotheek met veiligheid en privacy in gedachten.
LaatNode.js-framework dat ons volledige architectuur- en technisch ontwerp aanstuurt met MVC en meer.
MongoDBNoSQL-databaseoplossing die we gebruiken voor het opslaan van alle andere gegevens buiten mailboxen (bijvoorbeeld uw account, instellingen, domeinen en aliasconfiguraties).
MangoestMongoDB objectdocument modellering ("ODM") die we in onze hele stapel gebruiken. We hebben speciale helpers geschreven waarmee we gewoon kunnen blijven gebruiken Mongoes met SQLite 🎉
Node.jsNode.js is de open-source, platformonafhankelijke JavaScript-runtime-omgeving die al onze serverprocessen uitvoert.
Opmerking mailerNode.js-pakket voor het verzenden van e-mails, het maken van verbindingen en meer. Wij zijn officieel sponsor van dit project.
OpnieuwIn-memory database voor caching, publicatie-/abonneerkanalen en DNS via HTTPS-verzoeken.
SQLite3Meerdere cijfersVersleutelingsextensie voor SQLite waarmee volledige databasebestanden kunnen worden gecodeerd (inclusief het write-ahead-log ("WAL"), journaal, terugdraaien, ...).
SQLiteStudioVisuele SQLite-editor (die u ook kunt gebruiken) om ontwikkelingsmailboxen te testen, downloaden en bekijken.
SQLietIngebouwde databaselaag voor schaalbare, onafhankelijke, snelle en veerkrachtige IMAP-opslag.
SpamscannerNode.js antispam-, e-mailfilter- en phishing-preventietool (ons alternatief voor Spam-moordenaar en rspamd).
MandarijnDNS via HTTPS-verzoeken met Node.js en caching met Redis – wat zorgt voor wereldwijde consistentie en nog veel meer.
DondervogelOns ontwikkelteam gebruikt dit (en beveelt dit ook aan) als de voorkeurs-e-mailclient die u wilt gebruiken met E-mail doorsturen.
UTMOns ontwikkelingsteam gebruikt deze virtuele machines voor iOS en macOS om verschillende e-mailclients (parallel) te testen met onze IMAP- en SMTP-servers.
UbuntuModern open-source Linux-gebaseerd serverbesturingssysteem dat onze gehele infrastructuur aandrijft.
Wilde eendIMAP-serverbibliotheek – zie de opmerkingen hierover deduplicatie van bijlagen en Ondersteuning voor IMAP-protocol.
beter-sqlite3-meerdere-cijfersSnelle en eenvoudige API-bibliotheek waarmee Node.js programmatisch met SQLite3 kan communiceren.
e-mailsjablonenOntwikkelaarsvriendelijk e-mailframework voor het maken, bekijken en verzenden van aangepaste e-mails (bijvoorbeeld accountmeldingen en meer).
json-sqlSQL-querybouwer met syntaxis in Mongo-stijl. Dit bespaart ons ontwikkelingsteam tijd, omdat we over de hele stapel in Mongo-stijl kunnen blijven schrijven met een database-agnostische aanpak. Het helpt ook om SQL-injectieaanvallen te voorkomen door queryparameters te gebruiken.
knex-schema-inspecteurSQL-hulpprogramma om informatie over het bestaande databaseschema te extraheren. Hierdoor kunnen we eenvoudig valideren dat alle indices, tabellen, kolommen, beperkingen en meer geldig zijn en 1:1 met hoe ze zouden moeten zijn. We hebben zelfs geautomatiseerde helpers geschreven om nieuwe kolommen en indexen toe te voegen als er wijzigingen worden aangebracht in databaseschema's (met ook uiterst gedetailleerde foutwaarschuwingen).
knexSQL-querybuilder die we alleen gebruiken voor databasemigraties en schemavalidatie knex-schema-inspector.
mandarijn-Automatisch ik18n zinsvertaling met ondersteuning voor het gebruik van Markdown Google Cloud-vertaal-API.
mx-connectNode.js-pakket om verbindingen met MX-servers op te lossen en tot stand te brengen en fouten af te handelen.
pm2Node.js productieprocesmanager met ingebouwde load balancer (verfijnd voor prestaties).
smtp-serverSMTP-serverbibliotheek – we gebruiken deze voor onze mailuitwisseling ("MX") en uitgaande SMTP-servers.
ImapTestHandig hulpmiddel voor het testen van IMAP-servers aan de hand van benchmarks en RFC-specificatie IMAP-protocolcompatibiliteit. Dit project is gemaakt door de Duiventil team (een actieve open-source IMAP- en POP3-server uit juli 2002). Met deze tool hebben we onze IMAP-server uitgebreid getest.

U kunt andere projecten vinden waarin we gebruiken onze broncode op GitHub.

Aanbieders

AanbiederDoel
WolkflareDNS-provider, gezondheidscontroles, load balancers en back-upopslag gebruiken Wolkflare R2.
Digitale OceaanDedicated serverhosting, SSD-blokopslag en beheerde databases.
vultrDedicated serverhosting en SSD-blokopslag.

Gedachten

Principes

Forward Email is ontworpen volgens deze principes:

  1. Wees altijd ontwikkelaarsvriendelijk, gericht op beveiliging en privacy, en transparant.
  2. Houd u aan MVC, Unix, KISS, DRY, YAGNI, Twaalf Factor, Occam's scheermes, en hondenvoer
  3. Richt je op de scrappy, bootstrapped en ramen-winstgevend ontwikkelaar

Experimenten

tldr; Uiteindelijk is het gebruik van S3-compatibele objectopslag en/of virtuele tabellen technisch niet haalbaar vanwege prestatieredenen en gevoelig voor fouten vanwege geheugenbeperkingen.

We hebben een paar experimenten gedaan in de aanloop naar onze uiteindelijke SQLite-oplossing, zoals hierboven besproken.

Een daarvan was om te proberen het te gebruiken rcloon en SQLite samen met een S3-compatibele opslaglaag.

Dat experiment heeft ertoe geleid dat we randgevallen rondom rclone, SQLite en VFS gebruik:

  • Als u inschakelt --vfs-cache-mode writes flag met rclone, dan zijn de leesbewerkingen in orde, maar worden de schrijfbewerkingen in de cache opgeslagen.
    • Als u meerdere wereldwijd verspreide IMAP-servers heeft, zal de cache op deze servers uitgeschakeld zijn, tenzij u een enkele schrijver en meerdere luisteraars heeft (bijvoorbeeld een pub/sub-benadering).
    • Dit is ongelooflijk complex en het toevoegen van dergelijke extra complexiteit zal resulteren in meer single points of Failure.
    • S3-compatibele opslagproviders ondersteunen geen gedeeltelijke bestandswijzigingen – dat wil zeggen elke wijziging van de .sqlite bestand zal resulteren in een volledige wijziging en opnieuw uploaden van de database.
    • Andere oplossingen zoals rsync bestaan, maar ze zijn niet gericht op write-ahead-log ("WAL") ondersteuning – dus hebben we Litestream beoordeeld. Gelukkig codeert ons versleutelingsgebruik de WAL bestanden voor ons, dus daarvoor zijn we niet afhankelijk van Litestream. We hadden echter nog geen vertrouwen in Litestream voor productiegebruik en hebben daarover hieronder een paar opmerkingen.
    • Met behulp van deze optie van --vfs-cache-mode writes (de alleen manier om SQLite te gebruiken rclone voor schrijfbewerkingen) zal proberen de hele database helemaal opnieuw in het geheugen te kopiëren – het verwerken van één mailbox van 10 GB is prima, maar het verwerken van meerdere mailboxen met een buitengewoon hoge opslagcapaciteit zal ervoor zorgen dat de IMAP-servers tegen geheugenbeperkingen aanlopen en ENOMEM fouten, segmentatiefouten en datacorruptie.
  • Als u SQLite probeert te gebruiken Virtuele tafels (bijv. gebruiken s3db) om gegevens live te hebben op een S3-compatibele opslaglaag, dan zul je nog een aantal problemen tegenkomen:
    • Lezen en schrijven zal extreem traag zijn, omdat S3 API-eindpunten moeten worden geraakt met HTTP GET, PUT, HEAD, en POST methoden.
    • Uit ontwikkelingstests is gebleken dat het overschrijden van meer dan 500.000 tot 1 miljoen records op glasvezelinternet nog steeds wordt beperkt door de doorvoersnelheid van schrijven en lezen naar S3-compatibele providers. Onze ontwikkelaars hebben bijvoorbeeld gelopen for lussen om beide sequentiële SQL uit te voeren INSERT verklaringen en verklaringen die grote hoeveelheden gegevens in bulk schreven. In beide gevallen was de uitvoering verbluffend traag.
    • Virtuele tafels kunnen geen indexen hebben, ALTER TABLE verklaringen, en ander beperkingen – wat leidt tot vertragingen van 1-2 minuten of meer, afhankelijk van de hoeveelheid gegevens.
    • Objecten werden onversleuteld opgeslagen en er is geen ondersteuning voor native versleuteling beschikbaar.
  • We hebben ook onderzoek gedaan naar het gebruik sqlite-s3vfs die conceptueel en technisch vergelijkbaar is met het vorige opsommingsteken (dus dezelfde problemen heeft). Een mogelijkheid zou zijn om gebruik te maken van een gewoonte sqlite3 build verpakt met encryptie zoals wxSQLite3 (die we momenteel gebruiken in onze oplossing hierboven) door het installatiebestand bewerken.
  • Een andere mogelijke aanpak was het gebruik van de multiplex-extensie, maar dit heeft een beperking van 32 GB en zou complexe bouw- en ontwikkelingsproblemen vereisen.
  • ALTER TABLE -instructies zijn vereist (dus dit sluit het gebruik van virtuele tabellen volledig uit). Wij hebben nodig ALTER TABLE uitspraken om onze haak te slaan knex-schema-inspector om goed te werken – wat ervoor zorgt dat gegevens niet beschadigd raken en opgehaalde rijen kunnen worden geconverteerd naar geldige documenten volgens onze mongoose schemadefinities (waaronder beperking, variabel type en willekeurige gegevensvalidatie).
  • Bijna alle S3-compatibele projecten gerelateerd aan SQLite in de open-sourcegemeenschap zijn in Python (en niet in JavaScript, dat we voor 100% van onze stapel gebruiken).
  • Compressiebibliotheken zoals sqlite-zstd (zien opmerkingen) ziet er veelbelovend uit, maar is mogelijk nog niet klaar voor productiegebruik. In plaats daarvan wordt compressie aan de applicatiezijde toegepast op gegevenstypen zoals String, Object, Map, Array, Set, en Buffer wordt een schonere en eenvoudigere aanpak (en is ook gemakkelijker te migreren, omdat we een Boolean vlag of kolom – of zelfs gebruiken PRAGMA user_version=1 voor compressie of user_version=0 voor geen compressie als database-metagegevens).
    • Gelukkig hebben we deduplicatie van bijlagen al geïmplementeerd in onze IMAP-serveropslag – daarom zal elk bericht met dezelfde bijlage geen kopie van de bijlage bewaren – in plaats daarvan wordt één bijlage opgeslagen voor meerdere berichten en threads in een mailbox (en een buitenlandse referentie wordt vervolgens gebruikt).
  • Het project Litestream, een SQLite-replicatie- en back-upoplossing, is veelbelovend en we zullen het waarschijnlijk in de toekomst gebruiken.
  • Back-upherstel moet wrijvingsloos en triviaal zijn. Met behulp van een oplossing zoals MongoDB met mongodump en mongoexport is niet alleen vervelend, maar ook tijdrovend en heeft configuratiecomplexiteit.
    • SQLite-databases maken het eenvoudig (het is één bestand).
    • We wilden een oplossing ontwerpen waarbij gebruikers hun mailbox konden pakken en op elk moment konden vertrekken.
      • Eenvoudige Node.js-opdrachten om fs.unlink('mailbox.sqlite')) en het wordt permanent verwijderd uit de schijfopslag.
      • We kunnen op dezelfde manier een S3-compatibele API met HTTP gebruiken DELETE om eenvoudig snapshots en back-ups voor gebruikers te verwijderen.
    • SQLite was de eenvoudigste, snelste en meest kosteneffectieve oplossing.

Gebrek aan alternatieven

Voor zover wij weten zijn geen andere e-maildiensten op deze manier ontworpen en zijn ze ook niet open source.

Wij denk dat dit misschien te wijten is naar bestaande e-maildiensten met verouderde technologie in productie spaghetti-code 🍝.

De meeste, zo niet alle, bestaande e-mailserviceproviders zijn gesloten bron of adverteren als open bron. maar in werkelijkheid is alleen hun front-end open source.

Het meest gevoelige deel van e-mail (de daadwerkelijke opslag/IMAP/SMTP-interactie) gebeurt allemaal op de back-end (server), en niet aan de front-end (klant).

Probeer E-mail doorsturen eens

Schrijf je vandaag nog in via https://forwardemail.net! 🚀