Szyfrowane skrzynki pocztowe SQLite dla Twojej prywatności
W przeciwieństwie do innych usług e-mailowych zapewniamy, że tylko Ty masz stały dostęp do swojej skrzynki pocztowej .
- Strona wyszukiwania
- Spis treści
Przedmowa
tldr; Nasza usługa e-mail jest W 100% otwarte i zorientowane na prywatność dzięki bezpiecznym i szyfrowanym skrzynce pocztowej SQLite.
Dopóki nie wystartowaliśmy Obsługa protokołu IMAP, użyliśmy MongoDB do naszych stałych potrzeb w zakresie przechowywania danych.
Ta technologia jest niesamowita i nadal jej używamy – ale aby mieć szyfrowanie w MongoDB, musisz skorzystać z dostawcy oferującego MongoDB Enterprise, takiego jak Digital Ocean lub Mongo Atlas – lub zapłacić za licencję dla przedsiębiorstw (i później muszą pracować nad opóźnieniami zespołu sprzedaży).
Nasz zespół o godz Prześlij dalej e-mail potrzebował przyjaznego dla programistów, skalowalnego, niezawodnego i szyfrowanego rozwiązania do przechowywania skrzynek pocztowych IMAP. Jako twórcy oprogramowania open source korzystanie z technologii wymagającej uiszczenia opłaty licencyjnej, aby móc korzystać z funkcji szyfrowania w stanie spoczynku, było sprzeczne z nasze zasady – dlatego eksperymentowaliśmy, badaliśmy i opracowaliśmy od podstaw nowe rozwiązanie, aby sprostać tym potrzebom.
Zamiast korzystać ze wspólnej bazy danych do przechowywania Twoich skrzynek pocztowych, przechowujemy je indywidualnie i szyfrujemy Twoim hasłem (które masz tylko Ty). Nasza usługa e-mail jest tak bezpieczna, że jeśli zapomnisz hasła, utracisz skrzynkę pocztową (i musisz odzyskać dane za pomocą kopii zapasowych offline lub zacząć od nowa).
Czytaj dalej, gdy zagłębimy się poniżej w porównanie dostawców usług e-mail, jak działa nasz serwis, nasz stos technologii, i więcej.
Porównanie dostawców usług e-mail
Jesteśmy jedynym dostawcą usług e-mail w pełni open source i zorientowanym na prywatność, który przechowuje indywidualnie zaszyfrowane skrzynki pocztowe SQLite, oferuje nieograniczoną liczbę domen, aliasów i użytkowników oraz obsługuje wychodzące SMTP, IMAP i POP3:
W przeciwieństwie do innych dostawców poczty e-mail, w przypadku usługi Forward Email nie musisz płacić za przechowywanie w oparciu o domenę lub alias. Miejsce na dane jest współdzielone na całym koncie – więc jeśli masz wiele niestandardowych nazw domen i wiele aliasów na każdej z nich, jesteśmy dla Ciebie idealnym rozwiązaniem. Pamiętaj, że w razie potrzeby możesz nadal egzekwować limity miejsca na domenę lub alias.
Przeczytaj Porównanie usług e-mail
Jak to działa
-
Korzystając z klienta poczty e-mail, takiego jak Apple Mail, Thunderbird, Gmail lub Outlook – łączysz się z naszym bezpiecznym IMAP serwery korzystające z Twojej nazwy użytkownika i hasła:
- Twoja nazwa użytkownika to pełny alias z Twoją domeną, np
hello@example.com
. - Twoje hasło jest generowane losowo i wyświetlane tylko przez 30 sekund po kliknięciu Wygeneruj hasło z Moje konto Domeny Skróty.
- Twoja nazwa użytkownika to pełny alias z Twoją domeną, np
-
Po nawiązaniu połączenia Twój klient poczty e-mail wyśle wiadomość Polecenia protokołu IMAP do naszego serwera IMAP, aby synchronizować skrzynkę pocztową. Obejmuje to pisanie i przechowywanie wersji roboczych wiadomości e-mail oraz inne czynności, które możesz wykonać (np. oznaczenie wiadomości e-mail jako ważnej lub oznaczenie wiadomości e-mail jako spam/śmieci).
-
Serwery wymiany poczty (powszechnie zwane serwerami „MX”) odbierają nowe przychodzące wiadomości e-mail i przechowują je w Twojej skrzynce pocztowej. Gdy tak się stanie, Twój klient poczty e-mail otrzyma powiadomienie i zsynchronizuje Twoją skrzynkę pocztową. Nasze serwery wymiany poczty mogą przekazywać Twoją pocztę e-mail do jednego lub większej liczby odbiorców (w tym webhooki), przechowuj u nas swoje wiadomości e-mail w zaszyfrowanym magazynie IMAP, lub oba!
Chcesz dowiedzieć się więcej? Czytać jak skonfigurować przekazywanie wiadomości e-mail, jak działa nasza usługa wymiany pocztylub obejrzyj nasi przewodnicy.
-
Za kulisami nasz projekt bezpiecznego przechowywania wiadomości e-mail działa na dwa sposoby, aby Twoje skrzynki pocztowe były szyfrowane i dostępne tylko dla Ciebie:
-
Po otrzymaniu nowej poczty od nadawcy nasze serwery wymiany poczty zapisują ją w indywidualnej, tymczasowej i zaszyfrowanej skrzynce pocztowej.
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!
-
Kiedy łączysz się z naszym serwerem IMAP za pomocą swojego klienta poczty e-mail, Twoje hasło jest następnie szyfrowane w pamięci i używane do odczytu i zapisu w Twojej skrzynce pocztowej. Z Twojej skrzynki pocztowej można czytać i zapisywać tylko przy użyciu tego hasła. Pamiętaj, że ponieważ jesteś jedyną osobą znającą to hasło, tylko ty może czytać i pisać w Twojej skrzynce pocztowej, gdy uzyskujesz do niej dostęp. Następnym razem, gdy Twój klient poczty e-mail będzie próbował odpytać pocztę lub przeprowadzić synchronizację, nowe wiadomości zostaną przeniesione z tymczasowej skrzynki pocztowej i zapisane w rzeczywistym pliku skrzynki pocztowej przy użyciu podanego hasła. Pamiętaj, że ta tymczasowa skrzynka pocztowa jest później czyszczona i usuwana, dzięki czemu wiadomości znajdują się tylko w Twojej skrzynce pocztowej chronionej hasłem.
-
Jeśli jesteś podłączony do protokołu IMAP (np. korzystasz z klienta poczty e-mail, takiego jak Apple Mail lub Thunderbird), nie musimy zapisywać danych na dysku tymczasowym. Zamiast tego zostanie pobrane i użyte Twoje hasło IMAP zaszyfrowane w pamięci. W czasie rzeczywistym, gdy próbujemy dostarczyć Ci wiadomość, wysyłamy żądanie WebSocket do wszystkich serwerów IMAP z pytaniem, czy mają dla Ciebie aktywną sesję (jest to część pobierania), a następnie przekazujemy to dalej zaszyfrowane hasło w pamięci – dzięki temu nie musimy pisać do tymczasowej skrzynki pocztowej, możemy pisać do Twojej rzeczywistej zaszyfrowanej skrzynki pocztowej, używając zaszyfrowanego hasła.
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!
-
-
Kopie zapasowe zaszyfrowanych skrzynek pocztowych są robione codziennie. Możesz także w dowolnym momencie poprosić o utworzenie nowej kopii zapasowej lub pobrać najnowszą kopię zapasową z witryny Moje konto Domeny Skróty. Jeśli zdecydujesz się przejść na inną usługę e-mail, możesz w dowolnym momencie łatwo migrować, pobierać, eksportować i czyścić swoje skrzynki pocztowe i kopie zapasowe.
Technologie
Bazy danych
Zbadaliśmy inne możliwe warstwy przechowywania baz danych, jednak żadna nie spełniła naszych wymagań w takim stopniu jak SQLite:
Baza danych | Szyfrowanie w stanie spoczynku | W piaskownicy Skrzynki pocztowe | Licencja | Używany wszędzie |
---|---|---|---|---|
Sqlite ⭐ | ✅Tak z SQLite3MultipleCiphers | ✅ | ✅ Domena publiczna | ✅ |
MongoDB | ❌ „Dostępne tylko w MongoDB Enterprise” | ❌ Relacyjna baza danych | ❌ AGPL i SSPL-1.0 | ❌ |
rqlite | ❌ Tylko sieć | ❌ Relacyjna baza danych | ✅ MIT | ❌ |
dqlite | ❌ Nieprzetestowany i jeszcze nieobsługiwany? | ❌ Nieprzetestowany i jeszcze nieobsługiwany? | ✅ LGPL-3.0-only | ❌ |
PostgreSQL | ✅ tak | ❌ Relacyjna baza danych | ✅ PostgreSQL (podobny do BSD lub MIT ) | ❌ |
MariaDB | ✅ Tylko dla InnoDB | ❌ Relacyjna baza danych | ✅ GPLv2 oraz BUSL-1.1 | ❌ |
KaraluchDB | ❌ Funkcja dostępna tylko dla przedsiębiorstw | ❌ Relacyjna baza danych | ❌ BUSL-1.1 i inni | ❌ |
Tutaj jest wpis na blogu porównujący kilka opcji przechowywania baz danych SQLite w tabeli powyżej.
Bezpieczeństwo
Cały czas używamy szyfrowanie w stanie spoczynku (AES-256), szyfrowanie w transporcie (TLS), DNS przez HTTPS („DoH”) za pomocą 🍊 Mandarynka, oraz kwadrat (ChaCha20-Poly1305) szyfrowanie skrzynek pocztowych. Dodatkowo stosujemy uwierzytelnianie dwuskładnikowe oparte na tokenach (w przeciwieństwie do SMS-ów, które mogą być podejrzane). ataki typu man-in-the-middle), obrócone klucze SSH z wyłączonym dostępem roota, wyłącznym dostępem do serwerów poprzez zastrzeżone adresy IP i nie tylko.
W przypadku atak złej pokojówki lub nieuczciwego pracownika od zewnętrznego dostawcy, nadal możesz otworzyć swoją skrzynkę pocztową tylko za pomocą wygenerowanego hasła. Możesz mieć pewność, że nie polegamy na żadnych zewnętrznych dostawcach innych niż nasi dostawcy serwerów skarg SOC typu 2, takich jak Cloudflare, Digital Ocean i Vultr.
Naszym celem jest mieć ich jak najmniej pojedynczy punkt awarii jak to możliwe.
Skrzynki pocztowe
tldr; Nasze serwery IMAP korzystają z indywidualnie zaszyfrowanych baz danych SQLite dla każdej Twojej skrzynki pocztowej.
SQLite jest niezwykle popularny wbudowana baza danych – aktualnie działa na Twoim telefonie i komputerze – i wykorzystywane przez prawie wszystkie główne technologie.
Na przykład na naszych zaszyfrowanych serwerach znajduje się skrzynka pocztowa bazy danych SQLite linux@example.com
, info@example.com
, hello@example.com
i tak dalej – po jednym dla każdego jako a .sqlite
plik bazy danych. Nie nazywamy również plików bazy danych adresem e-mail – zamiast tego używamy BSON ObjectID i wygenerowanych unikalnych identyfikatorów UUID, które nie informują, do kogo należy skrzynka pocztowa ani pod jakim adresem e-mail się znajduje (np. 353a03f21e534321f5d6e267.sqlite
).
Każda z tych baz danych jest szyfrowana przy użyciu Twojego hasła (które tylko Ty posiadasz). kwadrat (ChaCha20-Poly1305). Oznacza to, że Twoje skrzynki pocztowe są indywidualnie szyfrowane, samodzielne, piaskownicai przenośny.
Dopracowaliśmy SQLite w następujący sposób PRAGMA:
PRAGMA | Zamiar |
---|---|
cipher=chacha20 | Szyfrowanie bazy danych SQLite ChaCha20-Poly1305. Odniesienie better-sqlite3-multiple-ciphers pod Projektowanie aby uzyskać więcej informacji. |
key="****************" | To jest Twoje odszyfrowane hasło przechowywane wyłącznie w pamięci, które jest przesyłane przez połączenie IMAP Twojego klienta poczty e-mail z naszym serwerem. Dla każdej sesji odczytu i zapisu tworzone są i zamykane nowe instancje bazy danych (w celu zapewnienia piaskownicy i izolacji). |
journal_model=WAL | Dziennik zapisu z wyprzedzeniem („WAL") co zwiększa wydajność i umożliwia równoczesny dostęp do odczytu. |
busy_timeout=5000 | Zapobiega błędom blokady zapisu podczas gdy inne zapisy mają miejsce. |
synchronous=NORMAL | Zwiększa trwałość transakcji bez ryzyka uszkodzenia danych. |
foreign_keys=ON | Wymusza wymuszanie odwołań do klucza obcego (np. relacji z jednej tabeli do drugiej). Domyślnie nie jest to włączone w SQLite, ale w celu sprawdzenia poprawności i integralności danych należy ją włączyć. |
encoding='UTF-8' | Domyślne kodowanie używać, aby zapewnić programistom zdrowy rozsądek. |
Wszystkie pozostałe wartości domyślne pochodzą z SQLite, jak określono w pliku oficjalna dokumentacja PRAGMY.
Konkurencja
tldr; Używamy
WebSocket
do równoczesnych odczytów i zapisów w zaszyfrowanych skrzynkach pocztowych SQLite.
Czyta
Klient poczty e-mail w telefonie może zostać rozwiązany imap.forwardemail.net
na jeden z naszych adresów IP Digital Ocean – a Twój klient stacjonarny może rozpoznać oddzielny adres IP od innego dostawca całkowicie.
Niezależnie od tego, z jakim serwerem IMAP łączy się Twój klient poczty e-mail, chcemy, aby połączenie odczytywało Twoją bazę danych w czasie rzeczywistym ze 100% dokładnością. Odbywa się to poprzez WebSockets.
Pisze
Zapisywanie w bazie danych przebiega nieco inaczej – ponieważ SQLite jest wbudowaną bazą danych, a Twoja skrzynka pocztowa domyślnie znajduje się w jednym pliku.
Rozważaliśmy opcje takie jak litestream
, rqlite
, oraz dqlite
poniżej – jednak żaden z nich nie spełniał naszych wymagań.
Aby wykonać zapisy z rejestrowaniem zapisu z wyprzedzeniem ("WAL„) włączone – musimy upewnić się, że tylko jeden serwer („Podstawowy”) jest za to odpowiedzialny. WAL drastycznie przyspiesza współbieżność i umożliwia jednemu pisarzowi i wielu czytelnikom.
Jednostka podstawowa działa na serwerach danych z zamontowanymi woluminami zawierającymi zaszyfrowane skrzynki pocztowe. Z punktu widzenia dystrybucji można wziąć pod uwagę wszystkie pojedyncze serwery IMAP imap.forwardemail.net
być serwerami dodatkowymi („Dodatkowe”).
Realizujemy dwustronną komunikację z WebSockety:
- Serwery główne korzystają z instancji ws'S
WebSocketServer
serwer. - Serwery dodatkowe korzystają z instancji ws'S
WebSocket
klient, który jest opakowany websocket-zgodnie z obietnicą oraz ponowne łączenie-websocket. Te dwie owijki zapewniają, żeWebSocket
ponownie łączy się i może wysyłać i odbierać dane w ramach określonych zapisów w bazie danych.
Kopie zapasowe
tldr; Kopie zapasowe zaszyfrowanych skrzynek pocztowych są tworzone codziennie. Możesz także natychmiast poprosić o nową kopię zapasową lub pobrać najnowszą kopię zapasową w dowolnym momencie ze strony Moje konto Domeny Skróty.
W przypadku kopii zapasowych po prostu uruchamiamy SQLite VACUUM INTO
polecenie codziennie podczas przetwarzania poleceń IMAP, które wykorzystuje zaszyfrowane hasło z połączenia IMAP w pamięci. Kopie zapasowe są przechowywane, jeśli nie zostanie wykryta żadna istniejąca kopia zapasowa lub jeśli SHA-256 hash w pliku uległ zmianie w porównaniu z najnowszą kopią zapasową.
Zauważ, że używamy VACUUM INTO
polecenie w przeciwieństwie do wbudowanego backup
polecenie, ponieważ jeśli strona zostanie zmodyfikowana podczas a backup
polecenia, to trzeba zacząć od nowa. The VACUUM INTO
polecenie wykona migawkę. Zobacz te komentarze dot GitHub oraz Wiadomości hakerskie aby uzyskać więcej informacji.
Dodatkowo używamy VACUUM INTO
w przeciwieństwie do backup
, ponieważ backup
polecenie pozostawi bazę danych niezaszyfrowaną na krótki okres do rekey
jest wywoływany (zobacz ten GitHub komentarz dla wglądu).
Szkoła Podstawowa będzie instruować Organizację Podstawową w zakresie WebSocket
połączenie w celu wykonania kopii zapasowej – a Podstawowy otrzyma wówczas polecenie, aby to zrobić, a następnie:
- Połącz się ze swoją zaszyfrowaną skrzynką pocztową.
- Zdobądź blokadę zapisu.
- Uruchom punkt kontrolny WAL poprzez
wal_checkpoint(PASSIVE)
. - Uruchom
VACUUM INTO
Polecenie SQLite. - Upewnij się, że skopiowany plik można otworzyć za pomocą zaszyfrowanego hasła (zabezpieczenie/zabezpieczenie fikcyjne).
- Prześlij go do Cloudflare R2 w celu przechowywania (lub u własnego dostawcy, jeśli określono).
Pamiętaj, że Twoje skrzynki pocztowe są szyfrowane — i chociaż mamy ograniczenia IP i inne środki uwierzytelniania dla komunikacji WebSocket — w przypadku złego aktora możesz mieć pewność, że jeśli ładunek WebSocket nie będzie zawierał Twojego hasła IMAP, nie będzie mógł otworzyć Twojej bazy danych .
Obecnie na każdą skrzynkę pocztową przechowywana jest tylko jedna kopia zapasowa, ale w przyszłości możemy zaoferować odzyskiwanie do określonego momentu („PITR").
Szukaj
Nasze serwery IMAP obsługują SEARCH
polecenia ze złożonymi zapytaniami, wyrażeniami regularnymi i nie tylko.
Szybka wydajność wyszukiwania jest dzięki FTS5 oraz sqlite-wyrażenie regularne.
przechowujemy Date
wartości w skrzynkach pocztowych SQLite jako ISO 8601 ciągi przez Date.prototype.toISOString (ze strefą czasową UTC, aby porównania równości działały prawidłowo).
Indeksy są również przechowywane dla wszystkich właściwości występujących w zapytaniach wyszukiwania.
Projektowanie
Oto tabela przedstawiająca projekty, których używamy w naszym kodzie źródłowym i procesie programowania (posortowane alfabetycznie):
Projekt | Zamiar |
---|---|
Ansible | Platforma automatyzacji DevOps do łatwego utrzymywania, skalowania i zarządzania całą naszą flotą serwerów. |
Bree | Harmonogram zadań dla Node.js i JavaScript z cron, date, ms, later i przyjazną dla człowieka obsługą. |
Kabina | Przyjazna dla programistów biblioteka rejestrowania JavaScript i Node.js z myślą o bezpieczeństwie i prywatności. |
Pozwolić | Framework Node.js, który wspiera całą naszą architekturę i projekty inżynieryjne za pomocą MVC i nie tylko. |
MongoDB | Rozwiązanie bazodanowe NoSQL, którego używamy do przechowywania wszystkich innych danych poza skrzynkami pocztowymi (np. Twoje konto, ustawienia, domeny i konfiguracje aliasów). |
Mangusta | Modelowanie dokumentów obiektowych MongoDB („ODM”), którego używamy w całym naszym stosie. Napisaliśmy specjalne pomocniki, które pozwalają nam po prostu kontynuować korzystanie Mangusta z SQLite 🎉 |
Node.js | Node.js to wieloplatformowe środowisko uruchomieniowe JavaScript o otwartym kodzie źródłowym, w którym uruchamiane są wszystkie nasze procesy serwerowe. |
Nodemailer | Pakiet Node.js do wysyłania e-maili, tworzenia połączeń i nie tylko. Jesteśmy oficjalnym sponsorem tego projektu. |
Redisa | Baza danych w pamięci do buforowania, kanałów publikowania/subskrypcji i DNS przez żądania HTTPS. |
SQLite3MultipleCiphers | Rozszerzenie szyfrowania dla SQLite umożliwiające szyfrowanie całych plików bazy danych (w tym dziennika zapisu z wyprzedzeniem („WAL"), dziennik, wycofanie, ...). |
SQLiteStudio | Wizualny edytor SQLite (którego możesz również użyć) do testowania, pobierania i przeglądania skrzynek pocztowych programistów. |
Sqlite | Wbudowana warstwa bazy danych zapewniająca skalowalne, samodzielne, szybkie i odporne przechowywanie IMAP. |
Skaner spamu | Narzędzie antyspamowe, filtrujące pocztę e-mail i zapobiegające phishingowi Node.js (nasza alternatywa dla Zabójca spamu oraz rspamd). |
Mandarynka | DNS przez żądania HTTPS z Node.js i buforowanie przy użyciu Redis – co zapewnia globalną spójność i wiele więcej. |
Ptak piorunowy | Nasz zespół programistów używa tego (i również to zaleca) jako preferowany klient poczty e-mail używany z funkcją przesyłania dalej. |
UTM | Nasz zespół programistów używa tej maszyny wirtualnej do tworzenia maszyn wirtualnych dla iOS i macOS w celu testowania różnych klientów poczty e-mail (równolegle) z naszymi serwerami IMAP i SMTP. |
Ubuntu | Nowoczesny serwerowy system operacyjny typu open source oparty na systemie Linux, który napędza całą naszą infrastrukturę. |
Dzika kaczka | Biblioteka serwerów IMAP – zobacz jej uwagi na deduplikacja załączników oraz Obsługa protokołu IMAP. |
lepsze-sqlite3-wiele-szyfrów | Szybka i prosta biblioteka API dla Node.js do programowej interakcji z SQLite3. |
Szablony wiadomości | Przyjazna dla programistów platforma e-mail do tworzenia, podglądu i wysyłania niestandardowych wiadomości e-mail (np. powiadomień o koncie i nie tylko). |
json-sql | Kreator zapytań SQL wykorzystujący składnię w stylu Mongo. Oszczędza to czas naszego zespołu programistów, ponieważ możemy kontynuować pisanie w stylu Mongo na całym stosie, stosując podejście niezależne od bazy danych. Pomaga także uniknąć ataków polegających na wstrzykiwaniu SQL poprzez użycie parametrów zapytania. |
Inspektor schematu knex | Narzędzie SQL do wyodrębniania informacji o istniejącym schemacie bazy danych. Pozwala nam to łatwo sprawdzić, czy wszystkie indeksy, tabele, kolumny, ograniczenia i inne są prawidłowe i są 1:1 z tym, jak powinny wyglądać. Napisaliśmy nawet automatyczne pomocniki, które dodadzą nowe kolumny i indeksy w przypadku wprowadzenia zmian w schematach baz danych (z niezwykle szczegółowym powiadamianiem o błędach). |
knex | Kreator zapytań SQL, którego używamy tylko do migracji baz danych i sprawdzania poprawności schematu knex-schema-inspector . |
mandarynka | Automatyczny 18n tłumaczenie fraz z obsługą Markdown przy użyciu API tłumaczenia w chmurze Google. |
połączenie mx | Pakiet Node.js do rozwiązywania i nawiązywania połączeń z serwerami MX oraz obsługi błędów. |
2:00 | Menedżer procesów produkcyjnych Node.js z wbudowanym modułem równoważenia obciążenia (dostrojony za wydajność). |
serwer smtp | Biblioteka serwerów SMTP – używamy jej do naszych serwerów wymiany poczty („MX”) i serwerów wychodzących SMTP. |
Test Imap | Przydatne narzędzie do testowania serwerów IMAP pod kątem testów porównawczych i zgodności protokołu IMAP ze specyfikacją RFC. Projekt ten został stworzony przez firmę Gołębnik zespół (aktywny serwer IMAP i POP3 o otwartym kodzie źródłowym od lipca 2002 r.). Za pomocą tego narzędzia dokładnie przetestowaliśmy nasz serwer IMAP. |
Możesz znaleźć inne projekty, w których używamy nasz kod źródłowy na GitHubie.
Dostawcy
Dostawca | Zamiar |
---|---|
Rozbłysk chmur | Dostawca DNS, kontrole stanu, moduły równoważenia obciążenia i miejsce na kopie zapasowe Cloudflare R2. |
Cyfrowy ocean | Hosting serwerów dedykowanych, pamięć blokowa SSD i zarządzane bazy danych. |
Vultr | Hosting serwerów dedykowanych i pamięć blokowa SSD. |
Myśli
Zasady
Przesyłanie wiadomości e-mail zostało zaprojektowane zgodnie z następującymi zasadami:
- Zawsze bądź przyjazny dla programistów, skupiający się na bezpieczeństwie i prywatności oraz przejrzysty.
- Przestrzegaj MVC, Uniksa, KISS, DRY, YAGNI, Dwanaście czynników, Brzytwa Ockhama, oraz karmienie psów
- Celuj w scrappy, bootstrap i ramen-dochodowy deweloper
Eksperymenty
tldr; Ostatecznie korzystanie z pamięci obiektowej i/lub tabel wirtualnych zgodnych z S3 nie jest technicznie wykonalne ze względu na wydajność i jest podatne na błędy z powodu ograniczeń pamięci.
Przeprowadziliśmy kilka eksperymentów prowadzących do ostatecznego rozwiązania SQLite, jak omówiono powyżej.
Jednym z nich była próba użycia rclon i SQLite wraz z warstwą pamięci kompatybilną z S3.
Ten eksperyment doprowadził nas do lepszego zrozumienia i odkrycia przypadków brzegowych związanych z rclone, SQLite i VFS stosowanie:
- Jeśli włączysz
--vfs-cache-mode writes
flag za pomocą rclone, wtedy odczyty będą OK, jednak zapisy będą buforowane.- Jeśli masz wiele serwerów IMAP rozproszonych na całym świecie, pamięć podręczna będzie na nich wyłączona, chyba że masz jednego autora i wielu słuchaczy (np. podejście pub/sub).
- Jest to niezwykle złożone i dodanie dodatkowej złożoności tego typu spowoduje więcej pojedynczych punktów awarii.
- Dostawcy pamięci masowej kompatybilni z S3 nie obsługują częściowych zmian plików – co oznacza jakąkolwiek zmianę pliku
.sqlite
plik spowoduje całkowitą zmianę i ponowne przesłanie bazy danych. - Inne rozwiązania, np
rsync
istnieją, ale nie skupiają się na dzienniku zapisu z wyprzedzeniem („WAL") - więc ostatecznie sprawdziliśmy Litestream. Na szczęście nasze użycie szyfrowania już szyfruje WAL plików za nas, więc nie musimy w tym celu polegać na Litestream. Jednak nie byliśmy jeszcze pewni Litestream do użytku produkcyjnego i poniżej zamieszczamy kilka uwag na ten temat. - Korzystając z tej opcji
--vfs-cache-mode writes
(t tylko sposób na użycie SQLiterclone
do zapisu) podejmie próbę skopiowania całej bazy danych od zera do pamięci – obsługa jednej skrzynki pocztowej o pojemności 10 GB jest OK, jednak obsługa wielu skrzynek pocztowych o wyjątkowo dużej pojemności spowoduje, że serwery IMAP będą miały ograniczenia pamięci iENOMEM
błędy, błędy segmentacji i uszkodzenia danych.
- Jeśli spróbujesz użyć SQLite Wirtualne stoły (np. za pomocą s3db), aby dane znajdowały się w warstwie pamięci kompatybilnej z S3, napotkasz kilka dodatkowych problemów:
- Odczyt i zapis będą bardzo powolne, ponieważ punkty końcowe interfejsu API S3 będą musiały zostać trafione za pomocą protokołu HTTP
GET
,PUT
,HEAD
, orazPOST
metody. - Testy rozwojowe wykazały, że przekraczanie 500K-1M+ rekordów w Internecie światłowodowym jest w dalszym ciągu ograniczone przepustowością zapisu i odczytu dla dostawców kompatybilnych z S3. Na przykład nasi programiści pobiegli
for
pętle do wykonywania obu sekwencyjnych operacji SQLINSERT
instrukcje i te, które masowo zapisywały duże ilości danych. W obu przypadkach występ był zdumiewająco powolny. - Wirtualne stoły nie może mieć indeksów,
ALTER TABLE
wypowiedzi i Inny ograniczenia – co prowadzi do opóźnień sięgających 1-2 minut lub więcej, w zależności od ilości danych. - Obiekty były przechowywane w postaci niezaszyfrowanej i nie jest łatwo dostępna natywna obsługa szyfrowania.
- Odczyt i zapis będą bardzo powolne, ponieważ punkty końcowe interfejsu API S3 będą musiały zostać trafione za pomocą protokołu HTTP
- Zbadaliśmy także użycie sqlite-s3vfs który jest podobny koncepcyjnie i technicznie do poprzedniego punktu (więc ma te same problemy). Jedną z możliwości byłoby użycie zwyczaju
sqlite3
kompilacja owinięta szyfrowaniem, takim jak wxSQLite3 (którego obecnie używamy w naszym rozwiązaniu powyżej) poprzez edycja pliku instalacyjnego. - Innym potencjalnym podejściem było użycie metody przedłużenie multipleksu, jednakże ma to ograniczenie do 32 GB i wymagałoby skomplikowanych problemów związanych z budowaniem i programowaniem.
ALTER TABLE
wymagane są instrukcje (więc całkowicie wyklucza to użycie wirtualnych tabel). PotrzebujemyALTER TABLE
instrukcje, aby nasz hak zknex-schema-inspector
działać poprawnie – co gwarantuje, że dane nie zostaną uszkodzone, a odzyskane wiersze będą mogły zostać przekonwertowane na prawidłowe dokumenty zgodnie z naszymimongoose
definicje schematów (które obejmują ograniczenia, typ zmiennej i dowolną walidację danych).- Prawie wszystkie projekty kompatybilne z S3, związane z SQLite w społeczności open source, są w Pythonie (a nie w JavaScript, którego używamy w 100% naszego stosu).
- Biblioteki kompresji, takie jak sqlite-zstd (Widzieć uwagi) wyglądają obiecująco, ale mogą nie być jeszcze gotowe do użytku produkcyjnego. Zamiast tego kompresja po stronie aplikacji dla typów danych, takich jak
String
,Object
,Map
,Array
,Set
, orazBuffer
będzie czystszym i łatwiejszym podejściem (a także łatwiej jest migrować, ponieważ moglibyśmy przechowywać plikBoolean
flaga lub kolumna – lub nawet użyćPRAGMA
user_version=1
do kompresji lubuser_version=0
bez kompresji jako metadane bazy danych).- Na szczęście w pamięci naszego serwera IMAP wdrożono już funkcję usuwania duplikatów załączników — dlatego w każdej wiadomości z tym samym załącznikiem nie zostanie zachowana kopia załącznika — zamiast tego pojedynczy załącznik jest przechowywany dla wielu wiadomości i wątków w skrzynce pocztowej (a obcy później stosuje się odniesienie).
- Projekt Litestream, będący rozwiązaniem do replikacji i tworzenia kopii zapasowych SQLite, jest bardzo obiecujący i najprawdopodobniej będziemy z niego korzystać w przyszłości.
- Nie chcę dyskredytować autorów (autorów) – ponieważ uwielbiamy ich pracę i wkład w open source już od ponad dziesięciu lat – jednakże z rzeczywistego użytkowania wynika, że tak może powodować silny ból głowy oraz potencjalna utrata danych w wyniku użytkowania.
- Przywracanie kopii zapasowych musi być bezproblemowe i proste. Korzystanie z rozwiązania takiego jak MongoDB z
mongodump
orazmongoexport
jest nie tylko żmudne, ale także czasochłonne i wymaga złożoności konfiguracji.- Bazy danych SQLite sprawiają, że jest to proste (jest to pojedynczy plik).
- Chcieliśmy zaprojektować rozwiązanie, w którym użytkownicy będą mogli w każdej chwili zabrać swoją skrzynkę pocztową i wyjść.
- Proste polecenia Node.js do
fs.unlink('mailbox.sqlite'))
i jest trwale usuwany z pamięci dyskowej. - W podobny sposób możemy używać interfejsu API zgodnego z S3 z protokołem HTTP
DELETE
aby łatwo usuwać migawki i kopie zapasowe dla użytkowników.
- Proste polecenia Node.js do
- SQLite był najprostszym, najszybszym i najbardziej opłacalnym rozwiązaniem.
Brak alternatyw
Według naszej wiedzy żadne inne usługi e-mail nie są zaprojektowane w ten sposób ani nie są typu open source.
My myślę, że to może być spowodowane do istniejących usług e-mail, w których wykorzystywana jest starsza technologia kod spaghetti 🍝.
Większość, jeśli nie wszyscy, istniejących dostawców usług e-mail to dostawcy usług o zamkniętym kodzie źródłowym lub reklamujący się jako dostawcy o otwartym kodzie źródłowym, ale w rzeczywistości tylko ich front-end jest open-source.
Najbardziej wrażliwa część wiadomości e-mail (rzeczywista interakcja przechowywania/IMAP/SMTP) wszystko odbywa się na zapleczu (serwerze) i nie na froncie (klient).
Wypróbuj funkcję przesyłania dalej e-mailem
Zapisz się już dziś o godz https://forwardemail.net! 🚀