تخطَّ إلى المستندات
Python

جهات الاتصال

`contacts.list` و`get` و`create` و`save` و`update` و`set_audiences` و`delete` و`delete_many` و`list_people` و`set_photo` و`remove_photo` و`block` و`unblock` و`list_threads` و`activity`.

كل الدوالّ

usage.py
from openemail import openemail page = openemail.contacts.list(limit=100)contact = openemail.contacts.get('[email protected]') saved = openemail.contacts.create({    'email': '[email protected]',    'name': 'Grace Hopper',    'notes': 'Met at the compiler workshop',}) openemail.contacts.update(saved['email'], {'notes': None})openemail.contacts.set_audiences(saved['email'], {    'audienceIds': ['aud_4c1b8e2a7d9f05c36b4e8a71'],})openemail.contacts.delete(saved['email']) print(len(page['items']), page['hasMore'], contact['source'], contact['lastSeenAt'])

الأحدث ظهورًا أولًا، مع وضع جهات الاتصال التي لم تُراسَل قط في الآخر. وتكون source بالقيمة auto عندما كُتب السجل لأن عضوًا أرسل إلى ذلك العنوان رسالة من محرّر الرسائل في التطبيق، وهو ادعاء مختلف جوهريًا عن أن شخصًا حفظ العنوان بنفسه. ووصول بريد من عنوان لا يكتب شيئًا، وكذلك الإرسال عبر هذه الواجهة.

دفتر العناوين ملك لمساحة العمل لا لشخص واحد، فجهة الاتصال التي يحفظها أي عضو هي نفسها التي يراها كل عضو وكل مفتاح. ويكتب create قيمة source بالقيمة manual ويضع جهة الاتصال في الجمهور الافتراضي فور كتابتها. اذكر قوائمك الخاصة في audienceIds لضمّها في الاستدعاء نفسه، وهو ما يتطلب أيضًا audiences:write، أو أضف جهة الاتصال لاحقًا عبر openemail.audiences.add_contact. ويحدّد set_audiences بالضبط القوائم التي تنتمي إليها جهة اتصال، باستدعاء واحد.

تُخزَّن العناوين بأحرف صغيرة ويرمّز العميل العنوان الذي تمرّره، فيصل [email protected] إلى السجل الصحيح. والعنوان هو الهوية، لذا لا يستطيع update تغييره: فنقل جهة اتصال يعني delete ثم create.

المعاملات: contacts.list

limitint
عدد جهات الاتصال المعادة في كل صفحة: عدد صحيح من 1 إلى 200، والافتراضي 50. وتُحوَّل القيمة تلقائيًا، فقيمة مثل `'100'` قادمة من سلسلة استعلام مقبولة، أما قيمة خارج المدى فترد 422 بدلًا من حصرها داخل المدى.
cursorstr
قيمة `nextCursor` من الصفحة السابقة. ولا تبنِ واحدة بنفسك أبدًا: فمؤشر يسمي جهة اتصال لم تعد موجودة يعطي 400 مع `invalid_cursor`، ما يعني أن حالة الترقيم لديك قديمة وأن عليك إعادة المرور من البداية دون cursor.
sourceContactSource
القيمة `'manual'` لجهات الاتصال التي حفظها شخص عن قصد، و`'auto'` لتلك التي سجّلها محرّر الرسائل في التطبيق. اتركها دون تحديد للحصول على الدفتر كاملًا.
qstr
يبحث في الاسم والعنوان، حتى 200 حرف. وإن لم يطابق شيء تمامًا في الصفحة الأولى، تُعاد تهجئات قريبة بدلًا من ذلك، وتواصل الصفحات التالية المطابقة بالطريقة نفسها.

الاستجابة: ContactResource

يعيد contacts.list قيمة Page[ContactResource]، فتكون السجلات في page['items'] ويتبع المرور قيمة page['nextCursor'] ما دامت page['hasMore'] تساوي True، وهو ما يفعله list_all وiterate نيابةً عنك. أما get وcreate وsave وupdate وset_audiences وset_photo وremove_photo فكل منها يعيد ContactDetailResource واحدًا، وهو السجل نفسه مضافًا إليه audiences. ودفتر العناوين غير محدود الحجم، ولهذا يعتمد هذا المسار الترقيم بدلًا من إعادة قائمة تتوقف عند 200 بصمت.

