Kuantum Dirençli E-posta: E-postanızı Güvende Tutmak İçin Şifrelenmiş SQLite Posta Kutularını Nasıl Kullanıyoruz

Kuantum-güvenli şifrelenmiş e-posta servisi illüstrasyonu

Önsöz

Important

E-posta servisimiz %100 açık kaynak ve güvenli, şifrelenmiş SQLite posta kutuları sayesinde gizlilik odaklıdır.

IMAP desteğini başlatana kadar kalıcı veri depolama ihtiyaçlarımız için MongoDB kullanıyorduk.

Bu teknoloji harika ve hâlâ kullanıyoruz – ancak MongoDB ile verilerin şifrelenmiş olarak saklanabilmesi için Digital Ocean veya Mongo Atlas gibi MongoDB Enterprise sunan bir sağlayıcı kullanmanız gerekiyor – ya da kurumsal lisans için ödeme yapmanız (ve ardından satış ekibiyle gecikmelerle uğraşmanız) gerekiyor.

Forward Email ekibimiz, IMAP posta kutuları için geliştirici dostu, ölçeklenebilir, güvenilir ve şifrelenmiş bir depolama çözümüne ihtiyaç duyuyordu. Açık kaynak geliştiriciler olarak, şifrelenmiş veri saklama özelliği için lisans ücreti ödemeniz gereken bir teknoloji kullanmak prensiplerimize aykırıydı – bu yüzden deneyler yaptık, araştırdık ve bu ihtiyaçları karşılamak için sıfırdan yeni bir çözüm geliştirdik.

Posta kutularınızı depolamak için paylaşılan bir veritabanı kullanmak yerine, posta kutularınızı şifrenizle (sadece sizin bildiğiniz) ayrı ayrı saklıyor ve şifreliyoruz. E-posta servisimiz o kadar güvenlidir ki, şifrenizi unutursanız posta kutunuzu kaybedersiniz (ve çevrimdışı yedeklerle kurtarmanız veya baştan başlamanız gerekir).

Aşağıda e-posta servis sağlayıcı karşılaştırması, servisimizin nasıl çalıştığı, teknoloji yığınımız ve daha fazlası ile derinlemesine incelemeye devam edin.

E-posta servis sağlayıcı karşılaştırması

Bireysel olarak şifrelenmiş SQLite posta kutuları depolayan, sınırsız alan adı, takma ad ve kullanıcı sunan, ayrıca giden SMTP, IMAP ve POP3 desteği olan tek %100 açık kaynak ve gizlilik odaklı e-posta servis sağlayıcısıyız:

Diğer e-posta sağlayıcılarının aksine, Forward Email ile alan adı veya takma ad başına depolama için ödeme yapmanız gerekmez. Depolama tüm hesabınızda paylaşılır – yani birden fazla özel alan adınız ve her birinde birden fazla takma adınız varsa, biz sizin için mükemmel çözümdür. İsterseniz alan adı veya takma ad bazında depolama sınırları koyabilirsiniz.

E-posta Servis Karşılaştırmasını Oku

