فلدي تذهب بسرعة. تحسين طلبات محتوى البريد الإلكتروني IMAP

تحية للجميع! في مقال سابق ، تحدثت عن كيفية مزامنة محتويات مربع في ذاكرة التخزين المؤقت المحلية بسرعة. أريد أن أتحدث هنا عن ميزات طلب محتويات الرسائل وأفضل طريقة لطلب المحتوى ، وعدم الخوف من الاستهلاك المرتفع للزيارات.

صورة

لنتذكر بسرعة ما تعلمناه في المقالة الأخيرة:

  • IMAP هو بروتوكول ذو حالة
  • لرؤية محتويات البريد الوارد ، يجب عليك أولاً تحديده باستخدام الأمر SELECT
  • لمزامنة المربع الذي نحن فيه بسرعة ، يمكنك استخدام الأمر NOOP
  • حتى لا يتم فرز الرسائل من التخزين المحلي لتحديث صندوق البريد الذي تركناه بالفعل ، يمكنك استخدام CONDSTORE و QRESYNC ، بشرط أن يدعم الخادم الخاص بك بيانات ملحق البروتوكول

يكفي!


دعني أذكرك بالأمر لطلب نص الرسالة:

1 FETCH number (BODY[])

سيؤدي هذا إلى إنشاء طلب للحصول على النص الكامل للرسالة وجميع المرفقات. فقط انظر كم من الوقت يستغرق الحصول على رسالة في 42 فقرة من Lorem Ipsum وصورة 2 ميغا بايت.

أولاً ، اسأل حجم الرسالة على الخادم. يتم ذلك عن طريق الأمر:

1 FETCH 18871 (RFC822.SIZE)

يقوم RFC822.SIZE بارجاع حجم الرسالة بالبايت:

* 18871 FETCH (RFC822.SIZE 3937793)

ونتيجة لذلك ، تستهلك رسالتنا ما يقرب من 4 ميغابايت.

الآن ، مع ذلك ، سنستخدم طلب النص الكامل للرسالة ونلقي نظرة على الوقت:

1 OK Fetch completed (0.007 + 3.265 secs).

3.3 ثانية! وهذه ليست سوى رسالة واحدة مع المرفق ، وتخيل أنها ستكون الصندوق بأكمله. ثم يستغرق الأمر أكثر من دقيقة لتنزيل ما لا يقل عن واحد وعشرين واحدًا.

يجب أن تعترف بأن عمل العميل الذي لم يتمكن في عام 2020 من مزامنة البريد بشكل أسرع من دقيقة سيء. ولكن ماذا تفعل؟

أعطني لدغة مرة واحدة


إذا سرقت RFC3501 في الفقرة 6.5.4 ، التي تصف المعلمات المحتملة لأمر FETCH ، فستلاحظ طلبًا مثيرًا للاهتمام:

BODY[<section>]<<partial>>

  • القسم - أي جزء من الرسالة للحصول عليها
  • جزئي - حجم هذا الجزء

كيف يتم البناء الجزئي؟ وهو سهل للغاية. أولاً ، تتم كتابة البايت التي تحتاج إلى بدء القراءة من خلال النقطة ، ثم عدد البايتات التي يجب قراءتها بشكل عام:

BODY[<section>]<<0.1024>>

نطلب هنا جزء الرسالة من صفر بايت إلى 1024.

حسنًا ، ما هو القسم؟ أولاً ، سأتحدث عن مثل هذه المعلمة المفيدة في استعلام FETCH مثل BODYSTRUCTURE:

1 FETCH 18871 (BODYSTRUCTURE)

تقوم هذه المعلمة ، كما تفهم على الأرجح من التوقيع ، بإرجاع بنية الحرف في النموذج الموضح في MIME-IMB .

* 18871 FETCH (BODYSTRUCTURE ((("text" "plain" ("charset" "utf-8") NIL NIL "quoted-printable" 25604 337 NIL NIL NIL NIL)("text" "html" ("charset" "utf-8") NIL NIL "quoted-printable" 29593 390 NIL NIL NIL NIL) "alternative" ("boundary" "--=_Part_763_774309787.1586268692") NIL NIL NIL)("image" "jpeg" ("name" "IMG_20200217_000236.jpg") NIL NIL "base64" 3880726 NIL ("attachment" ("filename" "IMG_20200217_000236.jpg")) NIL NIL) "mixed" ("boundary" "--=_Part_210_297656922.1586268692") NIL NIL NIL))


