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

الأخطاء

كل إخفاق يرفع استثناءً. صنفان اثنان، ومعرّف طلب على كل خطأ من API.

التقاط خطأ

catch_errors.py
from openemail import OpenEmailApiError, OpenEmailNetworkError, openemail try:    openemail.emails.send({'from': sender, 'to': recipient, 'subject': subject, 'text': text})except OpenEmailApiError as error:    if error.is_validation:        print(error.code, error.param, error.message)     if error.is_permission:        print(openemail.addresses.list())     if error.is_rate_limited:        print('try again in', error.retry_after_seconds, 'seconds')     print(error.status, error.request_id)     raiseexcept OpenEmailNetworkError as error:    if error.is_timeout:        print('no answer in time')     raise

الخطأ permission_error عند الإرسال يعود عادةً إلى نطاق الإرسال الخاص بالمفتاح، أي نطاق أو عنوان لم يُمنح له، لا إلى مساحة العمل، ولهذا يطبع المثال ما تقوله addresses.list() عن العناوين التي يجوز لهذا المفتاح الإرسال باسمها.

الأصناف

الصنفمتى
OpenEmailApiErrorاستجاب API، ولم يكن الرد نجاحًا. يحمل message وstatus وtype وcode وparam وdoc_url وrequest_id وretry_after_seconds وfields وbody.
OpenEmailNetworkErrorلم تصل أي استجابة: DNS أو TLS أو اتصال انقطع أو انتهاء المهلة. يحمل cause، وهو استثناء httpx الكامن تحته، وتكون is_timeout بقيمة True عندما يكون انتهاء المهلة هو السبب.
OpenEmailErrorالصنف الأساسي لكليهما، فكتلة except واحدة تلتقط كل إخفاق سببه API أو الشبكة. وWebhookVerificationError، الذي يرفعه verify_webhook_signature، يرث منه أيضًا.
ValueErrorيُرفع قبل إرسال أي شيء: مفتاح مفقود أو مشوّه، أو base_url غير صالح للاستخدام، أو بيانات اعتماد متجهة إلى http غير مشفّر، أو معرّف فارغ. أما http_client الخاطئ، أو جسم طلب لا يستطيع JSON حمله، فيرفع TypeError بدلًا من ذلك.

يسرد fields كل إجابة رفضها نموذج الاشتراك، في صورة key وerror، ويكون None في كل خطأ آخر. ويحتفظ body بـ JSON الذي أرسله API، أو يكون None حين لا يكون جسم الاستجابة JSON.

الخاصيةتكون true عندما
is_authتكون type بقيمة authentication_error، أي 401: لا مفتاح، أو نوع اعتماد خاطئ، أو مفتاح لم نُصدره.
is_permissionpermission_error، أي 403: مفتاح حقيقي ينقصه النطاق أو عنوان From الذي يحتاجه.
is_scope_missingتكون code بقيمة insufficient_scope، وهو الخطأ 403 الذي يسمّي نطاقًا مفقودًا.
is_invalid_requestinvalid_request_error، أي 400: طلب تعذّر فهمه. أما الرسالة التي تتجاوز سقف الحجم فتعود بالخطأ 422 message_too_large، ولذا فإن is_validation هي الخاصية التي تلتقطها.
is_validationvalidation_error، أي 422: رفضه المخطط، وparam تسمّي الحقل.
is_not_foundnot_found_error، أي 404: لا وجود لهذا المورد.
is_conflictconflict_error، أي 409: تجاوز المورد النقطة التي كان يمكن عندها تنفيذ هذا عليه.
is_rate_limitedrate_limit_error، أي 429. وتحمل retry_after_seconds مدة الانتظار عندما يحدّدها الخادم.
is_server_errorتكون status بقيمة 500 أو أعلى. اذكر request_id إن تواصلت مع الدعم.
is_retryableتكون status بقيمة 408 أو 429 أو 500 أو 502 أو 503 أو 504.
is_step_up_requiredcode هو step_up_required، أي الـ 403 الذي يتلقاه رمز وصول OAuth قبل تغيير حساس إلى أن يتحقق الشخص من رمز.

تقرأ معظم الخصائص الحقل type، وهو النصف المجمَّد من الغلاف. أما code فيبقى str، لأن API يضمن أنه مفتوح وتراكمي، فعامِل أي قيمة لا تعرفها معاملة type الخاص بها. وLiteral المغلق كان سيجعل ترقية SDK ثمنًا لقراءة وضع إخفاق جديد.

المتن الذي لا يطابق غلاف الخطأ الخاص بـ API يصبح مع ذلك OpenEmailApiError، مع استنتاج type من رمز الحالة وضبط code على unrecognised_response. والاستجابة الناجحة التي ليس متنها JSON ترفع الخطأ نفسه.

إلغاء استدعاء على AsyncOpenEmail لا يرفع أي OpenEmailError. بل ينتشر الإلغاء نفسه، سواء وقع أثناء الطلب أو أثناء الانتظار قبل إعادة المحاولة، ولا يُعاد أي شيء بعده.

request_id

يحمل كل OpenEmailApiError معرّف الطلب الذي أرسله الخادم، من متن الخطأ أو من الترويسة x-request-id، وهو الشيء الوحيد الذي يربط إخفاقك بسطر في سجل الخادم. أما الاستجابة الناجحة فتعيد المتن المحلَّل وحده، فلا يوجد فيها معرّف طلب لقراءته.

ينتهي str(error) برمز الحالة ورمز الخطأ ومعرّف الطلب، فسطر السجل الذي يطبع الاستثناء يحتفظ بالثلاثة كلها. ويصمد OpenEmailApiError أيضًا أمام التسلسل بـ pickle بكل حقوله، فالخطأ الذي يُرفع في عملية عاملة يصل إلى العملية الأم سليمًا.