Nasıl çalışır

  1. Apple Mail, Thunderbird, Gmail veya Outlook gibi e-posta istemcinizi kullanarak, kullanıcı adınız ve şifrenizle güvenli IMAP sunucularımıza bağlanırsınız:

    • Kullanıcı adınız, hello@example.com gibi alan adınızla birlikte tam takma adınızdır.
    • Şifreniz rastgele oluşturulur ve Şifre Oluştur butonuna tıkladığınızda sadece 30 saniye boyunca size gösterilir. Bu buton Hesabım Alan Adları Takma Adlar altında bulunur.
  2. Bağlandıktan sonra, e-posta istemciniz posta kutunuzu senkronize tutmak için IMAP protokol komutları gönderecektir. Bu, taslak e-postaların yazılması ve saklanması ile yapabileceğiniz diğer işlemleri (örneğin bir e-postayı Önemli olarak etiketlemek veya bir e-postayı Spam/İstenmeyen Posta olarak işaretlemek) içerir.

  3. Posta değişim sunucuları (genellikle "MX" sunucuları olarak bilinir) yeni gelen e-postaları alır ve posta kutunuza kaydeder. Bu olduğunda, e-posta istemciniz bilgilendirilir ve posta kutunuzu senkronize eder. Posta değişim sunucularımız e-postanızı bir veya daha fazla alıcıya (dahil olmak üzere webhooklar) iletebilir, e-postanızı bizimle şifrelenmiş IMAP depolamanızda saklayabilir, veya her ikisini de yapabilir!

  4. Sahne arkasında, güvenli e-posta depolama tasarımımız posta kutularınızı şifreli tutmak ve yalnızca sizin erişebilmeniz için iki şekilde çalışır:

    • Gönderen tarafından size yeni posta alındığında, posta değişim sunucularımız sizin için bireysel, geçici ve şifrelenmiş bir posta kutusuna yazar.

    • E-posta istemcinizle IMAP sunucumuza bağlandığınızda, şifreniz bellekte şifrelenir ve posta kutunuzu okumak ve yazmak için kullanılır. Posta kutunuz yalnızca bu şifre ile okunabilir ve yazılabilir. Bu şifreye yalnızca sizin sahip olduğunuzu unutmayın, bu nedenle posta kutunuza erişirken sadece siz okuyabilir ve yazabilirsiniz. E-posta istemciniz bir sonraki sefer posta kontrolü veya senkronizasyon yapmaya çalıştığında, yeni mesajlar bu geçici posta kutusundan alınır ve sağladığınız şifre kullanılarak gerçek posta kutusu dosyanıza kaydedilir. Bu geçici posta kutusunun daha sonra temizlenip silindiğini ve böylece yalnızca şifre korumalı posta kutunuzun mesajları içerdiğini unutmayın.

    • Eğer IMAP'e bağlıysanız (örneğin Apple Mail veya Thunderbird gibi bir e-posta istemcisi kullanıyorsanız), geçici disk depolamaya yazmamıza gerek yoktur. Bunun yerine, bellekte şifrelenmiş IMAP şifreniz alınır ve kullanılır. Gerçek zamanlı olarak, size bir mesaj teslim edilmeye çalışıldığında, tüm IMAP sunucularına aktif bir oturumunuz olup olmadığını soran bir WebSocket isteği göndeririz (bu alma kısmıdır) ve ardından şifrelenmiş bellekteki şifreyi iletiriz – böylece geçici posta kutusuna yazmamıza gerek kalmaz, şifrelenmiş şifrenizle gerçek şifrelenmiş posta kutunuza yazabiliriz.

  5. Şifrelenmiş posta kutularınızın yedekleri günlük olarak alınır. Ayrıca istediğiniz zaman yeni bir yedek talep edebilir veya en son yedeği Hesabım Alan Adları Takma Adlar bölümünden indirebilirsiniz. Başka bir e-posta hizmetine geçmeye karar verirseniz, posta kutularınızı ve yedeklerinizi istediğiniz zaman kolayca taşıyabilir, indirebilir, dışa aktarabilir ve temizleyebilirsiniz.

Teknolojiler

Veritabanları

Başka olası veritabanı depolama katmanlarını araştırdık, ancak hiçbiri SQLite kadar gereksinimlerimizi karşılamadı:

Veritabanı Dinlenme Halinde Şifreleme Sandboxed Posta Kutuları Lisans Her Yerde Kullanılıyor
SQLite SQLite3MultipleCiphers ile Evet ✅ Kamu Malı
MongoDB "Sadece MongoDB Enterprise'da Mevcut" ❌ İlişkisel veritabanı ❌ AGPL ve SSPL-1.0
rqlite Sadece Ağ ❌ İlişkisel veritabanı MIT
dqlite Test edilmemiş ve henüz desteklenmiyor? Test edilmemiş ve henüz desteklenmiyor? LGPL-3.0-only
PostgreSQL Evet ❌ İlişkisel veritabanı PostgreSQL ( BSD veya MIT benzeri)
MariaDB Sadece InnoDB için ❌ İlişkisel veritabanı GPLv2 ve BUSL-1.1
CockroachDB Sadece Enterprise özelliği ❌ İlişkisel veritabanı BUSL-1.1 ve diğerleri

