ارسال دستهای
`emails->sendBatch`: تا 100 پیام، با نتیجه به ازای هر مورد.
emails->sendBatch
$invoices = [ ['number' => 'INV-1042', 'email' => '[email protected]'], ['number' => 'INV-1043', 'email' => '[email protected]'],]; $messages = []; foreach ($invoices as $invoice) { $messages[] = [ 'from' => '[email protected]', 'to' => $invoice['email'], 'subject' => 'Invoice ' . $invoice['number'], 'text' => 'Your invoice is attached.', ];} $result = $client->emails->sendBatch($messages, idempotencyKey: 'invoices:2026-09'); echo $result->sent, ' sent, ', $result->failed, ' failed', PHP_EOL; foreach ($result as $item) { if ($item['status'] === 'error') { error_log($item['index'] . ' ' . $item['error']['code'] . ' ' . $item['error']['message']); } else { echo $item['index'], ' ', $item['email']['id'], PHP_EOL; }}sendBatch فهرستی از آرایههای پیام میگیرد که هرکدام دقیقاً همشکل آرایهای است که emails->send میگیرد، و یک OpenEmail\Result\BatchResult برمیگرداند. items آن برای هر پیام یک آرایه دارد، به همان ترتیب، که هرکدام یا ok است با پیامش، یا error است با پاکتی که آن پیام با آن رد میشد، و پیمودن نتیجه با حلقه همینها را میپیماید. هیچچیز بازگردانده نمیشود، پس شمار failed بالاتر از 0 فهرستی برای اقدام است نه دلیلی برای فرستادن دوبارهٔ دسته.
یک کلید idempotency کل دسته را پوشش میدهد و سرور آن را برای هر مورد گسترش میدهد، پس دستهای که دوباره تلاش شود هر پیام را بازپخش میکند، نه اینکه همه را روی اولی جمع کند. وقتی دوباره تلاشش میکنید همان فهرست را به همان ترتیب بفرستید: موردی که جابهجا شده به کلید جایگاه دیگری گره میخورد و بهصورت خطای idempotency_key_reuse برمیگردد.
پیامی که رد شود استثنا پرتاب نمیکند. فقط مشکلی با کل دسته استثنا پرتاب میکند: یک فهرست خالی، بیش از 100 پیام، بیش از 10 پیام دارای translate، شکست کلید یا اسکوپ، یا خطای سرور. خطای سرور در میانهٔ کار پس از رفتن موردهای پیشین رخ میدهد، و کلاینت با همان کلید دوباره تلاشش میکند، که آن موردها را بهجای دو بار فرستادن، بازپخش میکند.
موردها یکی پس از دیگری درون یک درخواست فرستاده میشوند، پس یک دستهٔ بزرگ از ارسالهای فوری بهطور محسوسی بیشتر از یک send طول میکشد. timeout: کلاینت را سخاوتمندانه تنظیم کنید.
پارامترها: emails->sendBatch
emailsarrayالزامی- یک تا 100 پیام، که به شکل `{"emails": [...]}` فرستاده میشوند و یکییکی به همان ترتیب دادهشده پذیرفته میشوند. هرکدام همان پردازشی را میگذراند که `emails->send` دارد، پس گیرندهٔ تنها در فهرست پیچیده میشود، `DateTimeInterface` به یک لحظه تبدیل میشود، بایتهای پیوست کدگذاری میشوند، و موردی که آرایه نباشد پیش از فرستادن هر چیزی `InvalidArgumentException` را پرتاب میکند. یک فهرست خالی، بیش از 100 پیام، یا بیش از 10 پیام دارای `translate`، کل فراخوانی را با یک `validation_error` روی `emails` رد میکند. نبود اسکوپ `emails:send` و `idempotencyKey:` بدشکل هم کل فراخوانی را رد میکنند، پیش از آنکه حتی یک پیام فرستاده شود.
idempotencyKeystring- دسته را در میان فرایندها یکتاسازی میکند. کلاینت در هر حال روی هر فراخوانی کلیدی تازهساخته میچسباند، پس تلاشهای دوبارهٔ خودش هرگز دو بار نمیفرستند، و سرور هر کلیدی را که بگیرد برای هر مورد به شکل `key/0`، `key/1` و همینطور ادامه گسترش میدهد، جداشده با اسلش، نویسهای که کلید خودِ شما اجازهٔ داشتنش را ندارد، تا یک کلید روی صد پیام نتواند همه را روی اولی جمع کند.
apiKeystring- دسته را بهجای کلید کلاینت با این کلید میفرستد.
هر پیام در emails
fromstring or arrayالزامی- فرستنده، به شکل نشانی خام، `Name <addr@host>` یا یک آرایه با `email` و `name`. هیچ فرستندهٔ جایگزینی وجود ندارد و کلید باید اجازهٔ این نشانی را داشته باشد. رد شدن فقط همان یک مورد را شکست میدهد، به شکل یک `permission_error` با کد `from_address_forbidden`.
tostring or arrayالزامی- دستکم یک گیرنده، و اگر یکی تنها بدهید کلاینت آن را در یک فهرست میپیچد. حداکثر 50 نشانی روی هم در `to`، `cc` و `bcc`، که به ازای هر پیام شمرده میشود نه در کل دسته.
ccstring or array- پیشفرض: هیچ، و به همان سقف 50 نشانی شمرده میشود که `to` و `bcc` هم به آن شمرده میشوند.
bccstring or array- پیشفرض: هیچ، و به همان سقف 50 نشانی شمرده میشود. `Bcc` یکی از نامهایی است که `headers` اجازهٔ تنظیمش را ندارد، پس این تنها راه رونوشت پنهان است. شکل هدری، همان پاکتِ بهازایهرگیرنده را که نشانی را پنهان نگه میدارد از بین میبرد.
replyTostring or array- جایی که پاسخها میروند. پس از `headers` اعمال میشود، پس `Reply-To`ای را که آنجا هم گذاشته باشید بازنویسی میکند، نه اینکه دومی اضافه کند.
subjectstring- حداکثر 998 نویسه، همان حد طول خط RFC 5322، با پیشفرض یک رشتهٔ خالی. موضوع خالی، وقتی `template` موضوعی داشته باشد، به موضوع خودِ قالب میافتد.
htmlstring- بخش HTML، حداکثر یک میلیون نویسه، و همان بخشی که وقتی هر دو بدنه داده شوند گیرندگان میبینند. یکی از `html`، `text`، `template` یا `draftId` الزامی است، و موردی که هیچکدام را نداشته باشد با یک `validation_error` روی `html` شکست میخورد.
textstring- بخش متن ساده، حداکثر یک میلیون نویسه. هر دو را میشود فرستاد، و هر حملونقلی در این مسیر از یک رشته یک بدنه میسازد، پس هرجا `html` باشد همان برنده است.
headersarray- فقط `X-*`، `List-*`، Reply-To، Precedence، Auto-Submitted، Importance، Priority و Feedback-ID. هر چیزی که خودِ لایهٔ انتقال تنظیم میکند (From، To، Bcc، Subject، Message-ID و سرآیندهای DKIM و ARC) بهجای حذف بیسروصدا با `reserved_header` رد میشود. مقدارها حداکثر 998 نویسهاند و نمیتوانند CR، LF یا NUL داشته باشند، چون خط دوم یعنی سرآیند دوم.
attachmentsarray- حداکثر 20 فایل به ازای هر پیام، با مجموع 5 MB برای فایلهای درونخطی پس از رمزگشایی، که به ازای هر پیام شمرده میشود نه به ازای دسته. `content` روی سیم base64 است. یک stream از `fopen`، یک `SplFileInfo` یا یک stream از نوع PSR-7 بدهید تا کلاینت آن را بخواند و کدگذاری کند، یا رشتهای که از پیش base64 باشد. یک آرایه فقط با `fileId` فایلی را نام میبرد که از پیش در فضای کاری هست و در سقف درونخطی شمرده نمیشود.
threadIdstring- پاسخدادن درون یک thread موجود، حداکثر 256 نویسه. حملونقل In-Reply-To و References را از روی آن مینویسد، و همین است که باعث میشود پاسخ داخل گفتوگو بنشیند نه کنارش.
draftIdstring- محتوای یک پیشنویس ذخیرهشده را زیر این پاکت بفرستید، حداکثر 256 نویسه. گیرندگان، موضوع و سرآیندهایی که اینجا ساخته میشوند همانهاییاند که روی سیم میروند.
templatearray- یک قالب ذخیرهشده را سمت سرور رندر میکند، با شناسه (`tpl_…`) یا slug، که `version` یک نسخه را سنجاق میکند و `props` و `slots` آن را پر میکنند. یک بار و هنگام پذیرفتهشدن مورد تعیین میشود، و در کنار `html` یا `text` و در کنار `draftId` رد میشود، چون هرکدام از آنها پاسخی دوم به این پرسش است که پیام چه چیزی دارد.
scheduledAtDateTimeInterface or string- یک `DateTimeInterface`، یک لحظهٔ ISO 8601، یا مدتی مانند `PT1H`، دستکم یک ثانیه در آینده و حداکثر 365 روز بعد. رشتهٔ تاریخی بدون ساعت یعنی نیمهشب UTC همان روز. موردها مستقل از هم زمانبندی میشوند، پس یک دسته میتواند صد زمان ارسال متفاوت داشته باشد.
cancellableForSecondsint- پنجرهٔ لغو برحسب ثانیه روی یک ارسال فوری، از 0 تا 900 با پیشفرض 0. هر مقدار بالای 0 در کنار `scheduledAt` روی همان مورد رد میشود، چون پیام زمانبندیشده تا وقتی نرفته از پیش قابل لغو است.
trackingarray- `opens` و `clicks`، که هرکدام اختیاریاند و هرکدام تنظیم را فقط برای همین یک پیام بازنویسی میکنند. کلیدی که ننویسید از نشانیای که پیام از آن فرستاده میشود (یا catch-allی که آن را گرفته) پیروی میکند، که خاموش است مگر همان نشانی روشنش کرده باشد.
tagsarray- حداکثر 10 برچسب، با کلیدهای 1 تا 64 نویسه از میان `A-Za-z0-9_-` و مقدارهای تا 256 نویسه. روی پیام همانطور بازگردانده میشوند و هرگز تفسیر نمیشوند: `emails->list` فقط بر اساس `status:`، `from:`، `broadcastId:` و بازهٔ زمانبندی فیلتر میکند و بس، پس برچسب چیزی است که از روی پیامی که از پیش در دست دارید بخوانید، نه راهی برای یافتنش.
translatearray- این مورد را به زبانی دیگر بفرستید، که در زمان پذیرش تعیین میشود تا کلماتی که تأیید شدهاند همان کلماتی باشند که بیرون میروند. حداکثر 10 مورد در یک دسته میتوانند آن را داشته باشند: هرکدام چند فراخوانی مدل خرج میکند و موردها به ترتیب اجرا میشوند، پس دستهای بزرگتر وسط ارسال قطع میشد. بیش از آن، کل فراخوانی با `too_many_items` روی `emails` رد میشود، پیش از آنکه چیزی فرستاده شود.
پاسخ: OpenEmail\Result\BatchResult
نتیجه فقطخواندنی است، روی items یک IteratorAggregate است و Countable هم هست، پس foreach ($result as $item) موردها را میپیماید و count($result) آنها را میشمارد.
itemsarray- یک آرایه برای هر پیام، به همان ترتیبی که فرستادهاید. هیچچیز بازگردانده نمیشود، پس این سابقهٔ آن است که بر سر هر پیام چه آمد، نه گزارشی دربارهٔ یک تراکنش. API چه همهٔ پیامها پذیرفته شوند، چه بعضی و چه هیچکدام، 207 پاسخ میدهد، پس فراخوانی در هر حال برمیگردد و آنچه باید رویش شاخه بزنید `status` هر مورد است.
sentint or null- چند مورد «پذیرفته» شدهاند، که همان تعداد موردهایی نیست که رفتهاند. یک مورد میتواند `ok` باشد و باز هم `email`ای داشته باشد که `status` آن `failed` یا `partial` است، چون لایهٔ انتقالی که پس از ساخته شدن ردیف پیام را رد کند، نتیجهای از تحویل است نه درخواستی ردشده. فقط وقتی null است که پاسخ شماری نداشته باشد.
failedint or null- چند مورد `error` دارند. شمار بالاتر از 0 فهرستی برای اقدام است نه دلیلی برای فرستادن دوبارهٔ دسته. پیامهای پذیرفتهشده پیش از این رفتهاند.
هر مورد
indexint- جایگاهی که پیامِ این مورد در فهرست فرستادهشده داشت. علاوه بر ترتیب، به شکل یک کلید هم حمل میشود، تا کدی که `items` را فیلتر یا مرتب میکند باز هم بتواند بگوید کدام پیام شکست خورده است.
statusstring- `ok` یا `error`. `ok` حامل `email` است، `error` حامل `error`، و هیچ موردی هر دو را ندارد.
emailarray- پیام پذیرفتهشده، فقط روی مورد `ok`، با همان شکلی که یک ارسال تکی برمیگرداند. `replayed` آن وقتی true است که `Idempotency-Key` مشتقشده با ارسالی که از پیش وجود داشته مطابقت کرده باشد، پس چیز تازهای فرستاده نشده و این همان پیام اصلی است. کلید `tracking` ندارد، چون تعامل بعداً گزارش میشود و در زمان پذیرش چیزی برای گزارش نیست.
errorarray- چرا همین یک پیام رد شد، فقط روی مورد `error`. این همان پاکت خطای API است منهای `docUrl` و `requestId`: آن دو خودِ درخواست را توصیف میکنند و درخواست بهعنوان یک کل موفق بوده است.
خطای یک مورد
typestring- دستهای که باید رویش شاخه بزنید: `validation_error`، `permission_error`، `not_found_error`، `conflict_error` و بقیه. این مجموعه ثابت است و بزرگتر نخواهد شد، برخلاف `code`.
codestring- شکست مشخص: `from_address_forbidden`، `invalid_email_address`، `too_many_recipients`، `reserved_header`، `message_too_large`، `unknown_parameter`. باز و افزودنی است، پس با کدی که نمیشناسید مثل `type` خودش رفتار کنید. اینجا نامش `code` است چون این پاکتِ تجزیهشده است، در حالی که یک استثنا همین مقدار را بهصورت `errorCode` دارد.
messagestring- یک جملهٔ نوشتهشده برای آدم، که مقدار خطاساز را در جایی که وجود دارد نام میبرد. شناسهای پایدار نیست. روی `code` شاخه بزنید.
paramstring- فیلدی که رد شد، به شکل مسیری نقطهدار درون همان یک پیام: `to.0`، `from`، `attachments`. وقتی شکست هیچ فیلدی را نام نبرد غایب است، و هرگز با جایگاه مورد در دسته پیشوند نمیگیرد؛ آن کارِ `index` است.