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

مقدمة
خدمة البريد الإلكتروني لدينا > [!IMPORTANT]
خدمة البريد الإلكتروني لدينا مفتوح المصدر بنسبة 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 المشفرة لدينا، أو كليهما!
Tip
هل ترغب بمعرفة المزيد؟ اقرأ كيفية إعداد إعادة توجيه البريد الإلكتروني، كيف تعمل خدمة تبادل البريد لدينا، أو اطلع على مرشدينا.
- خلف الكواليس، يعمل تصميم تخزين البريد الإلكتروني الآمن لدينا بطريقتين للحفاظ على صناديق البريد الخاصة بك مشفرة ولا يمكن الوصول إليها إلا من قبلك:
-
عند استلام بريد جديد لك من مرسل، تقوم خوادم تبادل البريد لدينا بالكتابة إلى صندوق بريد فردي مؤقت ومشفر لك.
-
عند اتصالك بخادم IMAP الخاص بنا باستخدام برنامج البريد الإلكتروني، تُشفَّر كلمة مرورك في الذاكرة وتُستخدم لقراءة رسائلك وكتابتها في صندوق بريدك. لا يُمكن قراءة رسائلك وكتابتها إلا باستخدام كلمة المرور هذه. تذكر أنه بما أنك الوحيد الذي يملك كلمة المرور هذه، أنت فقط من يمكنه قراءة رسائلك وكتابتها في صندوق بريدك عند الوصول إليه. في المرة القادمة التي يحاول فيها برنامج البريد الإلكتروني البحث عن رسائل أو مزامنتها، سيتم نقل رسائلك الجديدة من صندوق البريد المؤقت هذا وتخزينها في ملف صندوق بريدك الفعلي باستخدام كلمة المرور التي أدخلتها. يُرجى العلم أنه سيتم مسح صندوق البريد المؤقت هذا وحذفه لاحقًا، بحيث لا يحتوي على الرسائل إلا صندوق بريدك المحمي بكلمة مرور.
-
إذا كنت متصلاً ببروتوكول IMAP (مثلاً باستخدام برنامج بريد إلكتروني مثل Apple Mail أو Thunderbird)، فلن نحتاج إلى الكتابة إلى وحدة تخزين مؤقتة على القرص. بدلاً من ذلك، سيتم جلب كلمة مرور IMAP المشفرة المحفوظة في الذاكرة واستخدامها. في الوقت الفعلي، عند محاولة تسليم رسالة إليك، نرسل طلب WebSocket إلى جميع خوادم IMAP نسألهم عما إذا كانت لديهم جلسة نشطة لك (هذه هي مرحلة الجلب)، ثم نمرر كلمة المرور المشفرة المحفوظة في الذاكرة - لذا لا نحتاج إلى الكتابة إلى صندوق بريد مؤقت، بل يمكننا الكتابة إلى صندوق بريدك المشفر الفعلي باستخدام كلمة مرورك المشفرة.
٥. يتم إنشاء نسخ احتياطية لصناديق البريد المشفرة الخاصة بك يوميًا. يمكنك أيضًا طلب نسخة احتياطية جديدة في أي وقت أو تنزيل أحدث نسخة احتياطية من حسابي النطاقات الأسماء المستعارة. إذا قررت الانتقال إلى خدمة بريد إلكتروني أخرى، يمكنك بسهولة نقل وتنزيل وتصدير وحذف صناديق بريدك والنسخ الاحتياطية في أي وقت.
التقنيات
قواعد بيانات
لقد استكشفنا طبقات تخزين قاعدة البيانات الأخرى المحتملة، ولكن لم تلبي أي منها متطلباتنا بقدر ما فعلت SQLite:
قاعدة البيانات | التشفير في حالة السكون | صناديق البريد | رخصة | Used Everywhere |
---|---|---|---|---|
رابط الخلية_0 ⭐ | ✅ نعم مع SQLite3MultipleCiphers | :علامة_التحقق_البيضاء: | ✅ المجال العام | :علامة_التحقق_البيضاء: |
MongoDB | ❌ رابط الخلية_0 | ❌ قاعدة بيانات علائقية | ❌ AGPL و SSPL-1.0 |
❌ |
rqlite | ❌ رابط الخلية_0 | ❌ قاعدة بيانات علائقية | :علامة_التحقق_البيضاء: رمز_الخلية_0 | ❌ |
dqlite | ❌ رابط الخلية_0 | ❌ رابط الخلية_0 | :علامة_التحقق_البيضاء: رمز_الخلية_0 | ❌ |
PostgreSQL | :علامة_التحقق_البيضاء: رابط_الخلية_0 | ❌ قاعدة بيانات علائقية | ✅ PostgreSQL (مشابه لـ BSD أو MIT ) |
❌ |
MariaDB | :علامة_التحقق_البيضاء: رابط_الخلية_0 | ❌ قاعدة بيانات علائقية | ✅ GPLv2 و BUSL-1.1 |
❌ |
CockroachDB | ❌ رابط الخلية_0 | ❌ قاعدة بيانات علائقية | ❌ BUSL-1.1 وآخرون |
❌ |
فيما يلي تدوينة تقارن بين عدة خيارات لتخزين قاعدة بيانات SQLite في الجدول أعلاه.
الأمان
نستخدم دائمًا تشفير التشفير في حالة السكون (AES-256)، والتشفير أثناء النقل (TLS)، وDNS عبر HTTPS ("DoH") باستخدام 🍊 اليوسفي، وسكليت (تشاتشا20-بولي1305) على صناديق البريد. بالإضافة إلى ذلك، نستخدم مصادقة ثنائية العوامل قائمة على الرمز (على عكس الرسائل النصية القصيرة التي يُشتبه في أنها هجمات الرجل في المنتصف)، ومفاتيح SSH مُدارة مع تعطيل الوصول إلى الجذر، ووصول حصري إلى الخوادم عبر عناوين IP مقيدة، وغيرها.
في حال وجود حامل بريد مؤقت (هجوم الخادمة الشريرة) أو موظف غير موثوق من جهة خارجية، لا يزال بإمكانك فتح صندوق بريدك الإلكتروني إلا باستخدام كلمة المرور المُولّدة. كن مطمئنًا، لا نعتمد على أي جهات خارجية أخرى سوى مزودي خوادمنا الحاصلين على شهادة SOC من النوع 2، وهم Cloudflare وDataPacket وDigital Ocean وVultr.
هدفنا هو الحصول على أقل عدد ممكن من نقطة فشل واحدة.
صناديق البريد
tldr; تستخدم خوادم IMAP الخاصة بنا قواعد بيانات SQLite مشفرة بشكل فردي لكل صندوق بريد لديك.
قاعدة البيانات المضمنة SQLite هو برنامج شائع للغاية - يتم تشغيلها حاليًا على هاتفك والكمبيوتر - وتستخدمها جميع التقنيات الرئيسية تقريبًا.
على سبيل المثال، يوجد على خوادمنا المشفرة صندوق بريد قاعدة بيانات SQLite لـ linux@example.com
، وinfo@example.com
، وhello@example.com
، وهكذا - لكل منها ملف قاعدة بيانات .sqlite
. لا نسمي ملفات قاعدة البيانات بعنوان البريد الإلكتروني، بل نستخدم معرف كائن BSON ومعرفات UUID فريدة مُولّدة، والتي لا تُشارك اسم صاحب صندوق البريد أو عنوان البريد الإلكتروني الذي يتبعه (مثل 353a03f21e534321f5d6e267.sqlite
).
كل قاعدة بيانات من هذه القواعد مُشفّرة ذاتيًا باستخدام كلمة مرورك (التي تملكها وحدك) باستخدام سكليت (تشاتشا20-بولي1305). هذا يعني أن صناديق بريدك مُشفّرة بشكل فردي، ومستقلّة، وقابلة للنقل.
لقد قمنا بضبط SQLite باستخدام PRAGMA التالي:
PRAGMA |
غاية |
---|---|
cipher=chacha20 |
ChaCha20-Poly1305 SQLite database encryption. راجع better-sqlite3-multiple-ciphers ضمن Projects لمزيد من المعلومات. |
key="****************" |
هذه كلمة مرورك المُفككة والمُخزّنة في الذاكرة فقط، والتي تُمرّر عبر اتصال IMAP لعميل البريد الإلكتروني الخاص بك إلى خادمنا. يتم إنشاء نسخ جديدة من قاعدة البيانات وإغلاقها لكل جلسة قراءة وكتابة (لضمان الحماية والعزل). |
journal_model=WAL |
سجل الكتابة المسبقة ("WAL") which boosts performance and allows concurrent read access. |
busy_timeout=5000 |
يمنع أخطاء قفل الكتابة while other writes are taking place. |
synchronous=NORMAL |
يزيد من متانة المعاملات without data corruption risk. |
foreign_keys=ON |
ينفذ فرض مراجع المفاتيح الخارجية (على سبيل المثال علاقة من جدول إلى آخر). By default this is not turned on in SQLite، ولكن للتحقق من صحة البيانات وسلامتها يجب تمكينه. |
encoding='UTF-8' |
Default encoding لاستخدامه لضمان سلامة المطور. |
جميع الإعدادات الافتراضية الأخرى هي من SQLite كما هو محدد من وثائق PRAGMA الرسمية.
التزامن
tldr; نستخدم
WebSocket
للقراءة والكتابة المتزامنة إلى صناديق بريد SQLite المشفرة الخاصة بك.
يقرأ
قد يقوم عميل البريد الإلكتروني على هاتفك بحل imap.forwardemail.net
إلى أحد عناوين IP الخاصة بـ Digital Ocean - وقد يقوم عميل سطح المكتب الخاص بك بحل عنوان IP منفصل من مزود مختلف تمامًا.
بغض النظر عن خادم IMAP الذي يتصل به عميل البريد الإلكتروني الخاص بك، نريد أن يقرأ الاتصال من قاعدة بياناتك في الوقت الفعلي بدقة 100%. يتم ذلك من خلال WebSockets.
يكتب
تختلف عملية الكتابة إلى قاعدة البيانات الخاصة بك بعض الشيء - نظرًا لأن SQLite عبارة عن قاعدة بيانات مضمنة وصندوق البريد الخاص بك موجود في ملف واحد بشكل افتراضي.
لقد استكشفنا خيارات مثل litestream
، وrqlite
، وdqlite
أدناه - ولكن لم يلبِّ أي منها متطلباتنا.
لإتمام عمليات الكتابة مع تفعيل خاصية التسجيل المسبق ("WAL")، يجب التأكد من أن خادمًا واحدًا فقط ("Primary") مسؤول عن ذلك. يُسرّع 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)
.
٤. شغّل أمر SQLite VACUUM INTO
.
٥. تأكد من إمكانية فتح الملف المنسوخ باستخدام كلمة المرور المشفرة (الحماية/الحماية الوهمية).
٦. حمّله إلى Cloudflare R2 للتخزين (أو إلى مزوّد خدمة التخزين الخاص بك إذا تم تحديده).
تذكر أن صناديق البريد الخاصة بك مشفرة - وعلى الرغم من وجود قيود IP وتدابير مصادقة أخرى مطبقة لاتصالات WebSocket - في حالة وجود جهة سيئة، يمكنك التأكد من أنه ما لم يكن حمولة WebSocket تحتوي على كلمة مرور IMAP الخاصة بك، فلن تتمكن من فتح قاعدة البيانات الخاصة بك.
يتم تخزين نسخة احتياطية واحدة فقط لكل صندوق بريد في الوقت الحالي، ولكن في المستقبل قد نقدم استردادًا في نقطة زمنية معينة ("PITR").
بحث
تدعم خوادم IMAP الخاصة بنا الأمر SEARCH
مع الاستعلامات المعقدة وتعبيرات عادية والمزيد.
يتم تحقيق أداء بحث سريع بفضل FTS5 وsqlite-regex.
نقوم بتخزين قيم Date
في صناديق بريد SQLite كسلاسل ISO 8601 عبر Date.prototype.toISOString (مع المنطقة الزمنية UTC لمقارنات المساواة لتعمل بشكل صحيح).
يتم أيضًا تخزين الفهارس لجميع الخصائص الموجودة في استعلامات البحث.
مشاريع
فيما يلي جدول يوضح المشاريع التي نستخدمها في الكود المصدر وعملية التطوير (مرتبة أبجديًا):
مشروع | غاية |
---|---|
Ansible | منصة أتمتة DevOps لصيانة وتوسيع وإدارة أسطولنا بالكامل من الخوادم بكل سهولة. |
Bree | مجدول الوظائف لـ Node.js وJavaScript مع cron، والتواريخ، والملي ثانية، واللاحقة، والدعم السهل الاستخدام. |
Cabin | مكتبة تسجيل JavaScript وNode.js صديقة للمطورين مع وضع الأمان والخصوصية في الاعتبار. |
Lad | إطار عمل Node.js الذي يدعم بنيتنا الكاملة وتصميمنا الهندسي باستخدام MVC والمزيد. |
MongoDB | حل قاعدة بيانات NoSQL الذي نستخدمه لتخزين جميع البيانات الأخرى خارج صناديق البريد (على سبيل المثال حسابك والإعدادات والمجالات وتكوينات الأسماء المستعارة). |
Mongoose | نمذجة مستندات كائنات MongoDB ("ODM") التي نستخدمها في جميع حزمنا. كتبنا أدوات مساعدة خاصة تُمكّننا من مواصلة استخدام Mongoose مع SQLite بسهولة. |
Node.js | Node.js هي بيئة تشغيل JavaScript مفتوحة المصدر ومتعددة الأنظمة الأساسية والتي تقوم بتشغيل جميع عمليات الخادم لدينا. |
Nodemailer | حزمة Node.js لإرسال رسائل البريد الإلكتروني، وإنشاء الاتصالات، والمزيد. نحن الراعي الرسمي لهذا المشروع. |
Redis | قاعدة بيانات في الذاكرة للتخزين المؤقت وقنوات النشر/الاشتراك وطلبات DNS عبر HTTPS. |
SQLite3MultipleCiphers | امتداد التشفير لـ SQLite للسماح بتشفير ملفات قاعدة البيانات بأكملها (بما في ذلك سجل الكتابة المسبقة ("WAL")، والمجلة، والتراجع، ...). |
SQLiteStudio | محرر Visual SQLite (الذي يمكنك استخدامه أيضًا) لاختبار صناديق البريد الخاصة بالتطوير وتنزيلها وعرضها. |
SQLite | طبقة قاعدة بيانات مضمنة لتخزين IMAP قابل للتطوير ومستقل وسريع ومرن. |
Spam Scanner | أداة Node.js لمكافحة البريد العشوائي وتصفية البريد الإلكتروني ومنع التصيد الاحتيالي (بديلنا لـ Spam Assassin و rspamd). |
Tangerine | طلبات DNS عبر HTTPS باستخدام Node.js والتخزين المؤقت باستخدام Redis - مما يضمن الاتساق العالمي وأكثر من ذلك بكثير. |
Thunderbird | يستخدم فريق التطوير الخاص بنا هذا (ويوصي به أيضًا) باعتباره عميل البريد الإلكتروني المفضل للاستخدام مع إعادة توجيه البريد الإلكتروني. |
UTM | يستخدم فريق التطوير الخاص بنا هذه الآلات الافتراضية لإنشاء أنظمة التشغيل iOS وmacOS لاختبار عملاء البريد الإلكتروني المختلفين (بالتوازي) مع خوادم IMAP وSMTP الخاصة بنا. |
Ubuntu | نظام تشغيل خادم حديث مفتوح المصدر يعتمد على Linux والذي يدعم كافة البنية التحتية لدينا. |
WildDuck | مكتبة خادم IMAP - راجع ملاحظاتها على attachment de-duplication و IMAP protocol support. |
better-sqlite3-multiple-ciphers | مكتبة API سريعة وبسيطة لـ Node.js للتفاعل مع SQLite3 برمجيًا. |
email-templates | إطار عمل بريد إلكتروني صديق للمطورين لإنشاء رسائل بريد إلكتروني مخصصة ومعاينتها وإرسالها (على سبيل المثال إشعارات الحساب والمزيد). |
json-sql-enhanced | منشئ استعلامات SQL باستخدام صيغة Mongo. هذا يوفر وقت فريق التطوير لدينا، إذ يمكننا الاستمرار في الكتابة بصيغة Mongo عبر كامل الحزمة، مع نهج مستقل عن قواعد البيانات. كما أنه يساعد على تجنب هجمات حقن SQL باستخدام معلمات الاستعلام. |
knex-schema-inspector | أداة SQL لاستخراج معلومات حول مخطط قاعدة البيانات الحالي. هذا يُمكّننا من التحقق بسهولة من صحة جميع الفهارس والجداول والأعمدة والقيود وغيرها، وأنها 1:1 كما ينبغي. حتى أننا طوّرنا أدوات مساعدة آلية لإضافة أعمدة وفهرس جديدة في حال إجراء تغييرات على مخططات قاعدة البيانات (مع تنبيهات أخطاء مفصلة للغاية). |
knex | منشئ استعلامات SQL الذي نستخدمه فقط لترحيل قواعد البيانات والتحقق من صحة المخطط من خلال knex-schema-inspector . |
mandarin | ترجمة العبارة التلقائية i18n مع دعم Markdown باستخدام Google Cloud Translation API. |
mx-connect | حزمة Node.js لحل وإنشاء اتصالات مع خوادم MX ومعالجة الأخطاء. |
pm2 | مدير عملية إنتاج Node.js مع موازن التحميل المدمج (fine-tuned للأداء). |
smtp-server | مكتبة خادم SMTP – نستخدمها لتبادل البريد الإلكتروني ("MX") وخوادم SMTP الصادرة. |
ImapTest | أداة مفيدة لاختبار خوادم IMAP وفقًا لمعايير وتوافق بروتوكول IMAP مع مواصفات RFC. أنشأ هذا المشروع فريق [Dovecot](https://en.wikipedia.org/wiki/Dovecot_\(software\) (خادم IMAP وPOP3 مفتوح المصدر نشط منذ يوليو 2002). اختبرنا خادم IMAP الخاص بنا على نطاق واسع باستخدام هذه الأداة. |
يمكنك العثور على المشاريع الأخرى التي نستخدمها في كود المصدر الخاص بنا على GitHub.
مقدمو الخدمة
مزود | غاية |
---|---|
Cloudflare | مزود DNS، وفحوصات الصحة، وموازنات التحميل، وتخزين النسخ الاحتياطية باستخدام Cloudflare R2. |
Digital Ocean | استضافة خادم مخصص وقواعد بيانات مُدارة. |
Vultr | استضافة خادم مخصص. |
DataPacket | استضافة خادم مخصص. |
أفكار
مبادئ
تم تصميم خدمة إعادة توجيه البريد الإلكتروني وفقًا للمبادئ التالية:
١. كن دائمًا صديقًا للمطورين، مع التركيز على الأمان والخصوصية، وشفافًا.
٢. التزم بـ 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
(الطريقة الوحيدة لاستخدام SQLite بدلاً منrclone
للكتابة) إلى محاولة نسخ قاعدة البيانات بأكملها من البداية إلى الذاكرة - التعامل مع صندوق بريد واحد بسعة 10 جيجابايت أمرٌ مقبول، ولكن التعامل مع صناديق بريد متعددة ذات سعة تخزين عالية جدًا سيؤدي إلى مواجهة خوادم IMAP قيودًا في الذاكرة وأخطاءENOMEM
، وأخطاء في التجزئة، وتلف البيانات. -
إذا حاولت استخدام SQLite الطاولات الافتراضية (مثل استخدام s3db) لحفظ البيانات على طبقة تخزين متوافقة مع S3، فستواجه العديد من المشاكل الأخرى:
-
ستكون عمليات القراءة والكتابة بطيئة للغاية، حيث ستحتاج نقاط نهاية واجهة برمجة تطبيقات S3 إلى الوصول إلى HTTP
.sqlite
0 و.sqlite
1 و.sqlite
2 و.sqlite
3. -
أظهرت اختبارات التطوير أن تجاوز عدد السجلات من 500 ألف إلى مليون سجل على شبكة الإنترنت عبر الألياف الضوئية لا يزال محدودًا بمعدل نقل البيانات والكتابة إلى موفري خدمات متوافقين مع S3. على سبيل المثال، شغّل مطورونا حلقات
.sqlite
4 لتنفيذ عبارات SQL.sqlite
5 المتسلسلة، وتلك التي تكتب كميات كبيرة من البيانات بشكل جماعي. في كلتا الحالتين، كان الأداء بطيئًا بشكل مذهل. * الجداول الافتراضية لا يمكن أن تحتوي على فهارس، وعبارات.sqlite
6، و.sqlite
7 و.sqlite
8 - مما يؤدي إلى تأخيرات تصل إلى دقيقة أو دقيقتين أو أكثر حسب كمية البيانات. -
تم تخزين الكائنات بدون تشفير، ولا يتوفر دعم تشفير أصلي بسهولة.
-
استكشفنا أيضًا استخدام
.sqlite
9، وهو مشابه مفاهيميًا وتقنيًا للنقطة السابقة (لذا فهو يعاني من نفس المشاكل). أحد الاحتمالات هو استخدام بنيةrsync
0 مخصصة مشفّرة مثلrsync
1 (الذي نستخدمه حاليًا في حلنا أعلاه) من خلالrsync
2. -
نهج آخر محتمل هو استخدام
rsync
3، ولكن هذا له حد أقصى قدره 32 جيجابايت، وسيتطلب تعقيدات في البناء والتطوير. -
عبارات
rsync
4 مطلوبة (لذا، هذا يستبعد تمامًا استخدام الجداول الافتراضية). نحتاج إلى عباراتrsync
5 لكي يعمل ربطنا معrsync
6 بشكل صحيح، مما يضمن عدم تلف البيانات وإمكانية تحويل الصفوف المسترجعة إلى مستندات صالحة وفقًا لتعريفات مخططrsync
7 (التي تتضمن القيد، ونوع المتغير، والتحقق من صحة البيانات بشكل عشوائي). -
جميع المشاريع المتوافقة مع S3 تقريبًا والمتعلقة بـ SQLite في مجتمع المصادر المفتوحة تعمل بلغة بايثون (وليس جافا سكريبت التي نستخدمها بنسبة 100% في مجموعتنا).
-
تبدو مكتبات الضغط مثل
rsync
8 (انظرrsync
9) واعدة، ولكن __PROTECTED_LINK_189__0. بدلاً من ذلك، يُعدّ الضغط من جانب التطبيق على أنواع البيانات مثل __PROTECTED_LINK_189__1 و__PROTECTED_LINK_189__2 و__PROTECTED_LINK_189__3 و__PROTECTED_LINK_189__4 و__PROTECTED_LINK_189__5 و__PROTECTED_LINK_189__6 نهجًا أنظف وأسهل (وأسهل في النقل أيضًا، حيث يُمكننا تخزين علامة أو عمود __PROTECTED_LINK_189__7 - أو حتى استخدام __PROTECTED_LINK_189__8 و__PROTECTED_LINK_189__9 للضغط أو __PROTECTED_LINK_190__0 لعدم الضغط كبيانات تعريفية لقاعدة البيانات). -
لحسن الحظ، لدينا بالفعل خاصية إزالة تكرار المرفقات في وحدة تخزين خادم IMAP لدينا - وبالتالي، لن تحتفظ كل رسالة تحتوي على نفس المرفق بنسخة منه - بل يُخزّن مرفق واحد لرسائل وسلاسل رسائل متعددة في صندوق بريد (ويُستخدم مرجع خارجي لاحقًا).
-
مشروع Litestream، وهو حل نسخ احتياطي ونسخ احتياطي لـ SQLite، واعد جدًا، ومن المرجح أن نستخدمه في المستقبل.
-
لا نريد التقليل من شأن المؤلفين - فنحن نعشق عملهم ومساهماتهم في مجال المصادر المفتوحة منذ أكثر من عقد - ولكن من خلال الاستخدام العملي، يبدو أن هناك __PROTECTED_LINK_190__1 و__PROTECTED_LINK_190__2.
-
يجب أن تكون استعادة النسخة الاحتياطية سلسة وسهلة. استخدام حل مثل MongoDB مع __PROTECTED_LINK_190__3 و__PROTECTED_LINK_190__4 ليس مملًا فحسب، بل يتطلب وقتًا طويلًا وتعقيدًا في التكوين.
-
قواعد بيانات SQLite تجعل الأمر بسيطًا (إنه ملف واحد).
-
أردنا تصميم حل يسمح للمستخدمين بأخذ صندوق بريدهم ومغادرته في أي وقت.
-
أوامر Node.js بسيطة إلى __PROTECTED_LINK_190__5، ويتم مسحه نهائيًا من وحدة تخزين القرص.
-
يمكننا أيضًا استخدام واجهة برمجة تطبيقات متوافقة مع S3 مع HTTP __PROTECTED_LINK_190__6 لإزالة اللقطات والنسخ الاحتياطية بسهولة للمستخدمين.
-
كان SQLite الحل الأبسط والأسرع والأقل تكلفة.
عدم وجود بدائل
على حد علمنا، لا توجد خدمات بريد إلكتروني أخرى مصممة بهذه الطريقة ولا تعد مفتوحة المصدر.
نعتقد أن هذا قد يكون بسبب خدمات البريد الإلكتروني الحالية التي تحتوي على تقنية قديمة في الإنتاج مع كود السباغيتي 🍝.
معظم، إن لم يكن كل، موفري خدمات البريد الإلكتروني الحاليين إما مغلقي المصدر أو يعلنون عن كونهم مفتوحي المصدر، ولكن في الواقع فإن واجهتهم الأمامية فقط هي مفتوحة المصدر.
الجزء الأكثر حساسية في البريد الإلكتروني (التفاعل الفعلي بين التخزين/IMAP/SMTP) يتم إجراؤه بالكامل على الواجهة الخلفية (الخادم)، وليس على الواجهة الأمامية (العميل).
جرب إعادة توجيه البريد الإلكتروني
سجل اليوم في https://forwardemail.net! 🚀