Yukarıdaki tabloda birkaç SQLite veritabanı depolama seçeneğini karşılaştıran bir blog yazısı bulunmaktadır.

Güvenlik

Her zaman dinlenme halindeki şifreleme (AES-256), iletim halindeki şifreleme (TLS), 🍊 Tangerine kullanarak HTTPS üzerinden DNS ("DoH") ve posta kutularında sqleet (ChaCha20-Poly1305) şifrelemesi kullanıyoruz. Ayrıca, SMS'in araya girme saldırılarına açık olması nedeniyle token tabanlı iki faktörlü kimlik doğrulama, root erişimi devre dışı bırakılmış dönen SSH anahtarları, kısıtlı IP adresleri üzerinden sunuculara özel erişim ve daha fazlasını kullanıyoruz. Bir kötü hizmetçi saldırısı veya üçüncü taraf bir satıcıdan kötü niyetli bir çalışan durumunda, posta kutunuz yalnızca sizin oluşturduğunuz şifre ile açılabilir. İçiniz rahat olsun, Cloudflare, DataPacket, Digital Ocean, GitHub ve Vultr gibi SOC Tip 2 uyumlu sunucu sağlayıcılarımız dışında herhangi bir üçüncü taraf satıcıya güvenmiyoruz.

Amacımız mümkün olduğunca az tek hata noktası olmaktır.

Posta Kutuları

özet; IMAP sunucularımız her posta kutunuz için ayrı ayrı şifrelenmiş SQLite veritabanları kullanır.

SQLite son derece popüler bir gömülü veritabanıdır – şu anda telefonunuzda ve bilgisayarınızda çalışmaktadır – ve neredeyse tüm büyük teknolojiler tarafından kullanılmaktadır.

Örneğin, şifrelenmiş sunucularımızda linux@example.com, info@example.com, hello@example.com gibi her biri için bir SQLite veritabanı posta kutusu vardır – her biri .sqlite veritabanı dosyası olarak. Veritabanı dosyalarını e-posta adresi ile isimlendirmiyoruz – bunun yerine posta kutusunun kime ait olduğunu veya hangi e-posta adresine bağlı olduğunu paylaşmayan BSON ObjectID ve benzersiz UUID'ler kullanıyoruz (örneğin 353a03f21e534321f5d6e267.sqlite).

Bu veritabanlarının her biri, yalnızca sizin sahip olduğunuz şifreniz kullanılarak sqleet (ChaCha20-Poly1305) ile şifrelenmiştir. Bu, posta kutularınızın ayrı ayrı şifrelendiği, kendi içinde bağımsız, sandboxlanmış ve taşınabilir olduğu anlamına gelir.

SQLite'ı aşağıdaki PRAGMA ile ince ayar yaptık:

PRAGMA Amaç
cipher=chacha20 ChaCha20-Poly1305 SQLite veritabanı şifrelemesi. Daha fazla bilgi için Projeler altında better-sqlite3-multiple-ciphers referansına bakınız.
key="****************" Bu, e-posta istemcinizin IMAP bağlantısı aracılığıyla sunucumuza iletilen, yalnızca bellekte çözülen şifrenizdir. Her okuma ve yazma oturumu için yeni veritabanı örnekleri oluşturulur ve kapatılır (sandboxlama ve izolasyonu sağlamak için).
journal_mode=WAL Yazmadan önce günlük ("WAL") performansı artırır ve eşzamanlı okuma erişimine izin verir.
busy_timeout=5000 Yazma kilidi hatalarını diğer yazmalar devam ederken önler.
synchronous=NORMAL İşlemlerin dayanıklılığını veri bozulması riski olmadan artırır.
foreign_keys=ON Yabancı anahtar referanslarının (örneğin bir tablodan diğerine ilişki) uygulanmasını sağlar. SQLite'da varsayılan olarak kapalıdır, ancak doğrulama ve veri bütünlüğü için etkinleştirilmelidir.
encoding='UTF-8' Geliştirici sağduyusunu sağlamak için kullanılacak varsayılan kodlama.

