صناديق بريد 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 الخاص بنا للحفاظ على مزامنة صندوق البريد الخاص بك. يتضمن ذلك كتابة وتخزين مسودات رسائل البريد الإلكتروني والإجراءات الأخرى التي قد تقوم بها (على سبيل المثال، تصنيف رسالة بريد إلكتروني على أنها مهمة أو وضع علامة على بريد إلكتروني كبريد عشوائي/بريد غير هام).
-
تتلقى خوادم تبادل البريد (المعروفة باسم خوادم "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:
قاعدة البيانات | التشفير في الراحة | وضع الحماية صناديق البريد | رخصة | تستخدم في كل مكان |
---|---|---|---|---|
سكليتي ⭐ | ✅ نعم مع SQLite3MultipleCiphers | ✅ | ✅ المجال العام | ✅ |
MongoDB | ❌ "متوفر في MongoDB Enterprise فقط" | ❌ قاعدة بيانات علائقية | ❌AGPL و SSPL-1.0 | ❌ |
rqlite | ❌ الشبكة فقط | ❌ قاعدة بيانات علائقية | ✅ MIT | ❌ |
com.dqlite | ❌ لم تختبر ولم تدعم بعد؟ | ❌ لم تختبر ولم تدعم بعد؟ | ✅ LGPL-3.0-only | ❌ |
PostgreSQL | ✅ نعم | ❌ قاعدة بيانات علائقية | ✅ PostgreSQL (مشابه ل BSD أو MIT ) | ❌ |
ماريا دي بي | ✅ لInnoDB فقط | ❌ قاعدة بيانات علائقية | ✅ GPLv2 و BUSL-1.1 | ❌ |
صرصورDB | ❌ ميزة خاصة بالمؤسسات فقط | ❌ قاعدة بيانات علائقية | ❌ BUSL-1.1 و اخرين | ❌ |
هنا أ منشور مدونة يقارن بين العديد من خيارات تخزين قاعدة بيانات SQLite في الجدول أعلاه.
الأمان
في جميع الأوقات نستخدمها التشفير في الراحة (AES-256), التشفير أثناء النقل (TLS), DNS عبر HTTPS ("DoH") باستخدام 🍊 يوسفي، و com.sqleet (ChaCha20-Poly1305) التشفير على صناديق البريد. بالإضافة إلى ذلك، نستخدم المصادقة الثنائية القائمة على الرمز المميز (على عكس الرسائل النصية القصيرة التي يشتبه فيها هجمات الرجل في المنتصف)، تدوير مفاتيح 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
).
يتم تشفير كل قاعدة من قواعد البيانات هذه بنفسها باستخدام كلمة المرور الخاصة بك (التي تمتلكها أنت فقط). com.sqleet (ChaCha20-Poly1305). وهذا يعني أن صناديق البريد الخاصة بك مشفرة بشكل فردي، ومكتفية بذاتها، وضع الحماية، والمحمولة.
لقد قمنا بضبط 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 كما هو محدد من ملف وثائق براغما الرسمية.
التزامن
تلدر؛ نحن نستخدم
WebSocket
للقراءة والكتابة المتزامنة في صناديق بريد SQLite المشفرة الخاصة بك.
يقرأ
قد يتم حل مشكلة عميل البريد الإلكتروني الخاص بك على هاتفك imap.forwardemail.net
إلى أحد عناوين IP الرقمية الخاصة بنا - وقد يقوم عميل سطح المكتب الخاص بك بحل عنوان IP منفصل من عنوان IP مختلف مزود كليا.
بغض النظر عن خادم IMAP الذي يتصل به عميل البريد الإلكتروني الخاص بك، فإننا نريد أن تتم قراءة الاتصال من قاعدة بياناتك في الوقت الفعلي وبدقة 100%. ويتم ذلك من خلال WebSockets.
يكتب
تختلف الكتابة إلى قاعدة البيانات الخاصة بك قليلًا – نظرًا لأن SQLite عبارة عن قاعدة بيانات مضمنة ويعيش صندوق البريد الخاص بك في ملف واحد افتراضيًا.
لقد استكشفنا خيارات مثل litestream
, rqlite
، و dqlite
أدناه - ولكن لم يلبي أي منها متطلباتنا.
لإنجاز عمليات الكتابة باستخدام تسجيل الكتابة المسبق ("WAL") ممكّن - نحتاج إلى التأكد من أن خادمًا واحدًا فقط ("الأساسي") مسؤول عن القيام بذلك. WAL يعمل على تسريع التزامن بشكل كبير ويسمح لكاتب واحد والعديد من القراء.
يتم تشغيل الأساسي على خوادم البيانات مع وحدات التخزين المحملة التي تحتوي على صناديق البريد المشفرة. من وجهة نظر التوزيع، يمكنك مراعاة جميع خوادم IMAP الفردية الموجودة خلفها imap.forwardemail.net
أن تكون خوادم ثانوية ("ثانوية").
نحن ننجز التواصل في اتجاهين مع WebSockets:
- تستخدم الخوادم الأساسية مثيلاً لـ ws'س
WebSocketServer
الخادم. - تستخدم الخوادم الثانوية مثيلاً لـ ws'س
WebSocket
العميل الذي تم تغليفه به websocket كما وعدت و إعادة الاتصال websocket. يضمن هذان الغلافان أنWebSocket
يعيد الاتصال ويمكنه إرسال واستقبال البيانات لعمليات الكتابة في قاعدة بيانات محددة.
النسخ الاحتياطية
تلدر؛ يتم عمل نسخ احتياطية لصناديق البريد المشفرة الخاصة بك يوميًا. يمكنك أيضًا طلب نسخة احتياطية جديدة على الفور أو تنزيل أحدث نسخة احتياطية في أي وقت من حسابي المجالات اسماء مستعارة.
بالنسبة للنسخ الاحتياطية، نقوم ببساطة بتشغيل SQLite VACUUM INTO
الأمر كل يوم أثناء معالجة أوامر IMAP، مما يعزز كلمة المرور المشفرة من اتصال IMAP في الذاكرة. يتم تخزين النسخ الاحتياطية في حالة عدم اكتشاف نسخة احتياطية موجودة أو في حالة ظهور خطأ SHA-256 تم تغيير التجزئة في الملف مقارنة بأحدث نسخة احتياطية.
لاحظ أننا نستخدم ملف VACUUM INTO
الأمر بدلا من المدمج في backup
الأمر لأنه إذا تم تعديل الصفحة أثناء backup
عملية القيادة، ثم عليه أن يبدأ من جديد. ال VACUUM INTO
سوف يأخذ الأمر لقطة. انظر هذه التعليقات على جيثب و أخبار القراصنة لمزيد من البصيرة.
بالإضافة إلى ذلك نستخدم VACUUM INTO
في مقابل backup
، بسبب ال backup
سيترك الأمر قاعدة البيانات غير مشفرة لفترة وجيزة حتى rekey
تم استدعاؤه (راجع GitHub تعليق للبصيرة).
سيقوم الثانوي بإرشاد الابتدائية على WebSocket
اتصال لتنفيذ النسخ الاحتياطي - وسيتلقى البرنامج الأساسي بعد ذلك الأمر للقيام بذلك وسيقوم بعد ذلك بما يلي:
- الاتصال بصندوق البريد المشفر الخاص بك.
- الحصول على قفل الكتابة.
- قم بتشغيل نقطة تفتيش WAL عبر
wal_checkpoint(PASSIVE)
. - تشغيل
VACUUM INTO
أمر سكليتي. - تأكد من إمكانية فتح الملف المنسوخ باستخدام كلمة المرور المشفرة (الحماية/الحماية من الدمى).
- قم بتحميله إلى 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 والمزيد. |
MongoDB | حل قاعدة بيانات NoSQL الذي نستخدمه لتخزين جميع البيانات الأخرى خارج صناديق البريد (مثل حسابك والإعدادات والمجالات وتكوينات الاسم المستعار). |
النمس | نمذجة مستند كائن MongoDB ("ODM") الذي نستخدمه عبر مجموعتنا بأكملها. لقد كتبنا مساعدين خاصين يسمحون لنا بمواصلة الاستخدام ببساطة النمس مع SQLite 🎉 |
Node.js | Node.js هي بيئة تشغيل JavaScript مفتوحة المصدر ومتعددة الأنظمة الأساسية والتي تدير جميع عمليات الخادم لدينا. |
Nodemailer | حزمة Node.js لإرسال رسائل البريد الإلكتروني وإنشاء الاتصالات والمزيد. نحن الراعي الرسمي لهذا المشروع. |
ريديس | قاعدة بيانات في الذاكرة للتخزين المؤقت وقنوات النشر/الاشتراك وDNS عبر طلبات HTTPS. |
SQLite3MultipleCiphers | ملحق التشفير لـ SQLite للسماح بتشفير ملفات قاعدة البيانات بأكملها (بما في ذلك سجل الكتابة المسبق ("WAL")، مجلة، التراجع، ...). |
SQLiteStudio | محرر Visual SQLite (والذي يمكنك استخدامه أيضًا) لاختبار صناديق بريد التطوير وتنزيلها وعرضها. |
سكليتي | طبقة قاعدة بيانات مضمنة لتخزين IMAP قابل للتطوير ومكتفي بذاته وسريع ومرن. |
ماسح البريد المزعج | أداة Node.js لمكافحة البريد العشوائي وتصفية البريد الإلكتروني ومنع التصيد الاحتيالي (بديلنا لـ قاتل البريد العشوائي و com.rspamd). |
يوسفي | DNS عبر طلبات HTTPS باستخدام Node.js والتخزين المؤقت باستخدام Redis - مما يضمن الاتساق العالمي وغير ذلك الكثير. |
ثندربيرد | يستخدم فريق التطوير لدينا هذا (ويوصي بهذا أيضًا) كـ عميل البريد الإلكتروني المفضل لاستخدامه مع إعادة توجيه البريد الإلكتروني. |
UTM | يستخدم فريق التطوير لدينا إنشاء أجهزة افتراضية لنظامي التشغيل iOS وmacOS من أجل اختبار عملاء البريد الإلكتروني المختلفين (بالتوازي) مع خوادم IMAP وSMTP الخاصة بنا. |
أوبونتو | نظام تشغيل خادم حديث مفتوح المصدر قائم على نظام Linux والذي يعمل على تشغيل جميع بنيتنا التحتية. |
البطة البرية | مكتبة خادم IMAP – راجع ملاحظاتها على إلغاء تكرار المرفقات و دعم بروتوكول IMAP. |
أفضل-sqlite3-أصفار متعددة | مكتبة API سريعة وبسيطة لـ Node.js للتفاعل مع SQLite3 برمجيًا. |
قوالب البريد الإلكتروني | إطار بريد إلكتروني صديق للمطورين لإنشاء رسائل بريد إلكتروني مخصصة ومعاينتها وإرسالها (مثل إشعارات الحساب والمزيد). |
json-sql | منشئ استعلام SQL باستخدام بناء جملة نمط مونغو. وهذا يوفر وقت فريق التطوير لدينا حيث يمكننا الاستمرار في الكتابة بأسلوب Mongo عبر المجموعة بأكملها باستخدام نهج حيادي لقاعدة البيانات. كما أنه يساعد على تجنب هجمات حقن SQL باستخدام معلمات الاستعلام. |
مفتش مخطط knex | أداة SQL لاستخراج المعلومات حول مخطط قاعدة البيانات الموجودة. يتيح لنا ذلك التحقق بسهولة من صحة جميع المؤشرات والجداول والأعمدة والقيود وغيرها 1:1 مع كيف ينبغي أن يكونوا. حتى أننا كتبنا مساعدين آليين لإضافة أعمدة وفهارس جديدة إذا تم إجراء تغييرات على مخططات قاعدة البيانات (مع تنبيهات تفصيلية للغاية للأخطاء أيضًا). |
knex | منشئ استعلام SQL الذي نستخدمه فقط لعمليات ترحيل قاعدة البيانات والتحقق من صحة المخطط من خلاله knex-schema-inspector . |
الماندرين | تلقائي i18n ترجمة العبارة مع دعم استخدام Markdown واجهة برمجة تطبيقات الترجمة السحابية من Google. |
mx-connect | حزمة Node.js لحل وإنشاء الاتصالات مع خوادم MX ومعالجة الأخطاء. |
مساء2 | مدير عملية إنتاج Node.js مع موازن تحميل مدمج (ضبطها بدقة للأداء). |
خادم SMTP | مكتبة خادم SMTP - نستخدمها لتبادل البريد ("MX") وخوادم SMTP الصادرة. |
ImapTest | أداة مفيدة لاختبار خوادم IMAP مقابل المعايير وتوافق بروتوكول IMAP لمواصفات RFC. تم إنشاء هذا المشروع بواسطة حمامة فريق (خادم IMAP وPOP3 مفتوح المصدر نشط من يوليو 2002). لقد اختبرنا خادم IMAP الخاص بنا على نطاق واسع باستخدام هذه الأداة. |
يمكنك العثور على مشاريع أخرى نستخدمها فيها كود المصدر الخاص بنا على GitHub.
مقدمي الخدمات
مزود | غاية |
---|---|
كلاود فلير | مزود DNS، والفحوصات الصحية، وموازنات التحميل، وتخزين النسخ الاحتياطي باستخدام كلاودفلير R2. |
المحيط الرقمي | استضافة خادم مخصص، وتخزين كتلة SSD، وقواعد البيانات المُدارة. |
فولتر | استضافة خادم مخصص وتخزين كتلة SSD. |
أفكار
مبادئ
تم تصميم إعادة توجيه البريد الإلكتروني وفقًا لهذه المبادئ:
- كن دائمًا صديقًا للمطورين، مع التركيز على الأمان والخصوصية، والشفافية.
- الالتزام MVC, يونكس, KISS, DRY, YAGNI, اثنا عشر عامل, الحلاقة أوكام، و تطبيق تجريبي
- استهدف Scrapy، Bootstrapped، و رامين مربح مطور
التجارب
تلدر؛ في نهاية المطاف، فإن استخدام تخزين الكائنات المتوافق مع S3 و/أو الجداول الافتراضية ليس ممكنًا من الناحية الفنية لأسباب تتعلق بالأداء ويكون عرضة للخطأ بسبب قيود الذاكرة.
لقد أجرينا بعض التجارب التي أدت إلى حل SQLite النهائي كما تمت مناقشته أعلاه.
واحدة من هذه كانت محاولة استخدام com.rclone وSQLite مع طبقة تخزين متوافقة مع S3.
قادتنا هذه التجربة إلى فهم واكتشاف حالات الحافة المحيطة بـ rclone وSQLite و VFS الاستخدام:
- إذا قمت بتمكين
--vfs-cache-mode writes
ضع علامة باستخدام rclone، وستكون عمليات القراءة على ما يرام، ولكن سيتم تخزين عمليات الكتابة مؤقتًا.- إذا كان لديك عدة خوادم IMAP موزعة عالميًا، فسيتم إيقاف تشغيل ذاكرة التخزين المؤقت عبرها ما لم يكن لديك كاتب واحد ومستمعين متعددين (على سبيل المثال، أسلوب النشر/الفرع).
- هذا أمر معقد بشكل لا يصدق، وإضافة أي تعقيد إضافي مثل هذا سيؤدي إلى المزيد من نقاط الفشل الفردية.
- لا يدعم موفرو التخزين المتوافقون مع S3 التغييرات الجزئية للملفات - مما يعني أي تغيير في
.sqlite
سيؤدي الملف إلى تغيير كامل وإعادة تحميل قاعدة البيانات. - حلول أخرى مثل
rsync
موجودة، لكنها لا تركز على سجل الكتابة المسبق ("WAL") الدعم - لذلك انتهينا من مراجعة Litestream. ولحسن الحظ، فإن استخدام التشفير لدينا يقوم بالفعل بتشفير ملف WAL الملفات لنا، لذلك لا نحتاج إلى الاعتماد على Litestream لذلك. ومع ذلك، لم نكن واثقين بعد من استخدام Litestream في الإنتاج ولدينا بعض الملاحظات أدناه حول ذلك. - باستخدام هذا الخيار من
--vfs-cache-mode writes
(ال فقط طريقة لاستخدام SQLite أكثرrclone
للكتابة) سيحاول نسخ قاعدة البيانات بأكملها من نقطة الصفر في الذاكرة - يعد التعامل مع صندوق بريد واحد بسعة 10 جيجابايت أمراً مقبولاً، إلا أن التعامل مع صناديق بريد متعددة ذات مساحة تخزين عالية للغاية سيؤدي إلى تشغيل خوادم IMAP في قيود الذاكرة وENOMEM
الأخطاء وأخطاء التجزئة وفساد البيانات.
- إذا حاولت استخدام SQLite الجداول الافتراضية (على سبيل المثال باستخدام s3db) من أجل نشر البيانات على طبقة تخزين متوافقة مع S3، فسوف تواجه العديد من المشكلات الأخرى:
- ستكون القراءة والكتابة بطيئة للغاية حيث يجب الوصول إلى نقاط نهاية S3 API باستخدام HTTP
GET
,PUT
,HEAD
، وPOST
طُرق. - أظهرت اختبارات التطوير أن ما يزيد عن 500 ألف - 1 مليون+ من السجلات على إنترنت الألياف لا يزال محدودًا بإنتاجية الكتابة والقراءة لمقدمي الخدمات المتوافقين مع S3. على سبيل المثال، ركض مطورونا
for
حلقات للقيام بكلا SQL المتسلسلINSERT
البيانات وتلك التي كتبت بكميات كبيرة من البيانات. وفي كلتا الحالتين كان الأداء بطيئا بشكل مذهل. - الجداول الافتراضية لا يمكن أن يكون لها فهارس,
ALTER TABLE
تصريحات، و آخر محددات – مما يؤدي إلى تأخير يصل إلى 1-2 دقيقة أو أكثر حسب كمية البيانات. - تم تخزين الكائنات غير مشفرة ولا يتوفر دعم التشفير الأصلي بسهولة.
- ستكون القراءة والكتابة بطيئة للغاية حيث يجب الوصول إلى نقاط نهاية S3 API باستخدام HTTP
- لقد استكشفنا أيضًا استخدام sqlite-s3vfs وهو مشابه من الناحية المفاهيمية والفنية للنقطة السابقة (لذلك فهو يحتوي على نفس المشكلات). سيكون الاحتمال هو استخدام العرف
sqlite3
بناء ملفوف بالتشفير مثل wxSQLite3 (الذي نستخدمه حاليًا في حلنا أعلاه) من خلال تحرير ملف الإعداد. - كان النهج المحتمل الآخر هو استخدام تمديد متعدد، ولكن هذا له حد قدره 32 جيجابايت وسيتطلب مشكلات معقدة في البناء والتطوير.
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'))
ويتم مسحه نهائيًا من مساحة تخزين القرص. - يمكننا بالمثل استخدام واجهة برمجة التطبيقات المتوافقة مع S3 مع HTTP
DELETE
لإزالة اللقطات والنسخ الاحتياطية للمستخدمين بسهولة.
- أوامر Node.js البسيطة لـ
- كان SQLite هو الحل الأبسط والأسرع والأكثر فعالية من حيث التكلفة.
عدم وجود البدائل
على حد علمنا، لم يتم تصميم أي خدمات بريد إلكتروني أخرى بهذه الطريقة كما أنها ليست مفتوحة المصدر.
نحن أعتقد أن هذا قد يكون بسبب إلى خدمات البريد الإلكتروني الحالية التي تتمتع بتكنولوجيا قديمة في الإنتاج كود السباغيتي 🍝.
معظم موفري خدمة البريد الإلكتروني الحاليين، إن لم يكن جميعهم، إما أن يكونوا مصدرًا مغلقًا أو يعلنون على أنهم مفتوح المصدر، ولكن في الواقع فإن واجهتهم الأمامية هي فقط مفتوحة المصدر.
الجزء الأكثر حساسية في البريد الإلكتروني (التخزين الفعلي/تفاعل IMAP/SMTP) يتم كل ذلك على الواجهة الخلفية (الخادم)، و لا على الواجهة الأمامية (العميل).
جرب إعادة توجيه البريد الإلكتروني
سجل اليوم في https://forwardemail.net! 🚀