بناء حلول بريد إلكتروني آمنة: إرسال البريد عبر Microsoft Graph للمطورين
By Mirko Peters ·
أهلاً بكم مجدداً في البودكاست! في حلقة اليوم تعمّقنا في التفاصيل المعمارية لأنظمة تسليم البريد الإلكتروني الحديثة. عند بناء تطبيقات على مستوى المؤسسات، أصبحنا بحمد الله بعيدين عن الاعتماد على بروتوكولات SMTP القديمة، بما تحمله من كلمات مرور مضمّنة في الشيفرة ومصافحات غير مشفّرة. واليوم ننظر إلى واجهات برمجة تطبيقات حديثة تعتمد على الهوية، وتحديداً نستكشف كيفية الاستفادة من واجهة Microsoft Graph AP
Automatically translated with AI from the original post. Read the English original
أهلاً بكم مجدداً في البودكاست! في حلقة اليوم تعمّقنا في التفاصيل المعمارية لأنظمة تسليم البريد الإلكتروني الحديثة. عند بناء تطبيقات على مستوى المؤسسات، أصبحنا بحمد الله بعيدين عن الاعتماد على بروتوكولات SMTP القديمة، بما تحمله من كلمات مرور مضمّنة في الشيفرة ومصافحات غير مشفّرة. واليوم ننظر إلى واجهات برمجة تطبيقات حديثة تعتمد على الهوية، وتحديداً نستكشف كيفية الاستفادة من واجهة Microsoft Graph API لإرسال الرسائل بأمان وموثوقية وعلى نطاق واسع.
لمن يفضّل المتابعة بالقراءة، أو تجربة مقاطع الشيفرة، أو الرجوع إلى أنماط التنفيذ أثناء البرمجة، توسّع منشور المدونة المرافق هذا في النقاش الذي دار في البودكاست. سنستعرض رحلة المطور كاملة: إعداد مزود الهوية، والحصول على الرموز المميزة بأمان، وبناء حمولة الرسالة، ومعالجة أعطال الشبكة العابرة، وتأمين البنية استعداداً للنشر في بيئة الإنتاج. هيا بنا نبدأ.
مقدمة إلى واجهة برمجة تطبيقات Microsoft Graph Mail
لعقود، كان إرسال البريد من التطبيق يعني الاتصال بخادم SMTP، وتوفير بيانات اعتماد مصادقة أساسية (غالباً اسم مستخدم وكلمة مرور نصية صريحة مخزّنة في متغير بيئة، أو الأسوأ من ذلك في ملف إعدادات)، ثم الأمل في أفضل النتائج. يحمل هذا النهج مخاطر أمنية كبيرة؛ فإذا تعرّض ملف الإعدادات للاختراق، حصل المهاجم على وصول كامل إلى تلك الصندوق البريدي. وفضلاً عن ذلك، يتجه مزودو السحابة الكبار بشكل متزايد نحو إيقاف المصادقة الأساسية لصالح أطر هوية حديثة تعتمد على الرموز المميزة.
هنا يأتي دور واجهة Microsoft Graph API. فـMicrosoft Graph هو البوابة إلى البيانات والذكاء في Microsoft 365. وهو يوفّر نموذج برمجة موحّداً يمكنك من خلاله الوصول إلى البيانات التي تقوم عليها الإنتاجية في Microsoft 365 وWindows وEnterprise Mobility + Security. وفيما يخص البريد الإلكتروني، تتيح واجهة Microsoft Graph Mail API للتطبيق إرسال الرسائل نيابةً عن المستخدمين أو بصفته تطبيقاً مستقلاً، وذلك كله ضمن قواعد تفويض OAuth 2.0 الصارمة.
لماذا ينبغي للمطورين الانتقال إلى هذا النهج؟ أولاً وقبل كل شيء، الأمان. فباستخدام Azure Active Directory (المعروفة حالياً باسم Microsoft Entra ID) للمصادقة، تتخلص نهائياً من كلمات المرور المخزّنة. بدلاً من ذلك، يصادق تطبيقك باستخدام مفاتيح تشفير أو شهادات أو هويات مُدارة، مقابل الحصول على رموز وصول قصيرة الأجل تمنحه صلاحية تنفيذ مهام محددة. ثانياً، يمنحك Microsoft Graph قياسات تشغيلية (telemetry) غنية، وسجلات تدقيق أفضل، وتكاملاً عميقاً مع منظومة Microsoft الأوسع. سواء كنت ترسل إيصالات فواتير آلية، أو تنبيهات النظام، أو إشعارات موجّهة للمستخدمين، فإن Microsoft Graph يوفّر أساساً متيناً وحديثاً لكل احتياجاتك من رسائل البريد الإلكتروني المعاملاتية.
إعداد تسجيلات التطبيقات في Azure AD / Entra ID والأذونات
قبل كتابة أي سطر من الشيفرة، يجب إنشاء هوية لتطبيقك داخل المستأجر في Azure. تبدأ هذه العملية في مركز إدارة Microsoft Entra بإنشاء تسجيل تطبيق (App Registration).
تسجيل التطبيق خطوة بخطوة
انتقل إلى مركز إدارة Microsoft Entra، واختر "تسجيلات التطبيقات"، ثم انقر على "تسجيل جديد". أعطِ تطبيقك اسماً وصفياً، على سبيل المثال "خدمة الإشعارات المؤسسية"، واختر نوع الحسابات المدعومة المناسب. وفي معظم خدمات الخلفية، ستحتاج إلى خيار "الحسابات في هذا الدليل التنظيمي فقط". بعد الإنشاء، دوّن معرّف التطبيق (client ID) ومعرّف الدليل (tenant ID)؛ فستحتاج إليهما عند ضبط منطق الحصول على الرموز المميزة.
الأذونات المفوّضة مقابل أذونات التطبيق
من أهم القرارات المعمارية التي ستتخذها في هذه المرحلة، الاختيار بين الأذونات المفوّضة (delegated) وأذونات التطبيق (application).
- الأذونات المفوّضة: تُستخدم مع التطبيقات التي يكون فيها مستخدم مسجّل دخول حاضراً. يتصرف التطبيق نيابةً عن المستخدم. وفيما يخص إرسال البريد، يتطلب ذلك عادةً الإذن
Mail.Send. عندما يشغّل المستخدم التطبيق، يجب أن يوافق على أن يرسل التطبيق البريد باستخدام هويته. - أذونات التطبيق: تُستخدم من قِبل الخدمات الخلفية والبرامج الخفية (daemons) والمهام المجدولة التي تعمل دون وجود مستخدم مسجّل الدخول. يتصرف التطبيق بوصفه هويته الخاصة. لإرسال البريد، يتطلب ذلك الإذن
Mail.Sendمن نوع التطبيق. ولأن هذا الإذن يمنح التطبيق القدرة على إرسال البريد باسم أي مستخدم في المؤسسة (حسب الإعدادات)، فإنه يستلزم موافقة المسؤول.
بالنسبة إلى البرامج الخفية الخلفية وخدمات الإشعارات المصغّرة الآلية، ستحتاج حتمًا إلى أذونات التطبيق. بعد أن تمنح الإذن Mail.Send من نوع التطبيق في بوابة Azure، يجب على مسؤول المستأجر النقر صراحةً على زر "Grant admin consent" (منح موافقة المسؤول). ومن دون هذه الموافقة الإدارية، سيتلقى تطبيقك استجابات HTTP 403 Forbidden عند محاولة استدعاء Graph API.
المصادقة و加 الحصول على الرموز المميزة بأمان
بعد إعداد تسجيل تطبيقك ومنح الأذونات، يتمثل تحديك التالي في الحصول بأمان على رموز الوصول OAuth 2.0. لا تُدرج الأسرار أبدًا في الشيفرة بشكل ثابت، وتجنّب استخدام أسرار العميل إذا توفر بديل أكثر أمانًا.
تدفق بيانات الاعتماد للعميل (Client Credentials Flow)
بما أن التطبيقات الخلفية تعمل دون واجهة مستخدم، فإنها تعتمد على تدفق منح بيانات اعتماد العميل في OAuth 2.0. في هذا التدفق، يقدّم تطبيقك معرّف العميل الخاص به وإثبات هويته (إما سر العميل أو، والأفضل، شهادة غير متناظرة) مباشرةً إلى نقطة إصدار الرموز في منصة هوية Microsoft.
رغم شيوع أسرار العميل، فإنها تنتهي صلاحيتها ويجب تدويرها يدويًا، مما يُنشئ عبئًا تشغيليًا ومخاطر تعطل. نوصي بقوة باستخدام المصادقة المستندة إلى الشهادات (CBA) أو، إذا كان تطبيقك يعمل داخل Azure، الهويات المُدارة (Managed Identities). تُلغي الهويات المُدارة تمامًا الحاجة إلى إدارة بيانات الاعتماد في الشيفرة، إذ تتولى Azure دورة حياة الرموز تلقائيًا في الخلفية.
تنفيذ الحصول على الرموز في الشيفرة
الطريقة المعتمدة للحصول على الرموز في منظومة .NET هي استخدام مكتبة المصادقة من Microsoft (MSAL). تتولى MSAL تخزين الرموز مؤقتًا، ومنطق التجديد التلقائي، وتفاصيل البروتوكول جاهزةً دون إعداد إضافي.
إليك نظرة مفاهيمية على كيفية تهيئة تطبيق العميل السري (Confidential Client Application) والحصول على رمز:
// Conceptual initialization using MSAL
var confidentialClientApp = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithTenantId(tenantId)
.Build();
string[] scopes = new[] { "https://graph.microsoft.com/.default" };
var authResult = await confidentialClientApp.AcquireTokenForClient(scopes)
.ExecuteAsync();
string accessToken = authResult.AccessToken;
لاحظ سلسلة النطاق: https://graph.microsoft.com/.default. عند استخدام أذونات التطبيق، يؤدي طلب النطاق .default إلى أن تُصدر منصة الهوية رمزًا يتضمن جميع أذونات التطبيق التي تم تكوينها بشكل ثابت ونالت الموافقة أثناء مرحلة تسجيل التطبيق.
إنشاء حمولة البريد الإلكتروني وإرسالها
بمجرد أن تمتلك رمز وصول JWT صالحًا، تصبح جاهزًا لإنشاء طلب HTTP إلى Microsoft Graph API. تعتمد نقطة النهاية الخاصة بإرسال البريد على ما إذا كنت تستخدم أذونات مفوَّضة أم أذونات تطبيق.
بنية نقطة النهاية
إذا كنت ترسل البريد بوصفك مستخدمًا محددًا عبر أذونات التطبيق، فإن نقطة النهاية تتبع هذه البنية:
POST https://graph.microsoft.com/v1.0/users/{id-or-user-principal-name}/sendMail
يتيح ذلك لخدمتك الخلفية إرسال بريد إلكتروني من حساب خدمة مخصص، مثل notifications@yourcompany.com.
إنشاء حمولة JSON
يتوقع Microsoft Graph حمولة JSON تحدد بدقة خصائص الرسالة، بما في ذلك المستلمون، وسطر الموضوع، ونوع محتوى النص (نص عادي أو HTML)، والمرفقات الاختيارية. إليك مثالًا على حمولة بريد إلكتروني مُنسّقة بشكل صحيح:
{
"message": {
"subject": "System Status Update: Deployment Successful",
"body": {
"contentType": "HTML",
"content": "The scheduled deployment to the production cluster completed successfully at 03:00 UTC."
},
"toRecipients": [
{
"emailAddress": {
"address": "engineering-team@yourcompany.com"
}
}
],
"attachments": []
},
"saveToSentItems": "true"
}
انتبه جيدًا إلى الخاصية saveToSentItems. فضبطها على true يضمن وضع نسخة من الرسالة الصادرة تلقائيًا في مجلد العناصر المرسلة لصندوق البريد المُرسِل، وهو أمر لا يقدَّر بثمن للتدقيق وتصحيح الأخطاء.
تنفيذ معالجة الأعطال والمحاولات المتكررة بشكل مرن
استدعاءات الشبكة إلى واجهات برمجة التطبيقات السحابية عرضة بطبيعتها للأعطال العابرة. ستحدث في بيئة الإنتاج عاجلًا أم آجلًا مشكلات مثل أعطال DNS ومشكلات التوجيه اللحظية وتحديد المعدل (HTTP 429 Too Many Requests) أو تقييد الخادم المؤقت (أخطاء HTTP 5xx). إذا لم يأخذ منطق إرسال البريد لديك هذه الأعطال في الحسبان، فستفقد تطبيقك الرسائل، مما يؤدي إلى تجارب مستخدم معطلة وأصحاب مصلحة محبطين.
بناء نهج إعادة محاولة متين
لتحقيق توفر عالٍ، يجب أن تغلّف استدعاءات Microsoft Graph API بنهج إعادة محاولة مرن. تجعل مكتبات مثل Polly في منظومة .NET، أو أطر المرونة المكافئة في Node.js وPython وJava، هذا الأمر بسيطًا.
عند تصميم استراتيجية إعادة المحاولة، التزم بهذه المبادئ الأساسية:
- التراجع الأسي (Exponential Backoff): لا تُكرّر إرسال الطلبات إلى الواجهة فورًا بعد حدوث فشل. انتظر ثانيتين، ثم أربع ثوانٍ، ثم ثماني ثوانٍ، مع زيادة مدة التأخير في كل محاولة لاحقة، لإتاحة الفرصة للخدمة اللاحقة لاستعادة عملها.
- التشويش العشوائي (Jitter): أضِف فترات زمنية عشوائية إلى توقيت التراجع الأسي. فإذا فشلت مئة خدمة مصغّرة في الوقت نفسه وأعادت المحاولة في آنٍ واحد وبفواصل زمنية ثابتة، فستتسبب في هجوم حجب الخدمة الموزّع (DDoS) على واجهة Graph API بنفسها. يعمل التشويش العشوائي على توزيع حركة إعادة المحاولات عبر الزمن.
- احترام ترويسات Retry-After: عندما يُقيّد Microsoft Graph معدل الطلبات الصادرة من تطبيقك، فإنه يُعيد رمز الحالة HTTP 429 مصحوبًا بترويسة
Retry-Afterتحدد عدد الثواني التي يجب على تطبيقك انتظارها قبل إرسال طلب آخر. ويجب أن يتحقق عميل HTTP لديك من هذه الترويسة وأن يلتزم بها.
بالجمع بين التراجع الأسي وإدارة التقييد الذكية، تضمن أن تبقى خدمة إرسال البريد الإلكتروني لديك مستقرة وقادرة على الصمود حتى خلال أوقات الذروة في حركة المرور.
أفضل الممارسات لبيئات الإنتاج
قبل أن نختتم هذه التدوينة، دعونا نراجع قائمة مرجعية لأفضل الممارسات تساعدك على إبقاء تكامل البريد الإلكتروني لديك آمنًا وعالي الأداء وسهل الصيانة على المدى الطويل.
1. المعالجة غير المتزامنة عبر قوائم انتظار الرسائل
لا ترسل رسائل البريد الإلكتروني بشكل متزامن أبدًا داخل طلب ويب وارد أو استدعاء واجهة برمجية. فإذا أدى طلب HTTP إلى استدعاء فوري لـ Microsoft Graph، فسيضطر المستخدم إلى انتظار اكتمال رحلة الشبكة ذهابًا وإيابًا، وإذا تعرضت Graph لانقطاع مؤقت، فسيفشل طلب الويب. بدلًا من ذلك، ادفع حمولات البريد الإلكتروني إلى قائمة انتظار رسائل (مثل Azure Service Bus أو RabbitMQ أو AWS SQS)، ودع عاملًا خلفيًا مخصصًا يسحب الرسائل من القائمة وينفذ استدعاء Graph API بشكل غير متزامن.
2. المراقبة والتنبيه
زوّد خط إرسال البريد الإلكتروني لديك بتسجيل قوي للأحداث ومقاييس دقيقة. تتبّع مقاييس مثل إجمالي الرسائل المُرسلة، ومعدلات الفشل، ومتوسط عدد إعادات المحاولة، وزمن الحصول على الرموز المميزة. اضبط التنبيهات لارتفاعات الأخطاء غير الطبيعية؛ فعلى سبيل المثال، إذا تجاوزت نسبة أخطاء HTTP 403 أو 429 حدًا محددًا، فينبغي إخطار فريق العمليات لديك فورًا.
3. مبدأ أقل الامتيازات
راجع تسجيلات تطبيقات Azure AD بانتظام. هل يحتاج تطبيقك حقًا إلى أذونات واسعة على مستوى المؤسسة، أم يمكنك تقييد الوصول إلى صناديق بريد محددة؟ راجع منح الموافقة دوريًا للتأكد من تنظيف التطبيقات المهملة وسحب الوصول منها.
الخاتمة
إن الانتقال بعيدًا عن SMTP القديم واعتماد واجهة Microsoft Graph API خطوة هائلة نحو تحديث بنية تطبيقك. فمن خلال الجمع بين إعدادات تسجيل التطبيق المتينة، وتدفقات الحصول على الرموز المميزة الآمنة، والحمولات المنظمة، ومنطق إعادة المحاولة المرن، والمعالجة غير المتزامنة عبر قوائم الانتظار، تبني محرك بريد إلكتروني بمستوى المؤسسات يمكنك الوثوق به.
شكرًا لمتابعتكم البودكاست والقراءة معنا في هذه التدوينة. إذا وجدتم هذا الدليل مفيدًا، فلا تنسوا الاشتراك في البودكاست، ومشاركة هذا المقال مع زملائكم المهندسين، وترك تعليق يتضمن المواضيع التي ترغبون في أن نتناولها في الحلقات القادمة. برمجة سعيدة!