objectLiteral['contact']
دائمًا السلسلة `contact`، في سجلات القائمة كما في `get`.
emailstr
العنوان، ويُحوَّل إلى أحرف صغيرة عند الكتابة فيصبح `[email protected]` و`[email protected]` جهة اتصال واحدة، وهو المفتاح الذي تأخذه كل دوال contacts، إذ لا يُكشف أي معرّف لجهة الاتصال. والسجلات ملك لمساحة العمل لا للعضو أو المفتاح الذي كتبها، فكل عضو وكل مفتاح في مساحة العمل يقرأ ويكتب في دفتر عناوين واحد.
namestr | None
يكون `None` عندما لا يكون قد سُجّل أي اسم لهذا العنوان قط. والكتابة التلقائية لا تحمل اسمًا إلا إذا وفّرت الترويسة شيئًا غير العنوان نفسه، ولا يمكنها أبدًا أن تطمس اسمًا كتبه المستخدم.
sourceContactSource | str
تعني `auto` أن السجل كُتب لأن المستخدم أرسل بريدًا إلى ذلك العنوان؛ وتعني `manual` أن شخصًا أدخله بنفسه، وهو ادعاء مختلف جوهريًا، ولا تُنزل عملية الإدراج والتحديث قيمة `manual` إلى `auto` أبدًا. ووصول بريد من عنوان لا يكتب أي سجل على الإطلاق، وهذا مقصود، فمن لم يفعل سوى مراسلتك ليس هنا؛ ويبقى الاتحاد مفتوحًا لأن العمود نص حر قيمته الافتراضية `manual`.
notesstr | None
نص حر كتبه شخص ما عن هذا الشخص، في التطبيق أو عبر `update`، ولا يُولَّد آليًا أبدًا. ويكون `None` عندما لا يكون أحد قد كتب شيئًا، وتمرير `None` صراحةً في `update` يمسحه.
lastSeenAtstr | None
بصيغة ISO-8601 بتوقيت UTC، ويُحدَّث في كل مرة يرسل فيها عضو إلى ذلك العنوان من محرّر الرسائل في التطبيق، لا عند وصول بريد منه، فذلك لا يكتب شيئًا. ويكون `None` لجهة اتصال حُفظت عبر `create` ولم تُراسَل قط، وتأتي هذه في الآخر في الترتيب التنازلي حسب `lastSeenAt` الذي يعيده هذا المسار.
audienceslist[ContactAudienceResource]
يظهر في `get` و`create` و`save` و`update` و`set_audiences` و`set_photo` و`remove_photo` فقط، ولا يظهر أبدًا في سجلات القائمة. ويضم كل جمهور تنتمي إليه جهة الاتصال، في صورة قاموس فيه `id` و`name` و`builtin`، بما في ذلك الجمهور الافتراضي. وتكون `builtin` بالقيمة `default` في الجمهور الذي تنتمي إليه كل جهة اتصال و`None` في جمهور أنشأه شخص ما، لذا تفرّع على هذا الحقل لا على الاسم الذي يستطيع أي أحد تغييره.
photoUrlstr | None
مكان تقديم صورة جهة الاتصال، أو `None` حين لا تكون لها صورة. يعيّنها `set_photo`، وكل رفع يحصل على URL جديد.

تحديد جماهير جهة اتصال

يحدّد set_audiences(email, {'audienceIds': [...]}) بالضبط الجماهير التي تنتمي إليها جهة اتصال واحدة، بطلب واحد. تنضم جهة الاتصال إلى كل جمهور مذكور لم تكن فيه بعد، وتغادر كل جمهور آخر، ويعيد الاستدعاء ContactDetailResource بعد التغيير. ويتطلب audiences:write، لأنه يكتب العضويات لا جهة الاتصال، وتكراره لا يغيّر شيئًا.

يُحتفظ بالجمهور الافتراضي دائمًا، لذا فإن {'audienceIds': []} يُبقي جهة الاتصال في الجمهور الافتراضي وحده. ويقبل حتى 100 معرّف. والمعرّف الذي لا يشير إلى أي جمهور في مساحة العمل هذه يعطي 404 audience_not_found ولا يتغير شيء، والعنوان الذي ليس جهة اتصال يعطي 404 contact_not_found.

