البريد الإلكتروني المقاوم للكم: كيف نستخدم صناديق بريد SQLite المشفرة للحفاظ على أمان بريدك الإلكتروني

مقدمة
[!هام] خدمة البريد الإلكتروني لدينا هي مفتوح المصدر بنسبة 100% والتركيز على الخصوصية من خلال صناديق بريد SQLite الآمنة والمشفرة.
حتى أطلقنا دعم IMAPلقد استخدمنا MongoDB لتلبية احتياجاتنا المتعلقة بتخزين البيانات المستمرة.
هذه التكنولوجيا مذهلة وما زلنا نستخدمها حتى يومنا هذا - ولكن من أجل الحصول على تشفير ثابت مع MongoDB، تحتاج إلى استخدام مزود يقدم MongoDB Enterprise، مثل Digital Ocean أو Mongo Atlas - أو دفع ثمن ترخيص مؤسسي (وبعد ذلك يتعين عليك العمل مع زمن انتقال فريق المبيعات).
فريقنا في إعادة توجيه البريد الإلكتروني كنتُ بحاجة إلى حل تخزين سهل الاستخدام، وقابل للتطوير، وموثوق، ومشفّر لصناديق بريد IMAP. بصفتي مطورًا مفتوح المصدر، كان استخدام تقنية تتطلب دفع رسوم ترخيص للحصول على ميزة التشفير عند السكون أمرًا مخالفًا. مبادئنا - ولذلك قمنا بالتجربة والبحث وتطوير حل جديد من الصفر لحل هذه الاحتياجات.
بدلاً من استخدام قاعدة بيانات مشتركة لتخزين صناديق البريد الخاصة بك، نقوم بتخزين صناديق البريد الخاصة بك وتشفيرها بشكل فردي باستخدام كلمة المرور الخاصة بك (والتي تمتلكها أنت فقط). خدمة البريد الإلكتروني لدينا آمنة للغاية بحيث إذا نسيت كلمة المرور الخاصة بك، فإنك تفقد صندوق البريد الخاص بك (وتحتاج إلى التعافي باستخدام النسخ الاحتياطية غير المتصلة بالإنترنت أو البدء من جديد).
استمر في القراءة بينما نلقي نظرة متعمقة أدناه مقارنة بين مزودي خدمات البريد الإلكتروني, كيف تعمل خدمتنا, مجموعة التكنولوجيا لدينا، وأكثر.
مقارنة مزودي خدمة البريد الإلكتروني
نحن مزود خدمة البريد الإلكتروني الوحيد مفتوح المصدر بنسبة 100% والذي يركز على الخصوصية والذي يخزن صناديق بريد SQLite المشفرة بشكل فردي، ويقدم نطاقات وأسماء مستعارة ومستخدمين غير محدودة، ويدعم SMTP وIMAP وPOP3 الصادر:
على عكس موفري البريد الإلكتروني الآخرين، لا تحتاج إلى دفع تكاليف التخزين على أساس كل نطاق أو اسم مستعار مع Forward Email. مساحة التخزين مشتركة على حسابك بالكامل، لذا إذا كان لديك عدة أسماء نطاقات مخصصة وأسماء مستعارة متعددة على كل منها، فنحن الحل الأمثل لك. يُرجى العلم أنه لا يزال بإمكانك فرض حدود تخزينية لكل نطاق أو اسم مستعار، إذا رغبت في ذلك.
قراءة مقارنة خدمات البريد الإلكتروني
كيف يعمل؟
-
باستخدام عميل البريد الإلكتروني الخاص بك مثل Apple Mail أو Thunderbird أو Gmail أو Outlook - يمكنك الاتصال بشبكتنا الآمنة IMAP الخوادم باستخدام اسم المستخدم وكلمة المرور الخاصة بك:
- اسم المستخدم الخاص بك هو الاسم المستعار الكامل الخاص بك مع نطاقك مثل
[email protected]
. - يتم إنشاء كلمة المرور الخاصة بك بشكل عشوائي ويتم عرضها لك لمدة 30 ثانية فقط عند النقر فوقها إنشاء كلمة مرور من حسابي المجالات أسماء مستعارة.
- اسم المستخدم الخاص بك هو الاسم المستعار الكامل الخاص بك مع نطاقك مثل
-
بمجرد الاتصال، سيرسل لك عميل البريد الإلكتروني الخاص بك أوامر بروتوكول IMAP إلى خادم IMAP الخاص بنا للحفاظ على مزامنة صندوق بريدك. يشمل ذلك كتابة مسودات رسائل البريد الإلكتروني وتخزينها، بالإضافة إلى إجراءات أخرى قد تقوم بها (مثل تصنيف رسالة بريد إلكتروني كمهمة أو وضع علامة على أنها بريد عشوائي/غير مرغوب فيه).
-
تستقبل خوادم تبادل البريد (المعروفة باسم خوادم "MX") رسائل البريد الإلكتروني الواردة الجديدة وتخزنها في صندوق بريدك. عند حدوث ذلك، سيتلقى برنامج البريد الإلكتروني إشعارًا وسيزامن صندوق بريدك. يمكن لخوادم تبادل البريد لدينا إعادة توجيه بريدك الإلكتروني إلى مستلم واحد أو أكثر (بما في ذلك خطافات الويب)، قم بتخزين بريدك الإلكتروني في وحدة تخزين IMAP المشفرة لدينا، أو كلاهما!
[!نصيحة] هل ترغب بمعرفة المزيد؟ اقرأ كيفية إعداد إعادة توجيه البريد الإلكتروني, كيف تعمل خدمة تبادل البريد لدينا، أو عرض مرشدينا.
-
خلف الكواليس، يعمل تصميم تخزين البريد الإلكتروني الآمن لدينا بطريقتين للحفاظ على تشفير صناديق البريد الإلكتروني الخاصة بك وجعلها متاحة لك فقط:
-
عندما نتلقى بريدًا جديدًا لك من مرسل، تكتب خوادم تبادل البريد لدينا إلى صندوق بريد فردي ومؤقت ومشفر لك.
sequenceDiagram autonumber actor Sender Sender->>MX: Inbound message received for your alias (e.g. [email protected]). 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 ⭐ | ✅ نعم مع SQLite3 تشفيرات متعددة | ✅ | ✅ المجال العام | ✅ |
مونجو دي بي | ❌ "متوفر في MongoDB Enterprise فقط" | ❌ قاعدة بيانات علائقية | ❌ AGPL و SSPL-1.0 | ❌ |
rqlite | ❌ الشبكة فقط | ❌ قاعدة بيانات علائقية | ✅ MIT | ❌ |
دك لايت | ❌ لم يتم اختباره ولم يتم دعمه بعد؟ | ❌ لم يتم اختباره ولم يتم دعمه بعد؟ | ✅ LGPL-3.0-only | ❌ |
بوستجرس كيو ال | ✅ نعم | ❌ قاعدة بيانات علائقية | ✅ PostgreSQL (مشابه ل BSD أو MIT ) | ❌ |
ماريا دي بي | ✅ مخصص لـ InnoDB فقط | ❌ قاعدة بيانات علائقية | ✅ GPLv2 و BUSL-1.1 | ❌ |
قاعدة بيانات الصرصور | ❌ ميزة مخصصة للمؤسسات فقط | ❌ قاعدة بيانات علائقية | ❌ BUSL-1.1 و اخرين | ❌ |
وهنا هو تدوينة تقارن بين عدة خيارات لتخزين قاعدة بيانات SQLite في الجدول أعلاه.
حماية
نحن نستخدم في جميع الأوقات التشفير في حالة السكون (AES-256), التشفير أثناء النقل (TLS), DNS عبر HTTPS ("DoH") باستخدام 🍊 اليوسفي، و سكليت (تشاتشا20-بولي1305) تشفير صناديق البريد. بالإضافة إلى ذلك، نستخدم مصادقة ثنائية العوامل تعتمد على الرمز (على عكس الرسائل النصية القصيرة التي يُشتبه في أنها هجمات الرجل في المنتصف), مفاتيح SSH المُدارة مع تعطيل الوصول إلى الجذر، والوصول الحصري إلى الخوادم من خلال عناوين IP المقيدة، والمزيد.
في حالة حدوث هجوم الخادمة الشريرة أو موظف مارق من بائع تابع لجهة خارجية، لا يزال بإمكانك فتح صندوق البريد الخاص بك فقط باستخدام كلمة المرور التي تم إنشاؤهاكن مطمئنًا، فنحن لا نعتمد على أي بائعين خارجيين غير موفري خوادم SOC Type 2 لدينا وهم Cloudflare وDataPacket وDigital Ocean وVultr.
هدفنا هو أن يكون لدينا أقل عدد نقطة فشل واحدة قدر الإمكان.
صناديق البريد
ملخص؛ تستخدم خوادم IMAP الخاصة بنا قواعد بيانات SQLite مشفرة بشكل فردي لكل صندوق بريد لديك.
SQLite هو برنامج شائع للغاية قاعدة بيانات مضمنة - تعمل حاليًا على هاتفك وجهاز الكمبيوتر الخاص بك - وتستخدمها جميع التقنيات الرئيسية تقريبًا.
على سبيل المثال، يوجد على خوادمنا المشفرة صندوق بريد لقاعدة بيانات SQLite [email protected]
, [email protected]
, [email protected]
وهكذا - واحد لكل واحد كـ .sqlite
ملف قاعدة البيانات. لا نُسمّي ملفات قاعدة البيانات بعنوان البريد الإلكتروني أيضًا، بل نستخدم مُعرّف كائن BSON ومعرفات 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 منفصلاً من عنوان IP مختلف مزود تماما.
بغض النظر عن خادم IMAP الذي يتصل به عميل البريد الإلكتروني الخاص بك، نريد أن يقرأ الاتصال من قاعدة بياناتك في الوقت الفعلي بدقة 100%. يتم ذلك من خلال WebSockets.
يكتب
تختلف عملية الكتابة إلى قاعدة البيانات الخاصة بك بعض الشيء - نظرًا لأن SQLite عبارة عن قاعدة بيانات مضمنة وصندوق البريد الخاص بك موجود في ملف واحد بشكل افتراضي.
لقد استكشفنا خيارات مثل litestream
, rqlite
، و dqlite
أدناه - ولكن لم يلبِّ أي منها متطلباتنا.
لإنجاز عمليات الكتابة باستخدام تسجيل الكتابة المسبقة ("WAL") ممكّنًا - نحتاج إلى التأكد من أن خادمًا واحدًا فقط ("الأساسي") هو المسؤول عن القيام بذلك. WAL يعمل على تسريع التزامن بشكل كبير ويسمح بكاتب واحد وقراء متعددين.
يعمل النظام الأساسي على خوادم البيانات مع وحدات التخزين المُركّبة التي تحتوي على صناديق البريد المُشفّرة. من منظور التوزيع، يُمكنك اعتبار جميع خوادم IMAP المُستقلة خلفه. imap.forwardemail.net
أن تكون خوادم ثانوية ("ثانوية").
نحن ننجز التواصل في الاتجاهين مع مآخذ الويب:
- تستخدم الخوادم الأساسية مثيلًا من ويس'س
WebSocketServer
الخادم. - تستخدم الخوادم الثانوية مثيلًا من ويس'س
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
أمر 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، والتواريخ، والملي ثانية، واللاحقة، والدعم السهل الاستخدام. |
كابينة | مكتبة تسجيل JavaScript وNode.js صديقة للمطورين مع وضع الأمان والخصوصية في الاعتبار. |
فتى | إطار عمل Node.js الذي يدعم بنيتنا الكاملة وتصميمنا الهندسي باستخدام MVC والمزيد. |
مونجو دي بي | حل قاعدة بيانات NoSQL الذي نستخدمه لتخزين جميع البيانات الأخرى خارج صناديق البريد (على سبيل المثال حسابك والإعدادات والمجالات وتكوينات الأسماء المستعارة). |
النمس | نمذجة مستندات كائنات MongoDB ("ODM") التي نستخدمها في جميع حزمنا. كتبنا أدوات مساعدة خاصة تُمكّننا من الاستمرار في استخدام Mongoose مع SQLite 🎉 |
Node.js | Node.js هي بيئة تشغيل JavaScript مفتوحة المصدر ومتعددة الأنظمة الأساسية والتي تقوم بتشغيل جميع عمليات الخادم لدينا. |
نوداميلر | حزمة Node.js لإرسال رسائل البريد الإلكتروني، وإنشاء الاتصالات، والمزيد. نحن الراعي الرسمي لهذا المشروع. |
ريديس | قاعدة بيانات في الذاكرة للتخزين المؤقت وقنوات النشر/الاشتراك وطلبات DNS عبر HTTPS. |
SQLite3 تشفيرات متعددة | امتداد التشفير لـ SQLite للسماح بتشفير ملفات قاعدة البيانات بأكملها (بما في ذلك سجل الكتابة المسبقة ("WAL")، المجلة، التراجع، ...). |
إس كيو لايت ستوديو | محرر Visual SQLite (الذي يمكنك استخدامه أيضًا) لاختبار صناديق البريد الخاصة بالتطوير وتنزيلها وعرضها. |
SQLite | طبقة قاعدة بيانات مضمنة لتخزين IMAP قابل للتطوير ومستقل وسريع ومرن. |
ماسح البريد العشوائي | أداة Node.js لمكافحة البريد العشوائي وتصفية البريد الإلكتروني ومنع التصيد الاحتيالي (بديلنا لـ قاتل البريد العشوائي و rspamd). |
اليوسفي | طلبات DNS عبر HTTPS باستخدام Node.js والتخزين المؤقت باستخدام Redis - مما يضمن الاتساق العالمي وأكثر من ذلك بكثير. |
طائر الرعد | يستخدم فريق التطوير الخاص بنا هذا (ويوصي به أيضًا) كـ عميل البريد الإلكتروني المفضل للاستخدام مع Forward Email. |
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 باستخدام واجهة برمجة تطبيقات ترجمة Google Cloud. |
الاتصال عبر mx | حزمة Node.js لحل وإنشاء اتصالات مع خوادم MX ومعالجة الأخطاء. |
بي ام 2 | مدير عملية إنتاج Node.js مع موازن التحميل المدمج (مُضبوطة بدقة (للأداء). |
خادم smtp | مكتبة خادم SMTP – نستخدمها لتبادل البريد الإلكتروني ("MX") وخوادم SMTP الصادرة. |
ImapTest | أداة مفيدة لاختبار خوادم IMAP وفقًا للمعايير وتوافق بروتوكول IMAP مع مواصفات RFC. تم إنشاء هذا المشروع بواسطة برج الحمام فريق (خادم IMAP وPOP3 مفتوح المصدر نشط منذ يوليو 2002). اختبرنا خادم IMAP الخاص بنا على نطاق واسع باستخدام هذه الأداة. |
يمكنك العثور على مشاريع أخرى نستخدمها في كود المصدر الخاص بنا على GitHub.
مقدمي الخدمات
مزود | غاية |
---|---|
كلاود فلير | مزود DNS، وفحوصات الصحة، وموازنات التحميل، وتخزين النسخ الاحتياطية باستخدام كلاود فلير R2. |
المحيط الرقمي | استضافة خادم مخصص وقواعد بيانات مُدارة. |
فولتر | استضافة خادم مخصص. |
حزمة البيانات | استضافة خادم مخصص. |
أفكار
مبادئ
تم تصميم خدمة إعادة توجيه البريد الإلكتروني وفقًا للمبادئ التالية:
- يجب أن تكون دائمًا صديقة للمطورين، ومركزة على الأمان والخصوصية، وشفافة.
- الالتزام بـ MVC, يونكس, KISS, DRY, YAGNI, اثني عشر عاملًا, شفرة أوكام، و طعام الكلاب
- استهدف الأشخاص الذين يعملون بجد واجتهاد مربحة من الرامن مطور
التجارب
ملخص؛ في نهاية المطاف، فإن استخدام تخزين الكائنات المتوافق مع S3 و/أو الجداول الافتراضية ليس ممكنًا من الناحية الفنية لأسباب تتعلق بالأداء وهو عرضة للخطأ بسبب قيود الذاكرة.
لقد أجرينا بعض التجارب التي أدت إلى حل SQLite النهائي كما ناقشنا أعلاه.
كان أحد هذه الحلول هو محاولة استخدام rclone وSQLite مع طبقة تخزين متوافقة مع S3.
قادتنا هذه التجربة إلى فهم واكتشاف الحالات الحدية المحيطة بـ rclone وSQLite بشكل أكبر. VFS الاستخدام:
- إذا قمت بتمكين
--vfs-cache-mode writes
العلم مع rclone، ثم ستكون عمليات القراءة على ما يرام، ولكن سيتم تخزين عمليات الكتابة مؤقتًا.- إذا كان لديك عدة خوادم IMAP موزعة عالميًا، فسيتم إيقاف تشغيل ذاكرة التخزين المؤقت عبرها ما لم يكن لديك كاتب واحد ومستمعون متعددون (على سبيل المثال، نهج النشر/الاشتراك).
- هذا أمر معقد بشكل لا يصدق، وإضافة أي تعقيد إضافي مثل هذا سيؤدي إلى المزيد من نقاط الفشل الفردية.
- لا يدعم موفرو التخزين المتوافقون مع S3 التغييرات الجزئية للملفات - مما يعني أن أي تغيير في
.sqlite
سيؤدي الملف إلى تغيير كامل وإعادة تحميل قاعدة البيانات. - حلول أخرى مثل
rsync
موجودة، لكنها لا تركز على سجل الكتابة المسبقة ("WAL") الدعم - لذلك انتهينا من مراجعة Litestream. لحسن الحظ، فإن استخدامنا للتشفير يشفر بالفعل WAL ملفاتنا، لذا لسنا بحاجة للاعتماد على Litestream في ذلك. مع ذلك، لم نكن واثقين بعد من استخدام Litestream في الإنتاج، ولدينا بعض الملاحظات أدناه حول ذلك. - باستخدام هذا الخيار
--vfs-cache-mode writes
(ال فقط طريقة استخدام SQLiterclone
(للكتابة) ستحاول نسخ قاعدة البيانات بأكملها من البداية في الذاكرة - التعامل مع صندوق بريد واحد بحجم 10 جيجابايت أمر جيد، ومع ذلك فإن التعامل مع صناديق بريد متعددة ذات سعة تخزين عالية للغاية سيؤدي إلى تعرض خوادم IMAP لقيود الذاكرة وENOMEM
الأخطاء، وأخطاء التجزئة، وفساد البيانات.
- إذا حاولت استخدام SQLite الطاولات الافتراضية (على سبيل المثال باستخدام s3db) لكي تتمكن من حفظ البيانات على طبقة تخزين متوافقة مع S3، فسوف تواجه العديد من المشكلات الأخرى:
- ستكون عمليات القراءة والكتابة بطيئة للغاية حيث سيتعين الوصول إلى نقاط نهاية واجهة برمجة التطبيقات S3 باستخدام HTTP
GET
,PUT
,HEAD
، وPOST
طُرق. - أظهرت اختبارات التطوير أن تجاوز عدد السجلات من 500 ألف إلى مليون سجل على الإنترنت عبر الألياف الضوئية لا يزال محدودًا بمعدل الكتابة والقراءة لموفري الخدمة المتوافقين مع S3. على سبيل المثال، قام مطورونا بتشغيل
for
حلقات للقيام بكل من SQL المتتاليةINSERT
البيانات، وتلك التي كتبت كميات كبيرة من البيانات. في كلتا الحالتين، كان الأداء بطيئًا بشكل مذهل. - طاولات افتراضية لا يمكن أن يكون لها فهارس,
ALTER TABLE
البيانات، و آخر القيود - مما يؤدي إلى تأخيرات تصل إلى 1-2 دقيقة أو أكثر اعتمادًا على كمية البيانات. - تم تخزين الكائنات دون تشفير ولم يتوفر دعم التشفير الأصلي بسهولة.
- ستكون عمليات القراءة والكتابة بطيئة للغاية حيث سيتعين الوصول إلى نقاط نهاية واجهة برمجة التطبيقات S3 باستخدام 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! 🚀