กล่องจดหมาย SQLite ที่เข้ารหัสเพื่อความเป็นส่วนตัวของคุณ
ไม่เหมือนกับบริการอีเมลอื่น ๆ เรารับรองว่า มีเพียงคุณเท่านั้นที่สามารถเข้าถึงกล่องจดหมายของคุณ ได้ตลอดเวลา
- หน้าค้นหา
- สารบัญ
คำนำ
ทีแอลอาร์; บริการอีเมล์ของเราคือ โอเพ่นซอร์ส 100% และเน้นความเป็นส่วนตัวผ่านกล่องจดหมาย SQLite ที่ปลอดภัยและเข้ารหัส
จนกระทั่งเราเปิดตัว การสนับสนุน IMAPเราใช้ MongoDB สำหรับความต้องการพื้นที่จัดเก็บข้อมูลถาวรของเรา
เทคโนโลยีนี้น่าทึ่งมากและเรายังคงใช้มันอยู่ในปัจจุบัน แต่เพื่อที่จะมีการเข้ารหัสเมื่อไม่มีการใช้งานกับ MongoDB คุณต้องใช้ผู้ให้บริการที่ให้บริการ MongoDB Enterprise เช่น Digital Ocean หรือ Mongo Atlas – หรือชำระค่าลิขสิทธิ์ระดับองค์กร (และ ต่อมาต้องทำงานร่วมกับทีมขายที่มีความหน่วงแฝง)
ทีมงานของเราที่ ส่งต่ออีเมล ต้องการโซลูชันพื้นที่จัดเก็บข้อมูลที่เข้ารหัสที่เป็นมิตรต่อนักพัฒนา ปรับขนาดได้ เชื่อถือได้ และเข้ารหัสสำหรับกล่องจดหมาย IMAP ในฐานะนักพัฒนาโอเพ่นซอร์ส การใช้เทคโนโลยีที่คุณต้องจ่ายค่าธรรมเนียมใบอนุญาตเพื่อรับคุณสมบัติการเข้ารหัสเมื่อไม่มีการใช้งานนั้นขัดต่อ หลักการของเรา – ดังนั้นเราจึงทดลอง วิจัย และพัฒนาโซลูชันใหม่ตั้งแต่ต้นเพื่อแก้ปัญหาความต้องการเหล่านี้
แทนที่จะใช้ฐานข้อมูลที่ใช้ร่วมกันเพื่อจัดเก็บกล่องจดหมายของคุณ เราจะจัดเก็บและเข้ารหัสกล่องจดหมายของคุณเป็นรายบุคคลด้วยรหัสผ่านของคุณ (ซึ่งมีเพียงคุณเท่านั้น) บริการอีเมลของเรามีความปลอดภัยมาก หากคุณลืมรหัสผ่าน กล่องจดหมายของคุณจะหายไป (และจำเป็นต้องกู้คืนด้วยการสำรองข้อมูลออฟไลน์หรือเริ่มต้นใหม่)
อ่านต่อในขณะที่เราดำดิ่งลงด้านล่างด้วย การเปรียบเทียบผู้ให้บริการอีเมล, บริการของเราทำงานอย่างไร, กองเทคโนโลยีของเรา, และอื่น ๆ.
การเปรียบเทียบผู้ให้บริการอีเมล
เราเป็นผู้ให้บริการอีเมลแบบโอเพ่นซอร์สและเน้นความเป็นส่วนตัวเพียงรายเดียว 100% ที่เก็บกล่องจดหมาย SQLite ที่เข้ารหัสแยกกัน ให้บริการโดเมน นามแฝง และผู้ใช้ไม่จำกัด และรองรับ SMTP, IMAP และ POP3 ขาออก:
แตกต่างจากผู้ให้บริการอีเมลรายอื่น คุณไม่จำเป็นต้องชำระค่าพื้นที่จัดเก็บตามโดเมนหรือนามแฝงด้วยการส่งต่ออีเมล พื้นที่เก็บข้อมูลถูกใช้ร่วมกันทั่วทั้งบัญชีของคุณ ดังนั้นหากคุณมีชื่อโดเมนแบบกำหนดเองหลายชื่อและชื่อแทนหลายชื่อในแต่ละชื่อ เราคือโซลูชั่นที่สมบูรณ์แบบสำหรับคุณ โปรดทราบว่าคุณยังคงสามารถบังคับใช้ขีดจำกัดพื้นที่เก็บข้อมูลได้ หากต้องการต่อโดเมนหรือชื่อแทน
มันทำงานอย่างไร
-
การใช้โปรแกรมรับส่งอีเมลของคุณ เช่น Apple Mail, Thunderbird, Gmail หรือ Outlook - คุณเชื่อมต่อกับระบบรักษาความปลอดภัยของเรา IMAP เซิร์ฟเวอร์ที่ใช้ชื่อผู้ใช้และรหัสผ่านของคุณ:
- ชื่อผู้ใช้ของคุณคือนามแฝงเต็มของคุณกับโดเมนของคุณเช่น
hello@example.com
. - รหัสผ่านของคุณถูกสร้างขึ้นแบบสุ่มและแสดงให้คุณเห็นเพียง 30 วินาทีเมื่อคุณคลิก สร้างรหัสผ่าน จาก บัญชีของฉัน โดเมน นามแฝง
- ชื่อผู้ใช้ของคุณคือนามแฝงเต็มของคุณกับโดเมนของคุณเช่น
-
เมื่อเชื่อมต่อแล้ว ไคลเอนต์อีเมลของคุณจะส่ง คำสั่งโปรโตคอล IMAP ไปยังเซิร์ฟเวอร์ IMAP ของเราเพื่อให้กล่องจดหมายของคุณซิงค์กัน ซึ่งรวมถึงการเขียนและจัดเก็บอีเมลฉบับร่างและการดำเนินการอื่นๆ ที่คุณอาจทำ (เช่น ติดป้ายกำกับอีเมลว่าสำคัญหรือตั้งค่าสถานะอีเมลว่าเป็นสแปม/เมลขยะ)
-
เซิร์ฟเวอร์ Exchange Mail (หรือที่รู้จักกันทั่วไปในชื่อเซิร์ฟเวอร์ "MX") จะได้รับอีเมลขาเข้าใหม่และจัดเก็บไว้ในกล่องจดหมายของคุณ เมื่อสิ่งนี้เกิดขึ้น ไคลเอนต์อีเมลของคุณจะได้รับการแจ้งเตือนและซิงค์กล่องจดหมายของคุณ เซิร์ฟเวอร์แลกเปลี่ยนจดหมายของเราสามารถส่งต่ออีเมลของคุณไปยังผู้รับตั้งแต่หนึ่งรายขึ้นไป (รวมถึง เว็บฮุค) จัดเก็บอีเมลของคุณไว้ในที่เก็บข้อมูล IMAP ที่เข้ารหัสกับเรา หรือทั้งคู่!
สนใจที่จะเรียนรู้เพิ่มเติมหรือไม่? อ่าน วิธีการตั้งค่าการส่งต่ออีเมล, บริการแลกเปลี่ยนจดหมายของเราทำงานอย่างไรหรือดู คำแนะนำของเรา.
-
เบื้องหลัง การออกแบบพื้นที่จัดเก็บอีเมลที่ปลอดภัยของเราทำงานในสองวิธีเพื่อให้กล่องจดหมายของคุณได้รับการเข้ารหัสและมีเพียงคุณเท่านั้นที่สามารถเข้าถึงได้:
-
เมื่อได้รับจดหมายใหม่ถึงคุณจากผู้ส่ง เซิร์ฟเวอร์แลกเปลี่ยนจดหมายของเราจะเขียนไปยังกล่องจดหมายส่วนบุคคล ชั่วคราว และเข้ารหัสสำหรับคุณ
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!
-
เมื่อคุณเชื่อมต่อกับเซิร์ฟเวอร์ IMAP ของเราด้วยไคลเอนต์อีเมลของคุณ รหัสผ่านของคุณจะถูกเข้ารหัสในหน่วยความจำและใช้ในการอ่านและเขียนไปยังกล่องจดหมายของคุณ กล่องจดหมายของคุณสามารถอ่านและเขียนด้วยรหัสผ่านนี้เท่านั้น โปรดทราบว่าเนื่องจากคุณเป็นคนเดียวที่มีรหัสผ่านนี้ เพียงคุณเท่านั้น สามารถอ่านและเขียนไปยังกล่องจดหมายของคุณเมื่อคุณเข้าถึงได้ ครั้งถัดไปที่โปรแกรมรับส่งเมลของคุณพยายามสำรวจหาเมลหรือการซิงค์ ข้อความใหม่ของคุณจะถูกโอนจากกล่องจดหมายชั่วคราวนี้และจัดเก็บไว้ในไฟล์กล่องจดหมายจริงของคุณโดยใช้รหัสผ่านที่คุณให้มา โปรดทราบว่ากล่องจดหมายชั่วคราวนี้จะถูกล้างข้อมูลและลบหลังจากนั้น เพื่อให้มีเพียงกล่องจดหมายที่ป้องกันด้วยรหัสผ่านของคุณเท่านั้นที่มีข้อความ
-
หากคุณเชื่อมต่อกับ IMAP (เช่น ใช้โปรแกรมรับส่งเมล เช่น Apple Mail หรือ Thunderbird) เราไม่จำเป็นต้องเขียนลงพื้นที่จัดเก็บดิสก์ชั่วคราว รหัสผ่าน IMAP ที่เข้ารหัสในหน่วยความจำของคุณจะถูกดึงและใช้งานแทน แบบเรียลไทม์ เมื่อมีการพยายามส่งข้อความถึงคุณ เราจะส่งคำขอ WebSocket ไปยังเซิร์ฟเวอร์ IMAP ทั้งหมดเพื่อสอบถามว่าพวกเขามีเซสชันที่ใช้งานอยู่สำหรับคุณหรือไม่ (นี่คือส่วนที่ดึงข้อมูล) จากนั้นจะส่งต่อไปตามนั้น รหัสผ่านในหน่วยความจำที่เข้ารหัส – ดังนั้นเราจึงไม่จำเป็นต้องเขียนลงในกล่องจดหมายชั่วคราว เราสามารถเขียนไปยังกล่องจดหมายที่เข้ารหัสจริงของคุณได้โดยใช้รหัสผ่านที่เข้ารหัสของคุณ
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!
-
-
การสำรองข้อมูลกล่องจดหมายที่เข้ารหัสของคุณ จะทำทุกวัน คุณยังสามารถขอข้อมูลสำรองใหม่ได้ตลอดเวลาหรือดาวน์โหลดข้อมูลสำรองล่าสุดได้จาก บัญชีของฉัน โดเมน นามแฝง หากคุณตัดสินใจเปลี่ยนไปใช้บริการอีเมลอื่น คุณสามารถย้าย ดาวน์โหลด ส่งออก และล้างกล่องจดหมายและการสำรองข้อมูลของคุณได้อย่างง่ายดายทุกเมื่อ
เทคโนโลยี
ฐานข้อมูล
เราสำรวจเลเยอร์พื้นที่จัดเก็บฐานข้อมูลอื่นๆ ที่เป็นไปได้ แต่ไม่มีสิ่งใดที่ตอบสนองความต้องการของเราได้มากเท่ากับ SQLite:
ฐานข้อมูล | การเข้ารหัสที่เหลือ | แซนด์บ็อกซ์ กล่องจดหมาย | การอนุญาต | ใช้ทุกที่ |
---|---|---|---|---|
SQLite ⭐ | ✅ใช่กับ SQLite3MultipleCiphers | ✅ | ✅โดเมนสาธารณะ | ✅ |
มอนโกดีบี | ❌ "มีเฉพาะใน MongoDB Enterprise เท่านั้น" | ❌ฐานข้อมูลเชิงสัมพันธ์ | ❌AGPL และ SSPL-1.0 | ❌ |
rqlite | ❌ เครือข่ายเท่านั้น | ❌ฐานข้อมูลเชิงสัมพันธ์ | ✅ MIT | ❌ |
ดีคิวไลท์ | ❌ ยังไม่ได้ทดสอบและยังไม่รองรับใช่ไหม | ❌ ยังไม่ได้ทดสอบและยังไม่รองรับใช่ไหม | ✅ LGPL-3.0-only | ❌ |
โพสเกรสเอสคิวแอล | ✅ ใช่ | ❌ฐานข้อมูลเชิงสัมพันธ์ | ✅ PostgreSQL (คล้ายกับ BSD หรือ MIT ) | ❌ |
มาเรียดีบี | ✅ สำหรับ InnoDB เท่านั้น | ❌ฐานข้อมูลเชิงสัมพันธ์ | ✅ GPLv2 และ BUSL-1.1 | ❌ |
แมลงสาบDB | ❌ คุณลักษณะเฉพาะสำหรับองค์กรเท่านั้น | ❌ฐานข้อมูลเชิงสัมพันธ์ | ❌ BUSL-1.1 และคนอื่น ๆ | ❌ |
นี่คือก โพสต์ในบล็อกที่เปรียบเทียบตัวเลือกการจัดเก็บฐานข้อมูล SQLite หลายตัว ในตารางด้านบน
ความปลอดภัย
ตลอดเวลาที่เราใช้ การเข้ารหัสที่เหลือ (AES-256), การเข้ารหัสระหว่างทาง (TLS), DNS ผ่าน HTTPS ("DoH") โดยใช้ 🍊 ส้มเขียวหวาน, และ ตาราง (ชาช่า20-โพลี1305) การเข้ารหัสบนกล่องจดหมาย นอกจากนี้ เรายังใช้การตรวจสอบสิทธิ์แบบสองปัจจัยที่ใช้โทเค็น (ซึ่งตรงข้ามกับ SMS ที่น่าสงสัย) การโจมตีจากคนกลาง) คีย์ SSH ที่หมุนเวียนโดยปิดใช้งานการเข้าถึงรูท การเข้าถึงเซิร์ฟเวอร์แบบเอกสิทธิ์เฉพาะบุคคลผ่านที่อยู่ IP ที่จำกัด และอื่นๆ
ในกรณีที่มี การโจมตีของสาวใช้ชั่วร้าย หรือพนักงานหลอกลวงจากผู้ขายบุคคลที่สาม กล่องจดหมายของคุณยังคงสามารถเปิดได้ด้วยรหัสผ่านที่คุณสร้างขึ้นเท่านั้น. วางใจได้เลย เราไม่พึ่งพาผู้จำหน่ายบุคคลที่สามใดๆ นอกเหนือจากผู้ให้บริการเซิร์ฟเวอร์ร้องเรียน SOC Type 2 ของ Cloudflare, Digital Ocean และ Vultr
เป้าหมายของเราคือการมีให้น้อย จุดเดียวของความล้มเหลว เป็นไปได้.
กล่องจดหมาย
ทีแอลอาร์; เซิร์ฟเวอร์ IMAP ของเราใช้ฐานข้อมูล SQLite ที่เข้ารหัสแยกกันสำหรับกล่องจดหมายแต่ละกล่องของคุณ
SQLite เป็นที่นิยมอย่างมาก ฐานข้อมูลแบบฝัง – ขณะนี้มันทำงานบนโทรศัพท์และคอมพิวเตอร์ของคุณ – และใช้โดยเทคโนโลยีหลักเกือบทั้งหมด.
ตัวอย่างเช่น บนเซิร์ฟเวอร์ที่เข้ารหัสของเรา จะมีเมลบ็อกซ์ฐานข้อมูล SQLite linux@example.com
, info@example.com
, hello@example.com
และอื่นๆ – หนึ่งอันสำหรับแต่ละอันเป็น .sqlite
ไฟล์ฐานข้อมูล เราไม่ตั้งชื่อไฟล์ฐานข้อมูลด้วยที่อยู่อีเมล แต่เราใช้ BSON ObjectID และ UUID ที่ไม่ซ้ำกันที่สร้างขึ้นซึ่งไม่เปิดเผยว่ากล่องจดหมายเป็นของใครหรือที่อยู่อีเมลใดอยู่ภายใต้ (เช่น 353a03f21e534321f5d6e267.sqlite
).
แต่ละฐานข้อมูลเหล่านี้ได้รับการเข้ารหัสด้วยตนเองโดยใช้รหัสผ่านของคุณ (ซึ่งมีเพียงคุณเท่านั้น) โดยใช้ ตาราง (ชาช่า20-โพลี1305). ซึ่งหมายความว่ากล่องจดหมายของคุณได้รับการเข้ารหัสแยกกัน มีอยู่ในตัวเอง แซนด์บ็อกซ์และแบบพกพา
เราได้ปรับแต่ง SQLite ดังต่อไปนี้ PRAGMA:
PRAGMA | วัตถุประสงค์ |
---|---|
cipher=chacha20 | การเข้ารหัสฐานข้อมูล ChaCha20-Poly1305 SQLite. อ้างอิง better-sqlite3-multiple-ciphers ภายใต้ โครงการ เพื่อความเข้าใจที่ลึกซึ้งยิ่งขึ้น |
key="****************" | นี่เป็นรหัสผ่านเฉพาะในหน่วยความจำที่ถอดรหัสแล้วของคุณ ซึ่งจะถูกส่งผ่านการเชื่อมต่อ IMAP ของโปรแกรมรับส่งอีเมลของคุณไปยังเซิร์ฟเวอร์ของเรา อินสแตนซ์ฐานข้อมูลใหม่จะถูกสร้างและปิดสำหรับแต่ละเซสชันการอ่านและเขียน (เพื่อให้แน่ใจว่ามีแซนด์บ็อกซ์และการแยกตัว) |
journal_model=WAL | บันทึกการเขียนล่วงหน้า ("WAL") ซึ่งช่วยเพิ่มประสิทธิภาพและช่วยให้เข้าถึงการอ่านได้พร้อมกัน. |
busy_timeout=5000 | ป้องกันข้อผิดพลาดในการล็อคการเขียน ในขณะที่มีการเขียนอื่นเกิดขึ้น. |
synchronous=NORMAL | เพิ่มความคงทนในการทำธุรกรรม โดยไม่มีความเสี่ยงต่อความเสียหายของข้อมูล. |
foreign_keys=ON | บังคับใช้การอ้างอิงคีย์ต่างประเทศ (เช่น ความสัมพันธ์จากตารางหนึ่งไปอีกตารางหนึ่ง) ตามค่าเริ่มต้น สิ่งนี้จะไม่ถูกเปิดใช้งานใน SQLiteแต่สำหรับการตรวจสอบความถูกต้องและความสมบูรณ์ของข้อมูล ควรเปิดใช้งาน |
encoding='UTF-8' | การเข้ารหัสเริ่มต้น เพื่อใช้เพื่อให้แน่ใจว่านักพัฒนามีสติ |
ค่าเริ่มต้นอื่น ๆ ทั้งหมดมาจาก SQLite ตามที่ระบุจาก เอกสารอย่างเป็นทางการของ PRAGMA.
เห็นพ้องต้องกัน
ทีแอลอาร์; เราใช้
WebSocket
สำหรับการอ่านและเขียนไปยังกล่องจดหมาย SQLite ที่เข้ารหัสของคุณพร้อมกัน
อ่าน
ไคลเอนต์อีเมลของคุณบนโทรศัพท์ของคุณอาจแก้ไขได้ imap.forwardemail.net
ไปยังหนึ่งในที่อยู่ IP ของ Digital Ocean ของเรา และไคลเอนต์เดสก์ท็อปของคุณอาจแก้ไข IP ที่แยกจากที่อื่น ผู้ให้บริการ โดยสิ้นเชิง
ไม่ว่าไคลเอนต์อีเมลของคุณจะเชื่อมต่อเซิร์ฟเวอร์ IMAP ใด เราต้องการให้การเชื่อมต่ออ่านจากฐานข้อมูลของคุณแบบเรียลไทม์ด้วยความแม่นยำ 100% ทำได้ผ่าน WebSockets
เขียน
การเขียนไปยังฐานข้อมูลของคุณแตกต่างออกไปเล็กน้อย เนื่องจาก SQLite เป็นฐานข้อมูลแบบฝัง และกล่องจดหมายของคุณอยู่ในไฟล์เดียวตามค่าเริ่มต้น
เราได้สำรวจตัวเลือกต่างๆ เช่น litestream
, rqlite
, และ dqlite
ด้านล่าง – อย่างไรก็ตาม สิ่งเหล่านี้ไม่สามารถตอบสนองความต้องการของเราได้
เพื่อให้การเขียนสำเร็จด้วยการบันทึกล่วงหน้า ("WAL") เปิดใช้งานแล้ว – เราต้องแน่ใจว่ามีเพียงเซิร์ฟเวอร์เดียว ("หลัก") เท่านั้นที่รับผิดชอบในการดำเนินการดังกล่าว WAL เพิ่มความเร็วในการทำงานพร้อมกันอย่างมากและอนุญาตให้มีผู้เขียนหนึ่งคนและผู้อ่านหลายคนได้
ตัวหลักกำลังทำงานบนเซิร์ฟเวอร์ข้อมูลโดยมีไดรฟ์ข้อมูลที่ติดตั้งซึ่งมีกล่องจดหมายที่เข้ารหัส จากมุมมองของการเผยแพร่ คุณสามารถพิจารณาเซิร์ฟเวอร์ IMAP ทั้งหมดที่อยู่เบื้องหลังได้ imap.forwardemail.net
ให้เป็นเซิร์ฟเวอร์รอง ("รอง")
เราบรรลุการสื่อสารสองทางด้วย เว็บซ็อกเก็ต:
- เซิร์ฟเวอร์หลักใช้อินสแตนซ์ของ สของ
WebSocketServer
เซิร์ฟเวอร์ - เซิร์ฟเวอร์รองใช้อินสแตนซ์ของ สของ
WebSocket
ลูกค้าที่ห่อด้วย websocket ตามที่สัญญาไว้ และ เชื่อมต่อใหม่-websocket. กระดาษห่อทั้งสองนี้ช่วยให้มั่นใจได้ว่าWebSocket
เชื่อมต่อใหม่และสามารถส่งและรับข้อมูลสำหรับการเขียนฐานข้อมูลเฉพาะได้
การสำรองข้อมูล
ทีแอลอาร์; มีการสำรองข้อมูลกล่องจดหมายที่เข้ารหัสของคุณทุกวัน คุณยังสามารถขอข้อมูลสำรองใหม่ได้ทันทีหรือดาวน์โหลดข้อมูลสำรองล่าสุดได้ตลอดเวลาจาก บัญชีของฉัน โดเมน นามแฝง
สำหรับการสำรองข้อมูล เราเพียงเรียกใช้ SQLite VACUUM INTO
คำสั่งทุกวันระหว่างการประมวลผลคำสั่ง IMAP ซึ่งใช้ประโยชน์จากรหัสผ่านที่เข้ารหัสของคุณจากการเชื่อมต่อ IMAP ในหน่วยความจำ ข้อมูลสำรองจะถูกจัดเก็บหากตรวจไม่พบข้อมูลสำรองที่มีอยู่หรือหาก SHA-256 แฮชมีการเปลี่ยนแปลงในไฟล์เมื่อเปรียบเทียบกับการสำรองข้อมูลล่าสุด
โปรดทราบว่าเราใช้ VACUUM INTO
คำสั่งตรงข้ามกับในตัว backup
คำสั่งเพราะหากเพจถูกแก้ไขระหว่าง backup
การดำเนินการตามคำสั่งแล้วจะต้องเริ่มต้นใหม่ ที่ VACUUM INTO
คำสั่งจะจับภาพ ดูความคิดเห็นเหล่านี้ได้ที่ GitHub และ ข่าวแฮ็กเกอร์ เพื่อความเข้าใจที่ลึกซึ้งยิ่งขึ้น
นอกจากนี้เรายังใช้ VACUUM INTO
ตรงข้ามกับ backup
, เพราะว่า backup
คำสั่งจะปล่อยให้ฐานข้อมูลไม่ได้เข้ารหัสในช่วงเวลาสั้น ๆ จนกระทั่ง rekey
ถูกเรียกใช้ (ดู GitHub นี้ ความคิดเห็น เพื่อความเข้าใจ)
มัธยมศึกษาจะสั่งสอนประถมศึกษาเกี่ยวกับ WebSocket
การเชื่อมต่อเพื่อดำเนินการสำรองข้อมูล - จากนั้นตัวหลักจะได้รับคำสั่งให้ดำเนินการดังกล่าวและจะดำเนินการในภายหลัง:
- เชื่อมต่อกับกล่องจดหมายที่เข้ารหัสของคุณ
- รับล็อคการเขียน
- ดำเนินการจุดตรวจ WAL ผ่าน
wal_checkpoint(PASSIVE)
. - เรียกใช้
VACUUM INTO
คำสั่ง SQLite - ตรวจสอบให้แน่ใจว่าไฟล์ที่คัดลอกสามารถเปิดได้ด้วยรหัสผ่านที่เข้ารหัส (การป้องกัน/การป้องกันจำลอง)
- อัปโหลดไปยัง Cloudflare R2 เพื่อจัดเก็บข้อมูล (หรือผู้ให้บริการของคุณเอง หากระบุ)
โปรดจำไว้ว่ากล่องจดหมายของคุณได้รับการเข้ารหัส และแม้ว่าเราจะมีข้อจำกัด IP และมาตรการตรวจสอบสิทธิ์อื่นๆ สำหรับการสื่อสาร WebSocket ในกรณีที่มีผู้ไม่ประสงค์ดี คุณสามารถมั่นใจได้ว่า เว้นแต่เพย์โหลด WebSocket จะมีรหัสผ่าน IMAP ของคุณ จะไม่สามารถเปิดฐานข้อมูลของคุณได้ .
ในขณะนี้ จะมีการจัดเก็บข้อมูลสำรองไว้เพียงรายการเดียวต่อกล่องจดหมาย แต่ในอนาคต เราอาจเสนอการกู้คืน ณ เวลาใดเวลาหนึ่ง ("PITR").
ค้นหา
เซิร์ฟเวอร์ IMAP ของเรารองรับ SEARCH
คำสั่งที่มีการสืบค้นที่ซับซ้อน นิพจน์ทั่วไป และอื่นๆ
ประสิทธิภาพการค้นหาที่รวดเร็วนั้นต้องขอบคุณ FTS5 และ sqlite-regex.
เราจัดเก็บ Date
ค่าในกล่องจดหมาย SQLite เป็น ISO 8601 สตริงผ่าน Date.prototype.toISOString (พร้อมเขตเวลา UTC เพื่อให้การเปรียบเทียบความเท่าเทียมกันทำงานได้อย่างถูกต้อง)
ดัชนีจะถูกจัดเก็บสำหรับคุณสมบัติทั้งหมดที่อยู่ในคำค้นหาด้วย
โครงการ
นี่คือตารางสรุปโปรเจ็กต์ที่เราใช้ในซอร์สโค้ดและกระบวนการพัฒนาของเรา (เรียงตามตัวอักษร):
โครงการ | วัตถุประสงค์ |
---|---|
เข้าใจได้ | แพลตฟอร์มอัตโนมัติ DevOps สำหรับการบำรุงรักษา ปรับขนาด และจัดการเซิร์ฟเวอร์ทั้งหมดของเราได้อย่างง่ายดาย |
บรี | ตัวกำหนดเวลางานสำหรับ Node.js และ JavaScript พร้อม cron, วันที่, ms, เวอร์ชันใหม่กว่า และการสนับสนุนที่เป็นมิตรต่อมนุษย์ |
ห้องโดยสาร | ไลบรารีการบันทึก JavaScript และ Node.js ที่เป็นมิตรกับนักพัฒนาโดยคำนึงถึงความปลอดภัยและความเป็นส่วนตัว |
ปล่อย | เฟรมเวิร์ก Node.js ซึ่งขับเคลื่อนสถาปัตยกรรมและการออกแบบทางวิศวกรรมทั้งหมดของเราด้วย MVC และอื่นๆ |
มอนโกดีบี | โซลูชันฐานข้อมูล NoSQL ที่เราใช้สำหรับจัดเก็บข้อมูลอื่นๆ ทั้งหมดนอกกล่องจดหมาย (เช่น บัญชี การตั้งค่า โดเมน และการกำหนดค่านามแฝงของคุณ) |
พังพอน | การสร้างแบบจำลองเอกสารวัตถุ MongoDB ("ODM") ซึ่งเราใช้ทั่วทั้งสแต็กของเรา เราเขียนตัวช่วยพิเศษที่ช่วยให้เราใช้ต่อไปได้ พังพอนกับ SQLite 🎉 |
โหนด js | Node.js คือสภาพแวดล้อมรันไทม์ JavaScript แบบโอเพ่นซอร์สข้ามแพลตฟอร์มซึ่งรันกระบวนการเซิร์ฟเวอร์ทั้งหมดของเรา |
หมายเหตุจดหมาย | แพ็คเกจ Node.js สำหรับการส่งอีเมล การสร้างการเชื่อมต่อ และอื่นๆ เราเป็นผู้สนับสนุนอย่างเป็นทางการของโครงการนี้ |
เรดิส | ฐานข้อมูลในหน่วยความจำสำหรับการแคช เผยแพร่/ติดตามช่อง และ DNS ผ่านคำขอ HTTPS |
SQLite3MultipleCiphers | ส่วนขยายการเข้ารหัสสำหรับ SQLite เพื่ออนุญาตให้ไฟล์ฐานข้อมูลทั้งหมดถูกเข้ารหัส (รวมถึงบันทึกการเขียนล่วงหน้า ("WAL"), บันทึกประจำวัน, การย้อนกลับ, …) |
SQLiteสตูดิโอ | โปรแกรมแก้ไข Visual SQLite (ซึ่งคุณสามารถใช้ได้) เพื่อทดสอบ ดาวน์โหลด และดูกล่องจดหมายสำหรับการพัฒนา |
SQLite | เลเยอร์ฐานข้อมูลแบบฝังสำหรับพื้นที่จัดเก็บ IMAP ที่ปรับขนาดได้ ครบถ้วนในตัวเอง รวดเร็ว และยืดหยุ่น |
เครื่องสแกนสแปม | เครื่องมือป้องกันสแปม การกรองอีเมล และการป้องกันฟิชชิ่งของ Node.js (ทางเลือกของเราคือ นักฆ่าสแปม และ ตอบกลับ). |
ส้มเขียวหวาน | DNS ผ่านคำขอ HTTPS ด้วย Node.js และการแคชโดยใช้ Redis ซึ่งรับประกันความสอดคล้องทั่วโลกและอีกมากมาย |
ธันเดอร์เบิร์ด | ทีมพัฒนาของเราใช้สิ่งนี้ (และแนะนำสิ่งนี้ด้วย) เป็น ไคลเอนต์อีเมลที่ต้องการใช้กับส่งต่ออีเมล. |
UTM | ทีมพัฒนาของเราใช้สิ่งนี้เพื่อสร้างเครื่องเสมือนสำหรับ iOS และ macOS เพื่อทดสอบไคลเอนต์อีเมลที่แตกต่างกัน (พร้อมกัน) กับเซิร์ฟเวอร์ IMAP และ SMTP ของเรา |
อูบุนตู | ระบบปฏิบัติการเซิร์ฟเวอร์บน Linux แบบโอเพ่นซอร์สสมัยใหม่ซึ่งขับเคลื่อนโครงสร้างพื้นฐานทั้งหมดของเรา |
ไวลด์ดั๊ก | ไลบรารีเซิร์ฟเวอร์ IMAP – ดูหมายเหตุใน การขจัดไฟล์แนบที่ซ้ำกัน และ รองรับโปรโตคอล IMAP. |
ดีกว่า-sqlite3-หลายรหัส | ไลบรารี API ที่รวดเร็วและง่ายดายสำหรับ Node.js เพื่อโต้ตอบกับ SQLite3 โดยทางโปรแกรม |
เทมเพลตอีเมล | กรอบงานอีเมลที่เป็นมิตรต่อนักพัฒนาเพื่อสร้าง ดูตัวอย่าง และส่งอีเมลที่กำหนดเอง (เช่น การแจ้งเตือนบัญชี และอื่นๆ) |
json-sql | ตัวสร้างแบบสอบถาม SQL โดยใช้ไวยากรณ์สไตล์ Mongo สิ่งนี้ช่วยประหยัดเวลาของทีมพัฒนาของเราเนื่องจากเราสามารถเขียนต่อไปในสไตล์ Mongo ทั่วทั้งสแต็กด้วยวิธีไม่เชื่อเรื่องฐานข้อมูล นอกจากนี้ยังช่วยหลีกเลี่ยงการโจมตีแบบฉีด SQL โดยใช้พารามิเตอร์แบบสอบถาม |
ผู้ตรวจสอบโครงร่าง knex | ยูทิลิตี้ SQL เพื่อดึงข้อมูลเกี่ยวกับสคีมาฐานข้อมูลที่มีอยู่ สิ่งนี้ช่วยให้เราตรวจสอบได้อย่างง่ายดายว่าดัชนี ตาราง คอลัมน์ ข้อจำกัด และอื่นๆ ทั้งหมดนั้นถูกต้องและ 1:1 ด้วยวิธีที่ควรจะเป็น เรายังเขียนตัวช่วยอัตโนมัติเพื่อเพิ่มคอลัมน์และดัชนีใหม่หากมีการเปลี่ยนแปลงกับสคีมาฐานข้อมูล (พร้อมการแจ้งเตือนข้อผิดพลาดโดยละเอียดอย่างยิ่งด้วย) |
คุกเข่า | ตัวสร้างแบบสอบถาม SQL ซึ่งเราใช้เฉพาะสำหรับการย้ายฐานข้อมูลและการตรวจสอบสคีมาเท่านั้น knex-schema-inspector . |
ส้มแมนดาริน | อัตโนมัติ i18n การแปลวลีพร้อมรองรับการใช้ Markdown API การแปลของ Google Cloud. |
mx-เชื่อมต่อ | แพ็คเกจ Node.js เพื่อแก้ไขและสร้างการเชื่อมต่อกับเซิร์ฟเวอร์ MX และจัดการข้อผิดพลาด |
pm2 | ผู้จัดการกระบวนการผลิต Node.js พร้อมโหลดบาลานเซอร์ในตัว (ปรับแต่งอย่างละเอียด เพื่อประสิทธิภาพ) |
เซิร์ฟเวอร์ smtp | ไลบรารีเซิร์ฟเวอร์ SMTP – เราใช้สิ่งนี้สำหรับการแลกเปลี่ยนอีเมล ("MX") และเซิร์ฟเวอร์ SMTP ขาออก |
ImapTest | เครื่องมือที่มีประโยชน์สำหรับการทดสอบเซิร์ฟเวอร์ IMAP เทียบกับเกณฑ์มาตรฐานและความเข้ากันได้ของโปรโตคอล IMAP ตามข้อกำหนด RFC โครงการนี้ถูกสร้างขึ้นโดย โดฟคอต ทีม (เซิร์ฟเวอร์ IMAP และ POP3 แบบโอเพ่นซอร์สที่ใช้งานตั้งแต่เดือนกรกฎาคม 2545) เราได้ทดสอบเซิร์ฟเวอร์ IMAP ของเราอย่างกว้างขวางด้วยเครื่องมือนี้ |
คุณสามารถค้นหาโครงการอื่น ๆ ที่เราใช้อยู่ ซอร์สโค้ดของเราบน GitHub.
ผู้ให้บริการ
ผู้ให้บริการ | วัตถุประสงค์ |
---|---|
คลาวด์แฟลร์ | ผู้ให้บริการ DNS, การตรวจสอบสภาพ, โหลดบาลานเซอร์ และพื้นที่เก็บข้อมูลสำรองที่ใช้ คลาวด์แฟลร์ R2. |
มหาสมุทรดิจิตอล | โฮสติ้งเซิร์ฟเวอร์เฉพาะ พื้นที่เก็บข้อมูลบล็อก SSD และฐานข้อมูลที่ได้รับการจัดการ |
วัลเตอร์ | โฮสติ้งเซิร์ฟเวอร์เฉพาะและพื้นที่เก็บข้อมูลบล็อก SSD |
ความคิด
หลักการ
ส่งต่ออีเมลได้รับการออกแบบตามหลักการเหล่านี้:
- เป็นมิตรกับนักพัฒนา ให้ความสำคัญกับความปลอดภัยและความเป็นส่วนตัว และโปร่งใสเสมอ
- เป็นไปตาม MVC, ยูนิกซ์, KISS, DRY, YAGNI, ปัจจัยสิบสอง, มีดโกนของ Occam, และ การลองใช้
- กำหนดเป้าหมายกระท่อนกระแท่น บูตสแตรป และ ราเมนมีกำไร นักพัฒนา
การทดลอง
ทีแอลอาร์; ท้ายที่สุดแล้ว การใช้พื้นที่จัดเก็บอ็อบเจ็กต์ที่เข้ากันได้กับ S3 และ/หรือตารางเสมือนนั้นไม่สามารถทำได้ในทางเทคนิคด้วยเหตุผลด้านประสิทธิภาพและมีแนวโน้มที่จะเกิดข้อผิดพลาดเนื่องจากข้อจำกัดของหน่วยความจำ
เราได้ทำการทดลองเล็กน้อยซึ่งนำไปสู่โซลูชัน SQLite ขั้นสุดท้ายตามที่กล่าวไว้ข้างต้น
หนึ่งในนั้นคือการลองใช้ อาร์โคลน และ SQLite พร้อมกับเลเยอร์การจัดเก็บข้อมูลที่เข้ากันได้กับ S3
การทดลองนั้นทำให้เราเข้าใจเพิ่มเติมและค้นพบกรณี Edge ที่เกี่ยวข้องกับ rclone, SQLite และ VFS การใช้งาน:
- หากคุณเปิดใช้งาน
--vfs-cache-mode writes
ตั้งค่าสถานะด้วย rclone จากนั้นการอ่านจะเป็นเรื่องปกติ แต่การเขียนจะถูกแคชไว้- หากคุณมีเซิร์ฟเวอร์ IMAP หลายตัวที่กระจายอยู่ทั่วโลก แคชจะถูกปิดทั่วทั้งเซิร์ฟเวอร์ เว้นแต่คุณจะมีตัวเขียนเพียงตัวเดียวและผู้ฟังหลายตัว (เช่น วิธีการแบบ pub/sub)
- สิ่งนี้ซับซ้อนอย่างไม่น่าเชื่อ และการเพิ่มความซับซ้อนเพิ่มเติมเช่นนี้จะส่งผลให้เกิดความล้มเหลวจุดเดียวมากขึ้น
- ผู้ให้บริการพื้นที่จัดเก็บข้อมูลที่เข้ากันได้กับ S3 ไม่รองรับการเปลี่ยนแปลงไฟล์บางส่วน ซึ่งหมายถึงการเปลี่ยนแปลงใด ๆ ของ
.sqlite
จะส่งผลให้มีการเปลี่ยนแปลงและอัพโหลดฐานข้อมูลใหม่ทั้งหมด - โซลูชั่นอื่น ๆ เช่น
rsync
มีอยู่ แต่ไม่ได้มุ่งเน้นไปที่การบันทึกล่วงหน้า ("WAL") การสนับสนุน – ดังนั้นเราจึงได้ตรวจสอบ Litestream โชคดีที่การใช้การเข้ารหัสของเราได้เข้ารหัสแล้ว WAL ไฟล์ให้เรา ดังนั้นเราจึงไม่จำเป็นต้องพึ่งพา Litestream สำหรับเรื่องนั้น อย่างไรก็ตาม เรายังไม่มั่นใจใน Litestream สำหรับการใช้งานจริง และมีหมายเหตุบางประการด้านล่างนี้ - การใช้ตัวเลือกนี้ของ
--vfs-cache-mode writes
(ที่ เท่านั้น วิธีใช้ SQLite แทนrclone
สำหรับการเขียน) จะพยายามคัดลอกฐานข้อมูลทั้งหมดตั้งแต่เริ่มต้นในหน่วยความจำ - การจัดการกล่องจดหมายขนาด 10 GB หนึ่งกล่องก็โอเค แต่การจัดการกล่องจดหมายหลายกล่องที่มีพื้นที่จัดเก็บสูงเกินไปจะทำให้เซิร์ฟเวอร์ IMAP ทำงานอยู่ในข้อจำกัดของหน่วยความจำและENOMEM
ข้อผิดพลาด ข้อผิดพลาดในการแบ่งส่วน และความเสียหายของข้อมูล
- หากคุณพยายามใช้ SQLite ตารางเสมือนจริง (เช่น การใช้ เอส3ดีบี) เพื่อให้มีข้อมูลอยู่บนเลเยอร์พื้นที่จัดเก็บข้อมูลที่เข้ากันได้กับ S3 คุณจะพบกับปัญหาอื่นๆ อีกหลายปัญหา:
- การอ่านและเขียนจะช้ามากเนื่องจากตำแหน่งข้อมูล S3 API จะต้องถูกโจมตีด้วย HTTP
GET
,PUT
,HEAD
, และPOST
วิธีการ - การทดสอบการพัฒนาแสดงให้เห็นว่าบันทึกที่เกิน 500K-1M+ บนอินเทอร์เน็ตไฟเบอร์ยังคงถูกจำกัดด้วยปริมาณงานในการเขียนและการอ่านไปยังผู้ให้บริการที่รองรับ S3 ตัวอย่างเช่น นักพัฒนาของเราทำงาน
for
วนซ้ำเพื่อทำ SQL ตามลำดับทั้งสองINSERT
ข้อความสั่งและข้อความที่เขียนข้อมูลจำนวนมาก ในทั้งสองกรณีประสิทธิภาพการทำงานช้ามาก - ตารางเสมือนจริง ไม่สามารถมีดัชนีได้,
ALTER TABLE
งบและ อื่น ข้อจำกัด – ซึ่งทำให้เกิดความล่าช้ามากกว่า 1-2 นาทีขึ้นไป ขึ้นอยู่กับปริมาณข้อมูล - ออบเจ็กต์ถูกจัดเก็บโดยไม่ได้เข้ารหัสและไม่มีการสนับสนุนการเข้ารหัสแบบเนทีฟพร้อมใช้งาน
- การอ่านและเขียนจะช้ามากเนื่องจากตำแหน่งข้อมูล S3 API จะต้องถูกโจมตีด้วย HTTP
- เรายังสำรวจการใช้ sqlite-s3vfs ซึ่งมีแนวความคิดและทางเทคนิคคล้ายกับหัวข้อย่อยก่อนหน้า (ดังนั้นจึงมีปัญหาเดียวกัน) ความเป็นไปได้คือการใช้แบบกำหนดเอง
sqlite3
สร้างด้วยการเข้ารหัสเช่น wxSQLite3 (ซึ่งปัจจุบันเราใช้ในโซลูชันของเราด้านบน) ผ่าน แก้ไขไฟล์ติดตั้ง. - อีกแนวทางหนึ่งที่เป็นไปได้คือการใช้ ส่วนขยายมัลติเพล็กซ์อย่างไรก็ตาม มีข้อจำกัดอยู่ที่ 32 GB และจะต้องปวดหัวกับการสร้างและการพัฒนาที่ซับซ้อน
ALTER TABLE
จำเป็นต้องมีคำสั่ง (ดังนั้นสิ่งนี้จึงตัดการใช้ตารางเสมือนโดยสิ้นเชิง) พวกเราต้องการALTER TABLE
งบเพื่อที่จะเบ็ดของเราด้วยknex-schema-inspector
เพื่อให้ทำงานได้อย่างถูกต้อง ซึ่งรับประกันว่าข้อมูลจะไม่เสียหาย และแถวที่ดึงมาสามารถแปลงเป็นเอกสารที่ถูกต้องตามที่เรากำหนดmongoose
คำจำกัดความของสคีมา (ซึ่งรวมถึงข้อจำกัด ประเภทตัวแปร และการตรวจสอบข้อมูลตามอำเภอใจ)- โปรเจ็กต์ที่เข้ากันได้กับ S3 เกือบทั้งหมดที่เกี่ยวข้องกับ SQLite ในชุมชนโอเพ่นซอร์สนั้นเป็น Python (และไม่ใช่ JavaScript ที่เราใช้สำหรับสแต็กของเรา 100%)
- ไลบรารีการบีบอัดเช่น sqlite-zstd (ดู ความคิดเห็น) ดูมีแนวโน้ม แต่ อาจยังไม่พร้อมสำหรับการใช้งานการผลิต. แทนที่จะใช้การบีบอัดฝั่งแอปพลิเคชันกับประเภทข้อมูลเช่น
String
,Object
,Map
,Array
,Set
, และBuffer
จะเป็นแนวทางที่สะอาดกว่าและง่ายกว่า (และโยกย้ายได้ง่ายกว่าด้วย เนื่องจากเราสามารถจัดเก็บไฟล์Boolean
ธงหรือคอลัมน์ – หรือแม้แต่การใช้PRAGMA
user_version=1
สำหรับการบีบอัดหรือuser_version=0
โดยไม่มีการบีบอัดเป็นข้อมูลเมตาของฐานข้อมูล)- โชคดีที่เราได้นำไฟล์แนบที่ซ้ำกันไปใช้ในพื้นที่จัดเก็บข้อมูลเซิร์ฟเวอร์ IMAP ของเราแล้ว ดังนั้นทุกข้อความที่มีไฟล์แนบเดียวกันจะไม่เก็บสำเนาของไฟล์แนบ แทนที่จะเก็บไฟล์แนบไฟล์เดียวไว้สำหรับข้อความและเธรดหลายรายการในกล่องจดหมาย (และไฟล์แนบต่างประเทศ เพื่อใช้อ้างอิงในภายหลัง)
- โปรเจ็กต์ Litestream ซึ่งเป็นโซลูชันการจำลองและสำรองข้อมูล SQLite มีแนวโน้มที่ดีและเราจะใช้มันในอนาคต
- ไม่ให้เสื่อมเสียชื่อเสียงของผู้เขียน – เนื่องจากเราชอบงานและการมีส่วนร่วมของพวกเขาในโอเพ่นซอร์สมานานกว่าทศวรรษแล้ว – อย่างไรก็ตามจากการใช้งานจริงปรากฏว่ามี อาจจะปวดหัวมาก และ ข้อมูลที่อาจสูญหายจากการใช้งาน.
- การกู้คืนข้อมูลสำรองจะต้องราบรื่นและไม่สำคัญ การใช้โซลูชันเช่น MongoDB ด้วย
mongodump
และmongoexport
ไม่เพียงแต่น่าเบื่อเท่านั้น แต่ยังใช้เวลานานและมีความซับซ้อนในการกำหนดค่าอีกด้วย- ฐานข้อมูล SQLite ทำให้มันง่าย (เป็นไฟล์เดียว)
- เราต้องการออกแบบโซลูชันที่ผู้ใช้สามารถนำกล่องจดหมายและออกไปได้ทุกเมื่อ
- คำสั่ง Node.js อย่างง่ายเพื่อ
fs.unlink('mailbox.sqlite'))
และจะถูกลบออกจากที่เก็บข้อมูลดิสก์อย่างถาวร - ในทำนองเดียวกัน เราสามารถใช้ API ที่เข้ากันได้กับ S3 กับ HTTP
DELETE
เพื่อลบสแน็ปช็อตและการสำรองข้อมูลสำหรับผู้ใช้ได้อย่างง่ายดาย
- คำสั่ง Node.js อย่างง่ายเพื่อ
- SQLite เป็นโซลูชันที่ง่ายที่สุด รวดเร็วที่สุด และคุ้มค่าที่สุด
ขาดทางเลือกอื่น
ตามความรู้ของเรา ไม่มีบริการอีเมลอื่นใดที่ได้รับการออกแบบในลักษณะนี้หรือเป็นโอเพ่นซอร์ส
เรา คิดว่านี่อาจเป็นเพราะ ไปยังบริการอีเมลที่มีอยู่ซึ่งมีเทคโนโลยีเดิมในการผลิตด้วย รหัสสปาเก็ตตี้ 🍝.
ผู้ให้บริการอีเมลที่มีอยู่ส่วนใหญ่หากไม่ใช่ทั้งหมดนั้นเป็นแบบปิดหรือโฆษณาเป็นโอเพ่นซอร์ส แต่ในความเป็นจริงมีเพียงส่วนหน้าเท่านั้นที่เป็นโอเพ่นซอร์ส
ส่วนที่ละเอียดอ่อนที่สุดของอีเมล (การโต้ตอบที่เก็บข้อมูล/IMAP/SMTP จริง) เสร็จสิ้นทั้งหมดบนแบ็คเอนด์ (เซิร์ฟเวอร์) และ ไม่ ที่ส่วนหน้า (ไคลเอนต์).
ลองส่งต่ออีเมล
สมัครได้แล้ววันนี้ที่ https://forwardemail.net! 🚀