مجرد إلقاء نظرة على هذا الهيكل ، ورأسك يدور؟ لا تخف ، الآن سنكتشف ذلك. قارن بين قوسين الافتتاح والختام.

(
BODYSTRUCTURE 
(
[1] (
[1.1] ("text" "plain" ("charset" "utf-8") NIL NIL "quoted-printable" 25604 337 NIL NIL NIL NIL)
[1.2] ("text" "html" ("charset" "utf-8") NIL NIL "quoted-printable" 29593 390 NIL NIL NIL NIL) "alternative" ("boundary" "--=_Part_763_774309787.1586268692") NIL NIL NIL
)
[2] ("image" "jpeg" ("name" "IMG_20200217_000236.jpg") NIL NIL "base64" 3880726 NIL ("attachment" ("filename" "IMG_20200217_000236.jpg")) NIL NIL) "mixed" ("boundary" "--=_Part_210_297656922.1586268692") NIL NIL NIL
)
)


قد تلاحظ أنني أضع أرقامًا بالقرب من بعض الأقواس. هذا القسم.
كيف نحسبها؟ يجب تخطي القوس الأول ، لأنه يحتوي ببساطة على إجابة الطلب ، ثم يجب ترقيم كل قوس فتح وفقًا للقاعدة حيث يتم ترقيم العناوين في المستندات:

  • يتم ترقيم كل قوس فتح مع مراعاة القسم السابق
  • إذا كان القسم متداخلاً ، فسيتم إضافة القسم الحالي من خلال النقطة إلى الرقم السابق
  • إذا لم يكن القسم متداخلاً ، فقم بزيادة رقمه واحدًا


على سبيل المثال ، في هذه الحالة ، في الجزء الأول الذي ينتهي بـ "بديل" (أي ، هذا هو الجزء من الحرف متعدد الأجزاء / البديل ، حيث لدينا الحرية في اختيار الأجزاء التي سيتم عرضها للمستخدم) ، هناك قسمان يتم ترقيمهما من خلال نقطة. التقيت بخادم حيث قد يكون هناك تداخل من ثلاثة مستويات (أي [1.1.1] ، [1.1.2] ، إلخ).
دعونا نحلل الجزء [1.1] بالنظر إلى هيكل كل هذه الأشياء في وثيقة MIME-IMB . بناءً على ذلك ، يكون رأس نوع المحتوى هو الأول. ويشمل:

  • نوع MIME ، هنا هو نص / عادي
  • الترميز (charset = utf8)


فيما يلي معلمتان مكتوبتان كـ NIL. بصراحة ، لم أفهم ما هو ، ولكن حتى الآن لم أكن بحاجة إليه ، لذلك سأفتقده. أعتذر عن مثل هذه العبثية.
التالي هو رأس نقل المحتوى - الترميز ، يتم تضمينه فيه ، والذي يصف آلية الترميز ، هنا يمكن اقتباسه للطباعة. 
يصف الرقمان التاليان حجم الجزء بالبايت وعدد الأسطر ، إن أمكن. بمساعدتهم ، يمكننا حساب عدد وحدات البايت التي يجب أخذها لعرض عدد معين من الأسطر.
الأسطر التالية غير الموجودة في هذا الجزء:

  • معرف المحتوى ، الذي يتم استخدامه في السطر من الرسالة
  • وصف المحتوى ، سطر يصف ماهية هذا الجزء


بالنسبة إلى المعلمتين الأخريين ، لم أتمكن من العثور على إجابة محددة حول هذا ، ولكن قد تحتوي إحدى هذه المعلمات على أجزاء MD5 ، والتي قد تكون مفيدة في بعض الأحيان.
بالنسبة للجزء [2] ، كل شيء هو نفسه ، باستثناء أنه صورة ومرفق باسم وتشفير base64. إذا كان لا يزال من غير الواضح تمامًا ما يحدث هنا ، فقد تم تحديد كيفية حساب القسم بالضبط على هذا الموقع .

ماذا يعطي؟ وحقيقة أنه في مرحلة عرض الرسالة ، يمكننا بالفعل طلب الجزء العلوي فقط من المحتوى وعدم تحميل المرفقات حتى يدخل المستخدم نفسه الرسالة وينقر فوق الزر "تنزيل". تأتي جميع المعلومات لعرض المرفقات معنا إلى BODYSCTRUCTURE بحيث يمكن عرض الاسم والتنسيق والحجم دون تحميل المرفق نفسه. 

