بناء نظام أرشفة البريد الإلكتروني: التحديات وبالطبع الحل – الجزء 1
جيف غولدستين
04/02/2019
البريد الإلكتروني
1 min read

مع زيادة استخدام البريد الإلكتروني في البيئات التنظيمية، قررت أنه حان الوقت لبدء مشروع جديد يجمع كل هذا معًا مع أمثلة برمجية حول كيفية تخزين محتوى البريد الإلكتروني وجميع البيانات المرتبطة به.
قبل حوالي عام كتبت مدونة حول كيفية استرجاع نسخ من الرسائل الإلكترونية للأرشفة والعرض ولكن لم أتطرق إلى تخزين الرسائل الإلكترونية والبيانات ذات الصلة فعليًا، ومؤخرًا كتبت مدونة حول تخزين جميع بيانات الأحداث (مثل متى تم إرسال الرسالة الإلكترونية، فتحها، النقرات، الارتدادات، إلغاء الاشتراك، وما إلى ذلك) في بريد إلكتروني لغرض التدقيق، ولكن اخترت عدم إنشاء أي شفرة داعمة.
مع زيادة استخدام البريد الإلكتروني في البيئات التنظيمية، قررت أنه قد حان الوقت لبدء مشروع جديد يدمج كل هذا مع أمثلة على الشفرة حول كيفية تخزين محتوى الرسائل الإلكترونية وجميع البيانات المرتبطة بها. خلال العام المقبل، سأواصل البناء على هذا المشروع بهدف إنشاء تطبيق لتخزين العرض للرسائل الإلكترونية المؤرشفة وجميع معلومات السجل المنتجة بواسطة SparkPost. لا تمتلك SparkPost نظامًا للأرشفة لمحتوى الرسائل الإلكترونية ولكنه يسهل بناء منصة أرشفة إلى حد ما.
في سلسلة المدونات هذه، سأشرح العملية التي مررت بها من أجل تخزين محتوى الرسائل الإلكترونية على S3 (خدمة التخزين البسيط من أمازون) وجميع بيانات السجل ذات الصلة في MySQL لسهولة الرجوع المتقاطع. بالنسبة لأنظمة الأرشفة الإنتاجية التي تتطلب استراتيجيات نسخ احتياطي لقواعد البيانات قوية، فكر في تنفيذ عملية نسخ احتياطي واستعادة لـ PostgreSQL شاملة لضمان حماية بيانات الأرشفة بشكل صحيح. في النهاية، هذا هو نقطة البداية لبناء تطبيق سيمكن من البحث السهل عن الرسائل الإلكترونية المؤرشفة، ثم عرض تلك الرسائل جنبًا إلى جنب مع بيانات الأحداث (السجل). يمكن العثور على الشفرة لهذا المشروع في مستودع GitHub التالي: PHPArchivePlatform على GitHub
سوف تصف هذه المدونة الأولى من سلسلة المدونات التحدي وتضع الهندسة للحل. ستقوم باقي المدونات بتفاصيل أجزاء الحل مع أمثلة الشفرة.
كانت الخطوة الأولى في عمليتي هي كيفية الحصول على نسخة من الرسالة الإلكترونية المرسلة إلى المستلم الأصلي. للحصول على نسخة من محتوى الرسالة الإلكترونية، تحتاج إما إلى:
التقاط محتوى الرسالة الإلكترونية قبل إرسالها
جعل خادم البريد الإلكتروني يخزن نسخة
جعل خادم البريد الإلكتروني ينشئ نسخة لتخزينها
إذا كان خادم البريد الإلكتروني يضيف عناصر مثل تتبع الروابط أو تتبع الفتح، لا يمكنك استخدام الخيار الأول لأنه لن يعكس تغييرات التتبع.
هذا يعني أن الخادم يجب أن يخزن الرسالة الإلكترونية أو يقدم نسخة لك لتخزينها بشكل ما. نظرًا لعدم امتلاك SparkPost لآلية تخزين لمحتويات الرسائل الإلكترونية ولكن لديها طريقة لإنشاء نسخة للرسالة، سنقوم بجعل SparkPost ترسل لنا نسخة من الرسالة لتخزينها في S3.
يتم ذلك باستخدام خاصية الأرشفة من SparkPost. تمنح خاصية الأرشفة في SparkPost المرسل القدرة على إخبار SparkPost بإرسال نسخة من الرسالة إلى عنوان أو أكثر من العناوين الإلكترونية واستخدام نفس الروابط التتبعية والتفتح كما في الأصل. توضح وثائق SparkPost خاصية الأرشفة بالطريقة التالية:
المستلمون في قائمة الأرشفة سيحصلون على نسخة طبق الأصل من الرسالة المرسلة إلى عنوان RCPT TO. وبشكل خاص، الروابط المشفرة المخصصة للمستلم RCPT TO ستكون مماثلة في رسائل الأرشفة
الاختلافات الوحيدة من الرسالة RCPT TO هي أن بعض الرؤوس ستكون مختلفة لأن العنوان الهدف للرسالة المؤرشفة مختلف، ولكن جسم الرسالة سيكون نسخة طبق الأصل!
إذا كنت ترغب في شرح أعمق، إليك رابط إلى وثائق SparkPost حول إنشاء نسخ مكررة (أو أرشفة) من الرسالة الإلكترونية.
كملاحظة جانبية، تسمح SparkPost بالفعل بإرسال رسائل إلكترونية إلى عناوين cc وbcc وأرشفة. بالنسبة لهذا الحل، نركز على العناوين الأرشيفية فقط.
* ملحوظة * يمكن إنشاء الرسائل الإلكترونية المؤرشفة فقط عند إدخال الرسائل الإلكترونية عبر SMTP في SparkPost!
الآن بعد أن عرفنا كيفية الحصول على نسخة من الرسالة الإلكترونية الأصلية، نحن بحاجة إلى النظر في بيانات السجل التي يتم إنتاجها وبعض الفروق الدقيقة ضمن تلك البيانات. يتتبع SparkPost كل شيء يحدث على خوادمه ويقدم لك تلك المعلومات في شكل أحداث الرسائل. يتم تخزين تلك الأحداث على SparkPost لمدة 10 أيام ويمكن سحبها من الخادم عبر واجهة برمجة التطبيقات RESTful المسماة بأحداث الرسائل، أو يمكنك جعل SparkPost ترسل تلك الأحداث إلى أي عدد من التطبيقات التي ترغب في جمعها. يتم تنفيذ آلية الدفع عبر الشبكة في الوقت الحقيقي.
حاليًا، هناك 14 حدثًا مختلفًا قد يحدث للبريد الإلكتروني. إليك قائمة بالأحداث الحالية:
ارتداد
تأخير الارتباط
تسليم
فشل الإنشاء
رفض الإنشاء
الفتح الأولي
إدخال إلغاء الاشتراك
إلغاء الاشتراك من القائمة
فتح
خارج النطاق
رفض السياسة شكوى البريد العشوائي
* اتبع هذا الرابط لمرجع محدث لوصف كل حدث مع البيانات التي تتم مشاركتها لكل حدث.
كل حدث يحتوي على حقول عديدة تطابق نوع الحدث. بعض الحقول مثل transmission_id توجد في كل حدث، لكن حقول أخرى قد تكون أكثر تحديدًا للحدث؛ على سبيل المثال، فقط الأحداث المفتوحة والمضغوطة تحتوي على معلومات تحديد المواقع الجغرافية.
أحد إدخالات الحدث الهامة جدًا لهذا المشروع هو transmission_id. جميع إدخالات حدث الرسائل للرسالة الإلكترونية الأصلية، والرسائل المؤرشفة، وأي عناوين cc وbcc ستحمل نفس transmission_id.
هناك أيضًا إدخال عام يسمى message_id سيكون له نفس المعرف لكل إدخال للرسالة الإلكترونية الأصلية والرسالة المؤرشفة. أي عناوين cc أو bcc سيكون لها معرف خاص بها لإدخال message_id .
حتى الآن كل شيء يبدو رائعًا وبصراحة سهل إلى حد ما، لكن الآن يأتي الجزء الصعب. تذكر، من أجل الحصول على الرسالة الإلكترونية المؤرشفة، نجعل SparkPost ترسل نسخة من الرسالة الإلكترونية الأصلية إلى عنوان بريد إلكتروني آخر يتوافق مع بعض صناديق البريد التي لديك إمكانية الوصول إليها. ولكن من أجل أتمتة هذا الحل وتخزين جسم الرسالة الإلكترونية، سأستخدم ميزة أخرى لـ SparkPost تسمى إعادة توجيه البريد الإلكتروني الوارد. ما تفعله هو أخذ جميع الرسائل الإلكترونية المرسلة إلى نطاق معين ومعالجتها. من خلال معالجتها، يتم تفكيك الرسالة الإلكترونية وإنشاء بنية JSON يتم تسليمها بعد ذلك إلى تطبيق عبر webhook. انظر الملحق A لعينة من JSON.
إذا نظرت بعناية شديدة، ستلاحظ أن بنية JSON من الترحيل الوارد تفتقد إلى حقل مهم جدًا؛ وهو transmission_id. بينما جميع الرسائل الإلكترونية الصادرة تحتوي على transmission_id مع نفس الإدخال الذي يربط جميع البيانات من الرسالة الإلكترونية الأصلية والأرشيف والعناوين cc وbcc؛ ليس لدى SparkPost أي وسيلة لمعرفة أن الرسالة الإلكترونية الملتقطة بواسطة العملية الواردة مرتبطة بأي من الرسائل الإلكترونية الصادرة. العملية الواردة تعرف فقط أن رسالة إلكترونية أرسلت إلى نطاق محدد وتقوم بتحليل الرسالة. هذا كل شيء. سيتم التعامل مع أي رسالة إلكترونية مرسلة إلى ذلك النطاق بنفس الطريقة، سواء كانت رداً من عميل أو الرسالة المؤرشفة المرسلة من SparkPost.
لذا، الفكرة هي؛ كيف تلصق البيانات الصادرة مع العملية الواردة التي لقطت النسخة المؤرشفة من الرسالة الإلكترونية؟ ما قررت فعله هو إخفاء معرف فريد في جسم الرسالة الإلكترونية. كيف يتم ذلك يعود إليك، لكنني فقط أنشأت حقل إدخال مع وضع علامة مخفية مفعلة.
أضفت أيضًا هذا الحقل إلى كتلة البيانات الفوقية في رأس X-MSYS-API التي يتم تمريرها إلى SparkPost أثناء الإدخال. سينتهي هذا المعرف المخفي بأن يصبح لصقاً للكلية عملية، وهو مكون أساسي من المشروع وسيتم مناقشته بعمق في منشورات المدونات التالية.
الآن بعد أن لدينا المعرف الفريد الذي سيلصق هذا المشروع معًا ويفهم لماذا هو ضروري، يمكنني البدء في بناء رؤيتي للمشروع الرئيسي ومنشورات المدونات المقابلة.
التقاط وتخزين الرسالة المؤرشفة مع إدخال قاعدة بيانات للبحث/الفهرسة{



