الجدولة والإلغاء
`scheduledAt` و`emails->reschedule` و`emails->update` و`emails->cancel`.
الإرسال لاحقًا
$message = [ 'from' => '[email protected]', 'to' => '[email protected]', 'subject' => 'Your September invoice', 'text' => 'Invoice attached.',]; $client->emails->send([...$message, 'scheduledAt' => 'PT1H']);$client->emails->send([...$message, 'scheduledAt' => new \DateTimeImmutable('2027-01-01 09:00', new \DateTimeZone('UTC'))]);$client->emails->send([...$message, 'scheduledAt' => '2027-01-01T09:00:00.000Z']);DateTimeInterface، أو لحظة ISO 8601 في صورة سلسلة نصية، أو مدة مثل PT1H أو P2D. حتى سنة واحدة إلى الأمام، ولا يكون في الماضي أبدًا. ونشر رسالة بنيتها سابقًا في مصفوفة جديدة وإلى جانبها scheduledAt يضيف الحقل ويترك الأصل كما هو.
يُرسَل DateTimeInterface كلحظة بتوقيت UTC أيًّا كانت المنطقة الزمنية التي أُنشئ فيها، فالساعة 09:00 في Europe/London تخرج بوصفها اللحظة التي تدل عليها. وسلسلة التاريخ التي لا وقت فيها، مثل 2027-01-01، تُقرأ على أنها منتصف الليل UTC في ذلك اليوم، فمرّر لحظة حين تهمّ الساعة.
النقل والإيقاف
$message = [ 'from' => '[email protected]', 'to' => '[email protected]', 'subject' => 'Your September invoice', 'text' => 'Invoice attached.',]; $queued = $client->emails->send([...$message, 'scheduledAt' => 'PT1H']); $client->emails->reschedule($queued['id'], new \DateTimeImmutable('+1 day'));$client->emails->cancel($queued['id']);لا يمكن إيقاف سوى الرسائل queued وscheduled. وأي رسالة تجاوزت ذلك ترمي ConflictException، لأن جزءًا منها صار بالفعل في صندوق بريد أحدهم. وإلغاء رسالة ملغاة أصلًا ينجح ولا يغيّر شيئًا.
للعثور على ما ينتظر الانطلاق في نافذة زمنية، اعرض القائمة مع status: ['scheduled', 'queued'] وscheduledFrom: وscheduledTo:، كما يفعل تقويم التطبيق.
تغييرها قبل أن تنطلق
يغيّر emails->update رسالة لم تنطلق بعد: موعد انطلاقها عبر scheduledAt، وما تقوله عبر subject وhtml وtext، والعنوان الذي تخرج منه عبر from، ومن تذهب إليهم عبر to وcc وbcc. أرسل أيًّا منها معًا، والحقل الذي تتركه يحتفظ بقيمته. وقائمة المستلمين تستبدل القائمة المخزَّنة كاملة. وهذا ما يفعله تعديل رسالة مجدولة في تقويم التطبيق.
$updated = $client->emails->update('msg_3f9a1c07d2b84e6a9c5b1f20', [ 'subject' => 'Your September invoice, corrected', 'to' => ['[email protected]', '[email protected]'], 'scheduledAt' => new \DateTimeImmutable('2026-10-05 08:00', new \DateTimeZone('UTC')),]); echo $updated['status'], ' ', $updated['subject'], ' ', $updated['scheduledAt'], PHP_EOL;يُفحص from كما يُفحص عند الإرسال، فيجب أن يكون عنوانًا يجوز للمفتاح الإرسال باسمه. والرسالة التي تُرجمت عند قبولها تحتفظ بصياغتها المعتمدة، فأي subject أو html أو text جديد عليها يعطي 409 translation_locked، والرسالة التي شُفّرت قبل جدولتها تحتفظ بصياغتها ومستلميها. ألغِ هذه وأرسلها من جديد بدلًا من ذلك.
نافذة تراجع بدلًا من ذلك
$message = [ 'from' => '[email protected]', 'to' => '[email protected]', 'subject' => 'Your September invoice', 'text' => 'Invoice attached.',]; $held = $client->emails->send([...$message, 'cancellableForSeconds' => 30]); echo $held['status'], ' ', $held['cancellableUntil'], PHP_EOL;الرسالة المجدولة قابلة للإلغاء أصلًا حتى تنطلق، فلا يمكن الجمع بين الاثنين، والخادم يرفض ذلك. استخدم هذا الخيار لنافذة تراجع عن الإرسال في رسالة فورية.
المعاملات: الجدولة
scheduledAtDateTimeInterface or string- متى تُرسل الرسالة، في `emails->send`: `DateTimeInterface`، أو لحظة ISO 8601 في صورة سلسلة نصية، أو مدة مثل `PT1H` أو `P2D`. ويُرسَل `DateTimeInterface` كلحظة UTC، والسلسلة النصية كما هي، وسلسلة التاريخ التي لا وقت فيها تعني منتصف الليل UTC. على الأقل بعد ثانية من الآن وبحد أقصى 365 يومًا، وكلا الحدين يعطي `validation_error` على `scheduledAt`، واللغة الطبيعية غير مقبولة، لأن تحليل «الثلاثاء القادم» تحليلًا خاطئًا يرسل رسالة في وقت لا يمكن التراجع عنه.
cancellableForSecondsint- نافذة تراجع عن الإرسال على إرسال فوري: عدد صحيح من 0 إلى 900، والافتراضي 0. وأي قيمة فوق 0 تُرفض مع `scheduledAt`، الذي يكون قابلًا للإلغاء أصلًا حتى ينطلق، والرسالة المحتجزة بهذه الطريقة تبقى عند `queued` لا `scheduled`. فهي آلية التأجيل نفسها بتأخير قصير.
$idstringمطلوب- المعرّف `msg_`، وهو الوسيط الأول لـ `emails->cancel` و`emails->reschedule` و`emails->update`. وتحتاج هذه إلى `emails:send` لا إلى نطاق خاص بها، وتبحث عن المعرّف داخل مساحة عمل المفتاح نفسها، فمعرّف يخص مساحة أخرى يعطي `not_found_error` تمامًا كمعرّف لم يوجد قط.
$scheduledAtDateTimeInterface or stringمطلوب- الوقت الجديد، كوسيط ثانٍ لـ `emails->reschedule`، يُقرأ بالقواعد نفسها وفي نافذة السنة نفسها. وهو الشيء الوحيد الذي يغيّره `reschedule`، ولا يرسل العميل شيئًا غيره. والمدة نسبية إلى لحظة قراءة الخادم لها، فإعادة الجدولة المُعادة تحط بعد الأولى بقليل: بعدها لا قبلها أبدًا.
apiKeystring- وسيط مسمّى في أيٍّ من الاستدعاءات الثلاثة. يعمل بهذا المفتاح بدل مفتاح العميل.
الاستجابة
يعيد كلٌّ من cancel وreschedule وupdate الرسالة كاملة في صورة مصفوفة مفاتيحها أسماء API بصيغة camelCase.
objectstring- دائمًا `email`. تجيب هذه الاستدعاءات بالرسالة كاملة لا بمجرد إقرار، فلا حاجة إلى جلب شيء مجددًا لمعرفة ما تغيّر. ويعيد `emails->send` الشكل نفسه مع `replayed`.
idstring- المقبض `msg_`. ثابت طوال عمر الرسالة، وهو المعرّف الذي يأخذه كل استدعاء آخر عليها.
statusstring- تكون `cancelled` بعد الإلغاء و`scheduled` بعد إعادة الجدولة، بما في ذلك رسالة كانت `queued` فقط خلف نافذة تراجع، فإعادة الجدولة تحوّلها إلى جدولة حقيقية. ولا يمكن نقل أو إيقاف سوى الرسائل في الحالتين `queued` و`scheduled`. وأي شيء تجاوز ذلك يرمي `ConflictException` قيمة `errorCode` فيه `email_not_cancellable`، لأن جزءًا منه صار في صندوق بريد أحدهم بالفعل.
scheduledAtstring or null- لحظة ISO 8601 المقرر أن تُرسل فيها الرسالة. تُضبط لنافذة التراجع كما تُضبط لإرسال `scheduledAt`، لأنهما آلية واحدة، وتكون null في الإرسال الفوري العادي.
cancellableUntilstring or null- متى يتوقف الإلغاء عن العمل، وهي اللحظة نفسها التي تحملها `scheduledAt` في كلا المسارين المؤجَّلين. وتكون null في إرسال فوري يكون قد انطلق بالفعل قبل أن يعود الاستدعاء.
sentAtstring or null- متى غادرت الرسالة فعلًا. null ما دامت تنتظر، وnull إلى الأبد على الرسالة الملغاة.
messageIdstring or null- ترويسة Message-ID بحسب RFC 5322، وتكون null إلى أن توجد رسالة MIME، فهي دائمًا null على الرسائل التي يمكن لهذه الاستدعاءات أن تعمل عليها. وليست شيئًا تخاطب به API، ولا ما يعود به أي ارتداد لاحق أيضًا: فخدمة الإرسال تعيد كتابة الترويسة عند الخروج.
threadIdstring or null- المحادثة التي تنتمي إليها هذه الرسالة، مأخوذة من الطلب ومُعاد كتابتها بما يبلّغ عنه النقل بمجرد الإرسال. وتكون null عندما لا تكون الرسالة ردًا.
transportstring or null- كيف غادرت البايتات، وnull حتى الإرسال الفعلي، فهي null على كل رسالة يمكن أن يعيدها إلغاء أو إعادة جدولة. والإرسال في وضع الاختبار يسجّل `test`، وقد تظهر وسيلة نقل لا تسمّيها هذه الحزمة بعد، فعامل القيمة المجهولة كمعلومة لا كخطأ.
attemptsint- كم مرة طالب الإرسال بهذا السجل. تزداد مع كل مطالبة لا مع إرسال ناجح، وتكون 0 لأي شيء ما زال ينتظر.
lastErrorstring or null- آخر فشل سُجّل على الرسالة، وnull ما دام لم يفشل شيء. والإرسال المؤجَّل الذي تعذّر إدراج مهمته في الطابور يُكتب هنا بالشكل `Could not schedule: …` ويُنقل إلى `failed`، وهو السبيل الوحيد الذي تتوقف به رسالة مجدولة عن كونها قابلة للإلغاء دون أن يطلب أحد ذلك.
fromstring- العنوان الذي أُذن للرسالة أن تخرج منه: `from` الذي أُرسل، مخزَّنًا مجردًا بأحرف صغيرة. ويُحذف أي اسم معروض هنا، لأن مرشِّح `from:` في `emails->list` يقارن بالمساواة.