دعنا ننتقل إلى الممارسة. سنطلب كيلو بايت واحد من محتوى الرسالة بدون مرفقات ، فقط لمعرفة ما أرسلوه إلينا.

1 fetch 18871 (body[1.1]<0.1024>)
* 18871 FETCH (BODY[1.1]<0> {1024}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus consecte=
tur enim in nisi venenatis, id varius tellus viverra. Praesent et enim te=
llus. Nunc vestibulum diam tortor, id posuere turpis tempor luctus. Vivam=
us molestie non nunc nec placerat. Cras finibus ut erat et tristique. Cur=
abitur vitae commodo risus. Etiam sed scelerisque erat. Quisque cursus bl=
andit finibus. Nullam ac lectus accumsan, molestie quam non, mollis urna.=
 Nulla at arcu in libero condimentum mollis ut non velit. Vestibulum sed =
risus et magna congue iaculis. Vestibulum nec interdum elit, ut commodo m=
auris. Nulla ipsum leo, vestibulum nec ligula non, elementum ullamcorper =
risus. Nunc et malesuada sem, id venenatis massa. Integer dolor ante, max=
imus in eleifend nec, ultricies ut risus. Mauris posuere eget tortor at p=
orttitor.=0AIn porta elementum ornare. Suspendisse aliquam, tortor sed al=
iquam bibendum, nulla ante rhoncus elit, placerat accumsan augue nibh non=
 est. Duis finibus vel tortor finibu)
1 OK Fetch completed (0.073 + 0.000 + 0.072 secs).


حوالي 100 مللي ثانية ونرى بالفعل بعض محتوى الرسالة! هذه مجرد نتيجة ممتازة ، نظرًا لأننا في السابق استغرقنا ما يقرب من 4 ثوان لتنزيل محتوى حرف واحد. ثم يمكنك ببساطة تحميل محتوى الرسالة بالكامل في دفق الخلفية ، من الخارج سيبدو أن الحروف يتم تحميلها على الفور. كل ما كان مطلوبًا هو النظر إلى هيكل الرسالة وتنزيل ما هو مطلوب فقط للعرض السريع. 
لحظة واحدة فقط. سيؤدي هذا الطلب إلى ظهور الرسالة على الخادم كمقروءة. ولكن يمكنك إصلاح ذلك عن طريق إضافة نظرة خاطفة فقط إلى طلب النص

1 fetch 18871 (BODY.PEEK[1.1]<0.1024>)
* 18871 FETCH (BODY[1.1]<0> {1024}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus consecte=
tur enim in nisi venenatis, id varius tellus viverra. Praesent et enim te=
llus. Nunc vestibulum diam tortor, id posuere turpis tempor luctus. Vivam=
us molestie non nunc nec placerat. Cras finibus ut erat et tristique. Cur=
abitur vitae commodo risus. Etiam sed scelerisque erat. Quisque cursus bl=
andit finibus. Nullam ac lectus accumsan, molestie quam non, mollis urna.=
 Nulla at arcu in libero condimentum mollis ut non velit. Vestibulum sed =
risus et magna congue iaculis. Vestibulum nec interdum elit, ut commodo m=
auris. Nulla ipsum leo, vestibulum nec ligula non, elementum ullamcorper =
risus. Nunc et malesuada sem, id venenatis massa. Integer dolor ante, max=
imus in eleifend nec, ultricies ut risus. Mauris posuere eget tortor at p=
orttitor.=0AIn porta elementum ornare. Suspendisse aliquam, tortor sed al=
iquam bibendum, nulla ante rhoncus elit, placerat accumsan augue nibh non=
 est. Duis finibus vel tortor finibu)
1 OK Fetch completed (0.001 + 0.000 secs).


وفويلا! تبقى الرسالة غير مقروءة وبعض المحتوى الذي تلقيناه.
يصبح كل شيء أسهل حتى إذا تم تنفيذ ميزة طلب معاينة على الخادم الخاص بك. 

1 fetch 18871 (PREVIEW)
* 18871 FETCH (PREVIEW (FUZZY "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus consectetur enim in nisi venenatis, id varius tellus viverra. Praesent et enim tellus. Nunc vestibulum diam tortor, id posuere turpis t"))
1 OK Fetch completed (0.001 + 0.000 secs).