Diğer tüm varsayılanlar, resmi PRAGMA dokümantasyonunda belirtildiği gibi SQLite'tandır.

Eşzamanlılık

kısaca; Şifrelenmiş SQLite posta kutularınıza eşzamanlı okuma ve yazma işlemleri için WebSocket kullanıyoruz.

Okumalar

Telefonunuzdaki e-posta istemcisi imap.forwardemail.net adresini Digital Ocean IP adreslerimizden birine çözümleyebilir – ve masaüstü istemciniz tamamen farklı bir sağlayıcıdan ayrı bir IP adresi çözümleyebilir.

E-posta istemcinizin hangi IMAP sunucusuna bağlandığına bakılmaksızın, bağlantının veritabanınızı gerçek zamanlı ve %100 doğrulukla okumasını istiyoruz. Bu, WebSocket'ler aracılığıyla yapılır.

Yazmalar

Veritabanınıza yazmak biraz farklıdır – çünkü SQLite gömülü bir veritabanıdır ve posta kutunuz varsayılan olarak tek bir dosyada bulunur.

Aşağıda litestream, rqlite ve dqlite gibi seçenekleri araştırdık – ancak hiçbiri gereksinimlerimizi karşılamadı.

Write-ahead-logging ("WAL") etkinleştirilmiş yazmaları gerçekleştirmek için – yalnızca bir sunucunun ("Birincil") bu işlemi yapmasından emin olmamız gerekir. WAL eşzamanlılığı büyük ölçüde hızlandırır ve bir yazıcı ile birden fazla okuyucuya izin verir.

Birincil, şifrelenmiş posta kutularını içeren bağlanmış hacimlere sahip veri sunucularında çalışır. Dağıtım açısından, imap.forwardemail.net arkasındaki tüm bireysel IMAP sunucularını ikincil sunucular ("İkincil") olarak düşünebilirsiniz.

İki yönlü iletişimi WebSocket'ler ile sağlıyoruz:

  • Birincil sunucular, ws'nin WebSocketServer sunucu örneğini kullanır.
  • İkincil sunucular, ws'nin WebSocket istemci örneğini kullanır ve bu istemci websocket-as-promised ve reconnecting-websocket ile sarılır. Bu iki sarmalayıcı, WebSocket'in yeniden bağlanmasını ve belirli veritabanı yazmaları için veri gönderip almasını sağlar.

Yedekler

kısaca; Şifrelenmiş posta kutularınızın yedekleri günlük olarak alınır. Ayrıca istediğiniz zaman Hesabım Alan Adları Takma Adlar sayfasından yeni bir yedek talep edebilir veya en son yedeği indirebilirsiniz.

Yedekler için, IMAP komut işleme sırasında her gün SQLite VACUUM INTO komutunu çalıştırıyoruz; bu komut, bellekteki IMAP bağlantısından şifrelenmiş parolanızı kullanır. Yedekler, mevcut bir yedek algılanmazsa veya dosyanın SHA-256 karması en son yedekle karşılaştırıldığında değişmişse saklanır.

backup komutu yerine VACUUM INTO komutunu kullanmamızın nedeni, backup komutu sırasında bir sayfa değiştirilirse işlemin baştan başlaması gerekmesidir. VACUUM INTO komutu ise bir anlık görüntü alır. Daha fazla bilgi için bu GitHub ve Hacker News yorumlarına bakabilirsiniz.

Ayrıca backup komutu, rekey çağrılana kadar veritabanını kısa bir süre şifresiz bırakacağından VACUUM INTO komutunu tercih ediyoruz (detaylar için bu GitHub yorumu incelenebilir).