كل من في صفحة جهات الاتصال

يسرد list_people الأشخاص الذين تعرضهم صفحة جهات الاتصال في التطبيق: جهات الاتصال المحفوظة وكل عنوان ظهر في البريد، ولكلٍّ منها saved وthreads وlastAt. أما list فجهات الاتصال المحفوظة وحدها. ولا تأتي العناوين التي ظهرت في البريد إلا إذا كان المفتاح يحمل threads:read أيضًا، ويقول page['seen'] هل أتت. وsort هو recent أو name أو threads، ويبحث q في الأسماء والعناوين والملاحظات، ويُبقي blocked=True الأشخاص الذين تحظرهم قائمة حظر مساحة العمل، بما في ذلك قواعد النطاق الكامل. ويسمّي blockedBy القاعدة في كل صف.

people.py
from openemail import openemail page = openemail.contacts.list_people(sort='threads', limit=50) for person in page['items']:    if not person['saved'] and (person['threads'] or 0) > 5:        openemail.contacts.save(person['email']) blocked = openemail.contacts.list_all_people(blocked=True)

يمرّ list_all_people وiterate_people على كل صفحة. والمؤشر معتم، فأعِد nextCursor كما جاء، مع sort وq وblocked نفسها.

الحفظ والحذف والصور

save(email, {'name': ..., 'notes': ...}) هو إضافة إلى جهات الاتصال والإبقاء في جهات الاتصال: يحفظ عنوانًا ليس جهة اتصال بعد، ويُبقي عنوانًا سُجّل من إرسال محفوظًا يدويًا، ويعيد عنوانًا محذوفًا. وdelete هو حذف: يزيل جهة الاتصال المحفوظة ويُخفي العنوان، كي لا يسجّله محرّر الرسائل مجددًا، ويقبل كذلك عنوانًا لم يظهر إلا في البريد. ويقول wasSaved أيّهما كان. ويحذف delete_many ما يصل إلى 200 في استدعاء واحد.

photo.py
from pathlib import Path from openemail import openemail openemail.contacts.save('[email protected]', {'name': 'Grace Hopper'}) photo = Path('grace.jpg').read_bytes()contact = openemail.contacts.set_photo('[email protected]', photo, content_type='image/jpeg') openemail.contacts.remove_photo('[email protected]')openemail.contacts.delete_many(['[email protected]', '[email protected]'])

يرسل set_photo بايتات الصورة كما هي: PNG أو JPEG أو WebP أو GIF حتى 5 ميغابايت، تُلاءَم داخل مربع 512 بكسل. مرّر content_type=، لأن البايتات لا تحمل نوعًا خاصًا بها: فبدونه يُرفع الملف بنوع application/octet-stream، الذي يُرفض بـ 422 invalid_image. ويجب أن يكون العنوان جهة اتصال محفوظة أولًا.

الحظر

يضع block(email) العنوان في قائمة حظر مساحة العمل كي يُرفض بريده، مُسقطًا أي وسم زائد، ويزيل unblock(email) كل قاعدة تحظره. وكلاهما يحتاج settings:write، لأنهما يغيّران قائمة الحظر لا جهة الاتصال، ولا يحتاج أيٌّ منهما أن يكون العنوان جهة اتصال.

حين يرفع unblock قاعدة نطاق كامل، يسردها removed مع list مضبوطًا على blockedDomains، ويُلغى معها حظر كل من في ذلك النطاق.

المحادثات والنشاط

يتصفح list_threads(email) صفحةً تلو صفحة السلاسلَ التي كتبها العنوان أو كُتبت إليه، في كل المجلدات، ويمرّ list_all_threads وiterate_threads عليها كلها. ويعيد activity(email) الأرقام التي خلف تبويب النشاط لجهة اتصال: الوارد والصادر لكل فاصل، والسلاسل التي تنتظر ردك، والزمن الوسيط للرد في كل اتجاه. وكلاهما يحتاج threads:read.

activity.py
import time from openemail import openemail threads = openemail.contacts.list_threads('[email protected]', q='invoice') activity = openemail.contacts.activity(    '[email protected]',    minutes=30 * 24 * 60,    grain='day',    offset_minutes=time.localtime().tm_gmtoff // 60,) print(len(threads['items']), activity['totals']['waiting'])

المرجع