هنا لا نقضي الوقت في الاستعلام عن البنية على الإطلاق ونحصل على معاينة الرسالة على الفور. ولكن لا تنس أن بنية الاستعلام مفيدة لتحديد المرفقات بحيث لا يتم تحميلها في وضع الخمول.

انتظر


ينفذ أي برنامج بريد تقريبًا الزر "تحديث" إذا كان المستخدم يريد تلقي رسائل جديدة في الوقت الحالي. ولكن بطريقة ما ، هذا ليس رائعًا في عصرنا ، حيث توجد إشعارات في كل من الأجهزة والمتصفحات. ماذا يقول IMAP عن هذا؟ ويقول IDLE . هذه العملية تحمل الاتصال بالمجلد وتعلمك بالتغييرات التي تطرأ على المجلد. يرجى ملاحظة ، ليس صندوق البريد ، ولكن المجلدات. للقيام بذلك ، تحتاج إلى الخادم لتطبيق ميزة IDLE. 

أولاً ، حدد المجلد الذي سيرسل إليه الخادم تنبيهات ، ثم قم بتمكين IDLE

1 SELECT Inbox
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded $MDNSent)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded $MDNSent \*)] Flags permitted.
* 18872 EXISTS
* 0 RECENT
* OK [UNSEEN 18685] First unseen.
* OK [UIDVALIDITY 1532079879] UIDs valid
* OK [UIDNEXT 20155] Predicted next UID
* OK [HIGHESTMODSEQ 26338] Highest
1 OK [READ-WRITE] Select completed (0.002 + 0.000 + 0.001 secs).
1 IDLE
+ idling


يخطر الجواب "+ الخمول" حول إدراج الخمول في المجلد. ماذا يحدث إذا وصلت رسالة جديدة؟

* 18873 EXISTS
* 1 RECENT


لقد أرسلت لنفسي نفس الرسالة ، وأبلغتني بأنني يجب أن أطلب الرسالة 18873 ، وأن هناك 18873 رسالة في المجلد ، وأن رسالة واحدة وصلت للتو.
بعد ذلك ، سأطلب هذه الرسالة في اتصال آخر ، نحن مهتمون بالحرف مع الإجابة EXISTS.

