پرش به مستندات
PHP

ارسال دسته‌ای

`emails->sendBatch`: تا 100 پیام، با نتیجه به ازای هر مورد.

emails->sendBatch

send_batch.php
$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` است.