إرسال البريد وتتبّعه
أرسل البريد وأرسله دفعات وترجمه وجدوله وألغه بأوامر `emails`، ثم تابع تسليمه ومرات فتحه ونقراته بـ `tracking`.
نظرة عامة
مساحة الأسماء emails هي واجهة الإرسال في صورة أوامر، أمر لكل طريقة من طرق openemail.emails في SDK. يستدعي كل منها نقطة نهاية واحدة ويطبع ما تعيده. ومساحة الأسماء tracking تقرأ مرات الفتح والنقرات على البريد الذي أرسلته. ويعمل openemail email بدلًا من openemail emails.
كل أمر هنا يحتاج إلى تسجيل دخول، عبر المتصفح أو بمفتاح API، وإلى أحد نطاقَي صلاحية: emails:send للإرسال والترجمة والإلغاء وإعادة الجدولة، وemails:read لكل ما يقتصر على القراءة.
أي أمر إرسال تستخدم
openemail send هو الأمر المكتوب يدويًا في صفحة البريد، وهو يرسل عبر emails send. صُمّم لشخص يعمل على الطرفية: يختار عنوان الإرسال حين تُغفل --from، ويقرأ النص من ملف أو من stdin أو من محرّرك، ويرفق الملفات بمساراتها، ويعرض ملخصًا لتؤكده قبل أن يُرسل أي شيء. أما openemail emails send فيأخذ جسم الطلب في صورة خيارات، خيار لكل حقل، ولا يسأل عن شيء، وهذا يناسب سكربتًا يعرف بالضبط ما يرسله.
| send | emails send |
|---|---|
| --from <address> | مطلوب، مثل --to، ما لم يتضمنه --data. ويمكن لـ send أن يُغفله ويختار لك عنوانًا |
| -f, --body-file <path> | لا يوجد خيار ملف للنص. مرّر --html "$(cat body.html)"، أو الطلب كله في --data @email.json |
| -a, --attach <path> | --attachments، مصفوفة JSON من الملفات، لكل منها filename وcontent بترميز base64، أو fileId لملف موجود بالفعل في الملفات |
| --at <when> | --scheduled-at <when>، لحظة بصيغة ISO 8601 أو مدة مثل PT1H أو P2D. ويقبل send أيضًا مهلًا قصيرة مثل 10m و2h و1d |
| --undo <seconds> | --cancellable-for-seconds <n>، من 0 إلى 900 |
| --translate <language> | --translate '{"to":"de"}'، ويقبل أيضًا from وincludeOriginal وsubject |
| --template <id> --props <json> | --template '{"id":"welcome","props":{"name":"Ada"}}'، ويمكنه أيضًا تثبيت version |
| --draft <id> | --draft-id <id> |
| --thread <id> | --thread-id <id> |
| --tag <key=value> | --tags <key=value>، مكررًا، أو كائن JSON |
وحده emails send يملك --tracking لإيقاف تتبع الفتح أو النقر لإرسال واحد، و--signature، و--headers للترويسات المخصصة، و--attachment-delivery للاختيار بين إرفاق الملفات والربط إليها، و--data للجسم كله بصيغة JSON، مضمّنًا، أو من ملف عبر @path، أو من stdin عبر -.
ينتهي الاثنان بطريقة مختلفة. يخرج send بالرمز 1 حين يعود البريد بالحالة failed. أما emails send فيخرج بالرمز 0 كلما أجابت API، لذا افحص status فيما يطبعه.
كل أوامر emails
تحتاج send وsend-batch وtranslate وcancel وreschedule إلى emails:send. وتحتاج list وget وlist-events وget-tracking إلى emails:read. ومعرّف البريد هو msg_ يليه 24 حرفًا ست عشريًا، كما يعيده الإرسال.
| الأمر | ما تفعله |
|---|---|
| openemail emails send --from <value> --to <a,b> | أرسل بريدًا واحدًا الآن، أو احتجزه لنافذة تراجع عبر --cancellable-for-seconds، أو جدوله عبر --scheduled-at. النص هو --html أو --text أو كلاهما، أو --template محفوظ، أو --draft-id محفوظة |
| openemail emails send-batch <emails> | أرسل حتى 100 بريد مستقل في طلب واحد، من مصفوفة JSON في ملف، أو مضمّنة، أو على stdin عبر -. كل عنصر على شكل جسم emails send، وينجح أو يفشل وحده |
| openemail emails translate --to <value> | عاين ما سيسلّمه إرسال مترجَم، لـ --subject أو --html أو --text. لا يُخزَّن شيء ولا يُرسَل، ويستهلك إجراء ذكاء اصطناعي واحدًا |
| openemail emails list | صفحة واحدة من الرسائل المرسلة، الأحدث أولًا، مضيَّقة بـ --status أو --from أو --broadcast-id |
| openemail emails get <id> | بريد مرسل واحد مع حالة كل مستلم وخطئه ووقت تسليمه، وتقرير التتبع الكامل إن كان متتبَّعًا |
| openemail emails list-events <id> | سلسلة أحداث إرسال واحد، الأقدم أولًا: القبول، والجدولة، والإرسال، والتسليم، والارتداد، والشكوى، والفتح، والنقر، وغيرها |
| openemail emails get-tracking <id> | تقرير التفاعل لإرسال واحد: مجاميعه، ومدخلة لكل نسخة متتبَّعة، وكل رابط أُعيدت كتابته مع نقراته |
| openemail emails cancel <id> | أوقف بريدًا في الطابور أو مجدولًا قبل أن يُرسل. يطلب منك التأكيد |
| openemail emails reschedule <id> <scheduled-at> | انقل بريدًا في الطابور أو مجدولًا إلى لحظة بصيغة ISO 8601، أو مدة مثل PT30M، من ثانية واحدة إلى 365 يومًا من الآن |
كل أوامر tracking
تحتاج الخمسة كلها إلى emails:read. وتقبل tracking get وlist-opens وlist-clicks أيًّا من معرّفَي الرسالة: معرّف msg_ الذي أعاده إرسالها، أو معرّف التتبع tmsg_ الذي تحمله tracking list وحمولات خطافات الويب.
| الأمر | ما تفعله |
|---|---|
| openemail tracking list | صفحة واحدة من الرسائل المتتبَّعة المرسلة ضمن فترة، الأحدث أولًا، لكل منها تقريرها الكامل. يضيّقها --opened و--clicked، ويُبقي --no-opened تلك التي لم يفتحها أحد. الفترة 30 يومًا ما لم يحدد --days أو --minutes غير ذلك |
| openemail tracking get-stats | الأرقام التي تقف وراء لوحة التفاعل: الرسائل المتتبَّعة والمفتوحة والمنقور عليها، ومعدلات الفتح والنقر، وسلسلة زمنية في فترات --grain، وأعلى الروابط وبرامج البريد والبلدان |
| openemail tracking get <id> | تقرير التفاعل لرسالة واحدة، وهو المستند نفسه الذي يعيده emails get-tracking |
| openemail tracking list-opens <id> | مرات الفتح الفردية وراء عدد فتح الرسالة، الأحدث أولًا، كل منها معلَّم بـ human أو proxy أو machine. ويضيف --include-machine الزيارات التي لم تُحتسب |
| openemail tracking list-clicks <id> | النقرات الفردية على روابط رسالة، الأحدث أولًا، مع url الأصلي لكل منها. ويضيف --include-machine ماسحات الروابط والتكرارات المدمجة |
يغطي tracking list وget-stats كل رسالة متتبَّعة أرسلها صندوق البريد، بما فيها البريد المكتوب في تطبيق الويب والبريد المرسل عبر أدوات MCP أو المساعد، بينما يضم emails list سجلات الإرسال التي أنشأتها API. والتقرير الذي لا سجل إرسال له تكون فيه sendId مضبوطة على null.
أمثلة
أرسل من سكربت بمفتاح لاتكرارية خاص بك. تشغيله مرة أخرى بنفس --idempotency-key يطبع البريد الأول مع replayed: true بدلًا من إرسال بريد ثانٍ.
openemail emails send \ --from 'Acme Billing <[email protected]>' \ --to [email protected] \ --subject 'Your September invoice' \ --html '<p>The invoice is attached. Tell me if anything on it looks wrong.</p>' \ --attachments '[{"fileId":"file_6bb640f5b99e47deb758f1f5"}]' \ --tracking '{"opens":false}' \ --idempotency-key invoice:inv_2026_09_4192 \ --json | jq -r '.id + " " + .status'اجعل شخصًا يقرأ الترجمة قبل إرسالها. أرسل الصياغة المعتمدة في --subject و--html عاديين، دون --translate، وإلا تُرجمت مرة ثانية. ويحمل html المترجَم نصك الأصلي أسفله بالفعل، ما لم تمرّر --no-include-original.
openemail emails translate --to de \ --subject 'Your September invoice' \ --html "$(cat invoice.html)" \ --json > preview.jsonjq -r .html preview.jsonopenemail emails send --from [email protected] --to [email protected] \ --subject "$(jq -r .subject preview.json)" \ --html "$(jq -r .html preview.json)"أرسل دفعة من ملف. يخرج الأمر بالرمز 0 كلما عولجت الدفعة، حتى إن فشلت بعض العناصر، لذا اقرأ failed وstatus لكل عنصر. وتشغيله مرة أخرى بالمفتاح نفسه يعيد تشغيل العناصر التي أُرسلت ويرسل الباقي فقط، ما دامت المصفوفة محافظة على ترتيبها.
[ { "from": "[email protected]", "to": "[email protected]", "subject": "Receipt 4192", "text": "Thanks for your order." }, { "from": "[email protected]", "to": "[email protected]", "subject": "Receipt 4193", "text": "Thanks for your order." }]openemail emails send-batch receipts.json --idempotency-key receipts:2026-09-27 --json > result.jsonjq '{ sent, failed }' result.jsonjq -r '.items[] | select(.status == "error") | "\(.index) \(.error.code)"' result.jsonجدول بريدًا، ثم انقله، ثم ألغه. يجيب --yes عن التأكيد الذي يطلبه cancel، وهو ما لا يستطيعه السكربت.
ID=$(openemail send --from [email protected] --to [email protected] --subject "Standup notes" \ --body-file notes.md --at 2026-10-01T09:00:00Z --json | jq -r .id)openemail emails reschedule "$ID" 2026-10-01T13:00:00Zopenemail emails get "$ID" --json | jq -r '.status + " " + .scheduledAt'openemail emails cancel "$ID" --yesاعثر على عمليات الإرسال التي فشلت واقرأ ما حدث لإحداها. حين يُمرَّر الناتج عبر أنبوب دون --json، يطبع --all كائن JSON واحدًا في كل سطر.
openemail emails list --status failed,partial --from [email protected] --all | jq -r .idopenemail emails get msg_3f9a1c07d2b84e6a9c5b1f20openemail emails list-events msg_3f9a1c07d2b84e6a9c5b1f20 --all --json | jq -r '.items[] | .createdAt + " " + .type'اقرأ أسبوعًا من التفاعل بأيام تنقسم عند منتصف الليل بتوقيت UTC+2، واسرد ما لم يفتحه أحد، واحسب النقرات على كل رابط في رسالة واحدة.
openemail tracking get-stats --days 7 --offset-minutes 120 --json | jq '{ tracked, openRate, clickRate }'openemail tracking list --no-opened --days 7 --all | jq -r .subjectopenemail tracking list-clicks msg_3f9a1c07d2b84e6a9c5b1f20 --all | jq -r .url | sort | uniq -cالنطاقات والرموز والتأكيدات
- يطلب تسجيل الدخول عبر المتصفح نطاقات الصلاحية في صفحة الموافقة، ويحدد
openemail login --scopes emails:send,emails:readالاثنين مسبقًا. والأمر الذي ينقصه نطاقه يتوقف برمز الخروج4وinsufficient_scope، ويسمّي النطاق. send --attachمع ملفات تتجاوز 5 MB يرفعها إلى الملفات أولًا، وهذا يحتاج أيضًا إلىfiles:write.- لا يطلب أي من هذه الأوامر رمز تحقق، لذا يشغّلها تسجيل الدخول عبر المتصفح كما يشغّلها مفتاح API.
- يسأل
emails cancelقبل أن يلغي، ويجيب--yesعنك. ومن دون إشراف ودون--yesيتوقف بالرسالةRefusing to run unattended. Pass --yes to confirm.ورمز الخروج2. - لا يسأل
emails sendوsend-batchوrescheduleأبدًا. أماsendفيعرض ملخصًا ولا يسأل إلا في طرفية، و--yesيتخطى ذلك أيضًا. - يطبع
--dry-runالطلب الذي كان الأمر سيرسله، ولا يرسل شيئًا، ويخرج بالرمز0. وفيemails translateلا يستهلك أي إجراء ذكاء اصطناعي، وفيemails cancelلا يسأل عن شيء.
صفحات النتائج
تقرأ emails list وemails list-events وtracking list وlist-opens وlist-clicks صفحة واحدة. يحدد --limit حجمها، من 1 إلى 100 مع 25 افتراضيًا لقائمتي emails، ومن 1 إلى 200 مع 50 افتراضيًا لقوائم tracking الثلاث. ويواصل --cursor من المؤشر الذي طبعته الصفحة.
- يقرأ
--allكل صفحة ويبث العناصر: جدولًا في الطرفية، وكائن JSON واحدًا في كل سطر عند التمرير عبر أنبوب أو مع--ndjson. - يتوقف
--max <n>بعد هذا العدد من العناصر، ويتضمن--all. - يطبع
--jsonمستند{ items, hasMore, nextCursor }واحدًا، ومع--allكذلك. - التصفح بالمؤشر لا بالإزاحة، فالبريد المرسل أثناء تصفحك لا يزيح صفًا ولا يكرره أبدًا.
ما يجدر معرفته
- كل تشغيل ينشئ مفتاح لاتكرارية خاصًا به، يغطي إعادات المحاولة داخل ذلك التشغيل. وتشغيل الإرسال مرتين يرسل مرتين، ما لم يمرّر التشغيلان
--idempotency-keyنفسه. والمفتاح نفسه مع جسم مختلف يُرفض بـidempotency_key_reuseورمز الخروج7. - لا يمكن إلغاء أو نقل إلا البريد
queuedوscheduled. والإرسال الفوري بلا نافذة تراجع يخرج داخل الطلب نفسه، فحين يصبح معرّفه بين يديك يكون الوقت قد فات عادةً، وينتهي الاستدعاء بـemail_not_cancellableورمز الخروج6. - البريد الملغى يبقى ملغى. وإعادة الجدولة تغيّر الوقت فقط، ويُحسب للمدة من لحظة استلام الخادم للطلب، فلتغيير النص ألغِ ثم أرسل من جديد.
- الترجمة التي يتعذر إنتاجها ترفض الإرسال كله، ولا يخرج شيء دون ترجمة. والدفعة المترجمة تضم 10 رسائل على الأكثر تحمل
translate. - حصة الإرسال المستنفدة توقف الإرسال بـ
send_quota_exceededحتى أول الشهر، وحصة الذكاء الاصطناعي المستنفدة توقف الترجمة بـai_quota_exceededحتى منتصف الليل بتوقيت UTC، وكلاهما برمز الخروج8. - البريد المرسل بمفتاح
oe_test_لا يُسلَّم أبدًا. تظهر حالتهsent، معtransportمضبوطًا علىtest، ولا يُتتبَّع أبدًا. - يجيب
emails get-trackingوtracking getبـ 404، ورمز الخروج5، لرسالة لم تحمل بكسلًا ولا رابطًا معاد الكتابة، لأن عدم التتبع ليس كعدم الفتح. ويتبع التتبع الإعداد الذي أُرسلت به الرسالة، فتفعيله لاحقًا لا يصل إلى البريد السابق. - كل عدد هو حد أدنى. القارئ الذي يحجب برنامج بريده الصور لا يُحتسب فتحًا أبدًا، والنقرة دليل على القراءة أقوى من الفتح.
- يجيب
list-opensوlist-clicksبـ 404 لمعرّفmsg_لا شيء متتبَّع فيه، لكنهما يأخذان معرّفtmsg_كما هو، فيعود المعرّف المجهول قائمة فارغة. - المفتاح المقيّد ببعض العناوين لا يرى إلا البريد المرسل من تلك العناوين، والمفتاح الذي يحمل نطاقًا كاملًا يغطي كل عنوان فيه.
كل الخيارات
تذكر هذه الصفحة الخيارات الأهم. ويسرد openemail <command> --help كل وسيط وخيار يأخذه الأمر، بنوعه، والنطاق الذي يحتاجه، وطريقته ومساره، وما يعيده، والملاحظات من مرجع API. أضف --json لتحصل على المساعدة نفسها في مستند JSON واحد.
openemail emails --helpopenemail emails send --helpopenemail tracking list-opens --help --json