1 fetch 18873 (BODY.PEEK[1.1]<0.1024>)
* 18873 FETCH (BODY[1.1]<0> {1024}
---- Original Message ---- Tue, Apr 7, 2020, 17:11=0ASubject=
: Lorem Ipsum=0A  Lorem ipsum dolor sit amet, consectetur adipiscing elit=
. Vivamus consectetur enim in nisi venenatis, id varius tellus viverra. P=
raesent et enim tellus. Nunc vestibulum diam tortor, id posuere turpis te=
mpor luctus. Vivamus molestie non nunc nec placerat. Cras finibus ut erat=


من المهم جدا أن تفهم. يتطلب IDLE اتصالاً منفصلاً ، لذا لا يمكنك تلقي التغييرات وطلب الرسائل في نفس الجلسة.
ماذا يمكن لـ IDLE أيضًا القيام به؟ إنه قادر على الإخطار عن الرسائل المحذوفة والحروف التي تغيرت أعلامها. لنلق نظرة على الحرف على سبيل المثال ، وبذلك نضع علامة "رأيت" عليه ونحذف الحرف.

* 18873 FETCH (FLAGS (\Seen \Recent))
* OK Still here
* OK Still here
* 18873 EXPUNGE
* 18871 EXPUNGE
* 0 RECENT


حذفت المحادثة (18873 ، 18871) ونظرت إلى رسالة أخرى (استجابة FETCH). لماذا أصبحت هذه الرسالة 18871؟ لأن IMAP يحسب رقم الحرف إذا تغير شيء ما. منذ أن أصبح الأعلى ، تغير رقمه أيضًا. 
مع IDLE ، يمكننا مزامنة حالة الصندوق بسرعة ، ولكن من غير المريح أنه يتطلب اتصالًا منفصلاً. هل يمكن أن يكون أفضل؟ لهذا أنا هنا.

يصيح كيف حالك


ماذا لو أخبرتك أن هناك ميزة تسمح لك بتلقي إشعارات من الخادم في نفس الاتصال ، وحتى تكوينها خصيصًا لصناديق البريد ، ولا حتى واحدة. يبدو وكأنه حكاية خرافية ، لكن لا تصاب بالجنون ، فهذه قدرة حقيقية على الإخطار . يعرف الكثير ، على سبيل المثال:

  • تكوين مجلدات معينة نتوقع منها إشعارات
  • الاستماع إلى تغييرات حالة المجلد (قراءة الحروف ، الحروف الجديدة)
  • قم بتعيين تنسيق الإعلام ، أي ما نريد رؤيته عند تغيير المجلد
  • استمع إلى تغييرات اسم المجلد
  • استمع إلى تغييرات بيانات تعريف المجلد


دعنا نلقي نظرة على مثال لكيفية الاستماع إلى تغييرات حالة المجلد

1 notify set (inboxes (MessageNew FlagChange MessageExpunge))
1 OK NOTIFY completed (0.001 + 0.000 secs).


الآن سيرسل الخادم إلينا إشعارات بحالات المجلد ، على سبيل المثال ، سأضيف بضع رسائل إلى مجلدات مختلفة

* STATUS INBOX/Ozon (MESSAGES 312 UIDNEXT 321 UNSEEN 48)
* STATUS "INBOX/Company News" (MESSAGES 178 UIDNEXT 179 UNSEEN 1)
* STATUS "INBOX/Company News" (MESSAGES 177 UIDNEXT 179 UNSEEN 0)


سأقوم بتحليل الأمر:
يأتي أولاً الأمر NOTIFY SET. بعد ذلك ، بين قوسين ، نختار المجلدات التي سنستمع إليها:

  • Inboxes - لجميع المجلدات التي يمكنك تحديدها
  • شخصي - المجلدات الموجودة في مساحة اسم المستخدم
  • مشترك - المجلدات التي اشترك فيها المستخدم
  • الشجرة الفرعية - الشجرة الفرعية للمجلد الذي سيتم تحديده
  • صناديق البريد - هنا يمكنك سرد المجلدات للاستماع إليها.
  • محدد - تنبيه للمجلدات المحددة فقط


والمعلمات المسؤولة عن مرشح التنبيه:

  • MessageNew - في حالة وصول رسالة جديدة
  • FlagChange - إذا تغير العلم
  • MessageExpunge - إذا تم حذف الرسالة أو نقلها


ولكن باستخدام مثل هذا الأمر ، لا يمكننا تلقي معلمات رسالة جديدة أو تم تغييرها أو حذفها. للقيام بذلك ، حدد المعلمة المحددة وحدد ما تريد إرجاعه بالضبط. يمكننا إضافة تنبيه آخر دون حذف التنبيه السابق.

1 notify set status (selected (MessageNew (uid preview) MessageExpunge))


هنا داخل MessageNew ، نحدد المعلمات التي يجب أن يعرضها الإشعار. سأختار Inbox ومرة ​​أخرى سأرمي لنفسي lorem ipsum.

* 18868 FETCH (UID 20157 PREVIEW (FUZZY "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus consectetur enim in nisi venenatis, id varius tellus viverra. Praesent et enim tellus. Nunc vestibulum diam tortor, id posuere turpis t"))


كيف تريده؟ بالنسبة إلى وضع الخمول ، نحتاج إلى الحفاظ على اتصالين ، أحدهما يطلب أيضًا رسائل أعادها لنا. على الفور يجلبون لنا كل شيء على طبق من الفضة. 
وهكذا يمكننا الاستماع إلى تغييرات اسم المجلد

1 notify set (inboxes (MailboxName))


إعادة تسمية بعض المجلدات ورؤية النتيجة.

* LIST () "/" 1111 ("OLDNAME" (aaaa))


والآن نعلم أن هناك مجلد "aaaa" وأصبح "1111" ،
والآن يمكنك الاستماع إلى تغيير الأعلام وإزالة الرسائل. للقيام بذلك ، استخدم المعلمة FlagChange

1 notify set (selected (MessageNew (uid) FlagChange MessageExpunge))


وعندما تقوم بتغيير أعلام الرسائل وحذفها ، نحصل عليها

* 18865 EXPUNGE
* 18864 FETCH (FLAGS ())
* 18864 FETCH (FLAGS (\Answered))


ماذا بعد


كل هذه الميزات تساعد عميل البريد على العمل بسرعة وسهولة قدر الإمكان للمستخدم. يخطر IDLE و NOTIFY المستخدم بالتغييرات في المجلدات ، ويطلب جزءًا من الرسالة تسريع تحميله. 
في المقالة الأخيرة ، أود أن أتحدث عن آلية البحث في IMAP وكيف يمكن تسريعها وتقليل الحمل على الشبكة. شكرا للقراءة حتى النهاية. 

All Articles