İkincil, Birincil'e WebSocket bağlantısı üzerinden yedekleme komutunu verir – Birincil bu komutu alır ve ardından:

  1. Şifrelenmiş posta kutunuza bağlanır.
  2. Yazma kilidi alır.
  3. wal_checkpoint(PASSIVE) ile WAL kontrol noktası çalıştırır.
  4. VACUUM INTO SQLite komutunu çalıştırır.
  5. Kopyalanan dosyanın şifrelenmiş parola ile açılabildiğinden emin olur (güvenlik/koruma).
  6. Dosyayı depolama için Cloudflare R2'ye (veya belirtilmişse kendi sağlayıcınıza) yükler.

Posta kutularınızın şifreli olduğunu unutmayın – ve WebSocket iletişimi için IP kısıtlamaları ve diğer kimlik doğrulama önlemleri uygulamış olsak da – kötü niyetli bir durumda, WebSocket yükü IMAP şifrenizi içermediği sürece veritabanınızı açamaz.

Şu anda her posta kutusu için yalnızca bir yedek saklanmaktadır, ancak gelecekte nokta-zaman-kurtarma ("PITR") sunabiliriz.

IMAP sunucularımız karmaşık sorgular, düzenli ifadeler ve daha fazlasını destekleyen SEARCH komutunu destekler.

Hızlı arama performansı, FTS5 ve sqlite-regex sayesinde mümkündür.

Date değerlerini SQLite posta kutularında ISO 8601 dizeleri olarak saklıyoruz; bu, Date.prototype.toISOString (UTC zaman dilimi ile, eşitlik karşılaştırmalarının doğru çalışması için) kullanılarak yapılır.

Arama sorgularında yer alan tüm özellikler için dizinler de saklanır.

Projeler

Kaynak kodumuzda ve geliştirme sürecimizde kullandığımız projeleri (alfabetik olarak sıralanmış) gösteren tablo:

Proje Amaç
Ansible Tüm sunucu filomuzu kolayca yönetmek, ölçeklendirmek ve sürdürmek için DevOps otomasyon platformu.
Bree Node.js ve JavaScript için cron, tarihler, ms, later ve insan dostu destekle iş zamanlayıcı.
Cabin Güvenlik ve gizlilik odaklı geliştirici dostu JavaScript ve Node.js günlükleme kütüphanesi.
Lad MVC ve daha fazlası ile tüm mimari ve mühendislik tasarımımızı güçlendiren Node.js çerçevesi.
MongoDB Posta kutuları dışındaki tüm diğer verileri (ör. hesap, ayarlar, alan adları ve takma ad yapılandırmaları) saklamak için kullandığımız NoSQL veritabanı çözümü.
Mongoose Tüm yığınımızda kullandığımız MongoDB nesne belge modelleme ("ODM"). Mongoose'u SQLite ile kullanmaya devam etmemizi sağlayan özel yardımcılar yazdık 🎉
Node.js Tüm sunucu süreçlerimizi çalıştıran açık kaynak, çapraz platform JavaScript çalışma zamanı ortamı.
Nodemailer E-posta gönderme, bağlantılar oluşturma ve daha fazlası için Node.js paketi. Bu projenin resmi sponsoru biziz.
Redis Önbellekleme, yayın/abonelik kanalları ve DNS üzerinden HTTPS istekleri için bellek içi veritabanı.
SQLite3MultipleCiphers Tüm veritabanı dosyalarının (yazma öncesi günlük ("WAL"), günlük, geri alma vb. dahil) şifrelenmesine izin veren SQLite şifreleme eklentisi.
SQLiteStudio Geliştirme posta kutularını test etmek, indirmek ve görüntülemek için kullanabileceğiniz görsel SQLite düzenleyici.
SQLite Ölçeklenebilir, kendi kendine yeten, hızlı ve dayanıklı IMAP depolama için gömülü veritabanı katmanı.
Spam Scanner Node.js anti-spam, e-posta filtreleme ve kimlik avı önleme aracı (bizim Spam Assassin ve rspamd alternatifimiz).
Tangerine Node.js ile DNS üzerinden HTTPS istekleri ve Redis kullanarak önbellekleme – küresel tutarlılık ve çok daha fazlasını sağlar.
Thunderbird Geliştirme ekibimiz tarafından kullanılan ve Forward Email ile kullanılması önerilen tercih edilen e-posta istemcisi.
UTM Geliştirme ekibimiz, IMAP ve SMTP sunucularımızla farklı e-posta istemcilerini (paralel olarak) test etmek için iOS ve macOS üzerinde sanal makineler oluşturmak için bunu kullanır.
Ubuntu Tüm altyapımızı güçlendiren modern açık kaynak Linux tabanlı sunucu işletim sistemi.
WildDuck IMAP sunucu kütüphanesi – ek açıklamalarını ve IMAP protokol desteğini inceleyin.
better-sqlite3-multiple-ciphers SQLite3 ile programatik olarak etkileşim için Node.js'e hızlı ve basit API kütüphanesi.
email-templates Geliştirici dostu e-posta çerçevesi; özel e-postalar (ör. hesap bildirimleri ve daha fazlası) oluşturmak, önizlemek ve göndermek için.
json-sql-enhanced Mongo tarzı sözdizimi kullanan SQL sorgu oluşturucu. Bu, geliştirme ekibimizin tüm yığın boyunca Mongo tarzında yazmaya devam etmesini sağlar ve veritabanı bağımsız bir yaklaşım sunar. Ayrıca sorgu parametreleri kullanarak SQL enjeksiyon saldırılarını önlemeye yardımcı olur.
knex-schema-inspector Mevcut veritabanı şeması hakkında bilgi çıkarmak için SQL aracı. Bu, tüm dizinlerin, tabloların, sütunların, kısıtlamaların ve daha fazlasının geçerli ve olması gerektiği gibi 1:1 olduğunu kolayca doğrulamamızı sağlar. Veritabanı şemalarında değişiklik yapılırsa yeni sütunlar ve dizinler eklemek için otomatik yardımcılar bile yazdık (çok ayrıntılı hata uyarılarıyla).
knex Yalnızca veritabanı geçişleri ve knex-schema-inspector ile şema doğrulama için kullandığımız SQL sorgu oluşturucu.
mandarin Markdown desteği ile otomatik i18n ifade çevirisi için Google Cloud Translation API kullanımı.
mx-connect MX sunucularıyla bağlantı kurmak ve hataları yönetmek için Node.js paketi.
pm2 Yerleşik yük dengeleyici ile Node.js üretim süreç yöneticisi (performans için ince ayarlı).
smtp-server SMTP sunucu kütüphanesi – posta değişimi ("MX") ve giden SMTP sunucularımız için kullanıyoruz.
ImapTest IMAP sunucularını kıyaslamalar ve RFC spesifikasyonu IMAP protokol uyumluluğu açısından test etmek için faydalı araç. Bu proje, Dovecot ekibi tarafından oluşturuldu (Temmuz 2002'den beri aktif açık kaynak IMAP ve POP3 sunucusu). IMAP sunucumuzu bu araçla kapsamlı şekilde test ettik.

Diğer kullandığımız projeleri GitHub üzerindeki kaynak kodumuzda bulabilirsiniz.

Sağlayıcılar

Sağlayıcı Amaç
Cloudflare DNS sağlayıcısı, sağlık kontrolleri, yük dengeleyiciler ve Cloudflare R2 kullanarak yedek depolama.
GitHub Kaynak kodu barındırma, CI/CD ve proje yönetimi.
Digital Ocean Özel sunucu barındırma ve yönetilen veritabanları.
Vultr Özel sunucu barındırma.
DataPacket Özel sunucu barındırma.

Düşünceler

İlkeler

Forward Email şu ilkeler doğrultusunda tasarlanmıştır:

  1. Her zaman geliştirici dostu, güvenlik ve gizlilik odaklı ve şeffaf olmak.
  2. MVC, Unix, KISS, DRY, YAGNI, Twelve Factor, Occam's razor ve dogfooding prensiplerine bağlı kalmak.
  3. Mütevazı, kendi kendine yeten ve ramen-kârlı geliştiriciyi hedeflemek.

Deneyler

kısaca; Sonuç olarak S3 uyumlu nesne depolama ve/veya Sanal Tabloların performans nedenleriyle teknik olarak uygulanabilir olmadığı ve bellek sınırlamaları nedeniyle hata yapmaya eğilimli olduğu görülmüştür.

Yukarıda tartışıldığı gibi nihai SQLite çözümümüze ulaşana kadar birkaç deney yaptık.

Bunlardan biri, rclone ve SQLite'ı S3 uyumlu bir depolama katmanı ile birlikte kullanmayı denemekti.

Bu deney, rclone, SQLite ve VFS kullanımıyla ilgili kenar durumları daha iyi anlamamıza ve keşfetmemize yol açtı:

  • rclone ile --vfs-cache-mode writes bayrağını etkinleştirirseniz, okuma işlemleri iyi çalışır ancak yazmalar önbelleğe alınır.
    • Birden fazla IMAP sunucunuz küresel olarak dağıtılmışsa, önbellek bunlar arasında kapalı olur; ancak tek bir yazıcı ve birden fazla dinleyici (örneğin bir pub/sub yaklaşımı) varsa bu sorun olmaz.
    • Bu inanılmaz derecede karmaşıktır ve buna benzer ek karmaşıklıklar daha fazla tek hata noktası yaratır.
    • S3 uyumlu depolama sağlayıcıları kısmi dosya değişikliklerini desteklemez – bu, .sqlite dosyasındaki herhangi bir değişikliğin veritabanının tamamen değişmesi ve yeniden yüklenmesi anlamına gelir.
    • rsync gibi diğer çözümler vardır, ancak bunlar yazma öncesi günlük ("WAL") desteğine odaklanmaz – bu yüzden Litestream'i inceledik. Neyse ki şifreleme kullanımız zaten WAL dosyalarını bizim için şifreliyor, bu yüzden Litestream'e bu konuda güvenmemize gerek yok. Ancak Litestream'in üretim kullanımı için henüz tam güvenimiz yok ve aşağıda bununla ilgili birkaç notumuz var.
    • --vfs-cache-mode writes seçeneğini kullanmak (yazmalar için rclone üzerinden SQLite kullanmanın tek yolu) tüm veritabanını sıfırdan belleğe kopyalamaya çalışır – 10 GB'lık bir posta kutusunu yönetmek sorun değil, ancak çok yüksek depolama gerektiren birden fazla posta kutusunu yönetmek IMAP sunucularının bellek sınırlarına, ENOMEM hatalarına, segmentasyon hatalarına ve veri bozulmasına yol açar.
  • SQLite Sanal Tabloları (örneğin s3db kullanarak) S3 uyumlu depolama katmanında veri tutmak için kullanmaya çalışırsanız, birkaç başka sorunla karşılaşırsınız:
    • Okuma ve yazma işlemleri çok yavaş olur çünkü S3 API uç noktalarına HTTP GET, PUT, HEAD ve POST yöntemleriyle erişilmesi gerekir.
    • Geliştirme testleri, fiber internet üzerinde 500K-1M+ kayıt aşımının bile S3 uyumlu sağlayıcılara yazma ve okuma hızlarıyla sınırlı olduğunu gösterdi. Örneğin geliştiricilerimiz hem ardışık SQL INSERT ifadeleri hem de büyük miktarda veriyi toplu yazan for döngüleri çalıştırdı. Her iki durumda da performans şaşırtıcı derecede yavaştı.
    • Sanal tablolar indekslere, ALTER TABLE ifadelerine ve diğer kısıtlamalara sahip olamaz – bu da veri miktarına bağlı olarak 1-2 dakika veya daha fazla gecikmeye yol açar.
    • Nesneler şifrelenmemiş olarak depolanır ve yerel şifreleme desteği mevcut değildir.
  • Ayrıca sqlite-s3vfs kullanmayı araştırdık; bu kavramsal ve teknik olarak önceki maddeye benzer (dolayısıyla aynı sorunlara sahip). Bir olasılık, yukarıdaki çözümümüzde kullandığımız gibi şifreleme ile sarılmış özel bir sqlite3 derlemesi kullanmak olabilir; örneğin wxSQLite3 aracılığıyla kurulum dosyasını düzenleyerek.
  • Başka bir potansiyel yaklaşım multiplex eklentisi kullanmaktı, ancak bunun 32 GB sınırı var ve karmaşık derleme ve geliştirme zorlukları gerektirir.
  • ALTER TABLE ifadeleri gereklidir (bu nedenle Sanal Tablolar tamamen elenir). knex-schema-inspector ile kancamızın düzgün çalışması için ALTER TABLE ifadelerine ihtiyacımız var – bu, verilerin bozulmamasını ve alınan satırların mongoose şema tanımlarımıza göre geçerli belgelere dönüştürülebilmesini sağlar (bu tanımlar kısıtlamalar, değişken türleri ve keyfi veri doğrulamasını içerir).
  • Açık kaynak topluluğunda SQLite ile ilgili S3 uyumlu projelerin neredeyse tamamı Python'dadır (ve bizim kullandığımız %100 JavaScript değildir).
  • sqlite-zstd gibi sıkıştırma kütüphaneleri (bkz. yorumlar) umut verici görünmekle birlikte henüz üretim kullanımı için hazır olmayabilir. Bunun yerine String, Object, Map, Array, Set ve Buffer gibi veri türlerinde uygulama tarafı sıkıştırma daha temiz ve kolay bir yaklaşım olacaktır (ve geçişi de daha kolaydır, çünkü bir Boolean bayrak veya sütun saklayabiliriz – ya da veritabanı meta verisi olarak sıkıştırma için PRAGMA user_version=1 veya sıkıştırmasız için user_version=0 kullanabiliriz).
    • Neyse ki IMAP sunucu depolamamızda ek dosya çoğaltma önleme zaten uygulanmıştır – bu nedenle aynı eki içeren her mesaj eki kopyalamaz – bunun yerine bir posta kutusundaki birden fazla mesaj ve konu için tek bir ek saklanır ve yabancı bir referans kullanılır.
  • SQLite çoğaltma ve yedekleme çözümü olan Litestream projesi çok umut verici ve muhtemelen gelecekte kullanacağız.
  • Yedek geri yükleme sürtünmesiz ve basit olmalıdır. mongodump ve mongoexport kullanan MongoDB gibi çözümler sadece zahmetli değil, aynı zamanda zaman alıcı ve yapılandırma karmaşıklığına sahiptir.
    • SQLite veritabanları bunu basitleştirir (tek bir dosyadır).
    • Kullanıcıların posta kutularını istedikleri anda alıp ayrılabilecekleri bir çözüm tasarlamak istedik.
      • Basit Node.js komutlarıyla fs.unlink('mailbox.sqlite') yaparak dosya kalıcı olarak diskten silinir.
      • Benzer şekilde S3 uyumlu API ile HTTP DELETE kullanarak kullanıcılar için anlık görüntüleri ve yedekleri kolayca kaldırabiliriz.
    • SQLite en basit, en hızlı ve en maliyet etkin çözümdü.

Alternatif Eksikliği

Bildiklerimize göre, başka hiçbir e-posta servisi bu şekilde tasarlanmamıştır ve açık kaynak değildir.

Bunun sebebinin, mevcut e-posta servislerinin üretimde spagetti kod 🍝 içeren eski teknolojiye sahip olmaları olduğunu düşünüyoruz.

Mevcut e-posta servis sağlayıcılarının çoğu ya kapalı kaynaklıdır ya da açık kaynak olarak reklam yapar, ancak gerçekte sadece ön yüzleri açık kaynaktır.

E-postanın en hassas kısmı (gerçek depolama/IMAP/SMTP etkileşimi) tamamen arka uçta (sunucu) yapılır, ön uçta (istemci) değil.

Forward Email'i Deneyin

Bugün https://forwardemail.net adresinden kaydolun! 🚀