batch भेजें
`emails.send_batch`: 100 संदेशों तक, हर आइटम का अलग नतीजा।
emails.send_batch
invoices = [ {number: "INV-1042", email: "[email protected]"}, {number: "INV-1043", email: "[email protected]"}] messages = invoices.map do |invoice| {from: "[email protected]", to: invoice[:email], subject: "Invoice #{invoice[:number]}", text: "Your invoice is attached."}end result = client.emails.send_batch(messages, idempotency_key: "invoices:2026-09") puts "#{result.sent} sent, #{result.failed} failed" result.items.each do |item| if item[:status] == "error" warn "#{item[:index]} #{item.dig(:error, :code)} #{item.dig(:error, :message)}" else puts "#{item[:index]} #{item.dig(:email, :id)}" endendsend_batch संदेश Hashes की एक Array लेता है, हर एक बिल्कुल emails.send की बॉडी जैसा, और एक OpenEmail::BatchResult लौटाता है। इसके items में हर संदेश के लिए क्रम से एक Hash होता है, हर एक या तो अपने संदेश के साथ ok या उस envelope के साथ error जिससे वह संदेश अस्वीकार होता। कुछ भी वापस नहीं लिया जाता, इसलिए 0 से ऊपर की failed गिनती बैच को दोबारा भेजने का कारण नहीं, बल्कि कार्रवाई करने की सूची है।
एक idempotency कुंजी पूरे बैच को कवर करती है और सर्वर उसे हर आइटम के लिए आगे बढ़ाता है, इसलिए दोबारा आज़माया गया बैच हर संदेश को replay करता है, उन सबको पहले वाले पर नहीं समेटता। पुनः प्रयास करते समय वही Array उसी क्रम में भेजें: जो आइटम खिसक गया वह दूसरी जगह की कुंजी से जुड़ जाता है और idempotency_key_reuse error के रूप में लौटता है।
अस्वीकृत संदेश raise नहीं करता। सिर्फ़ पूरे बैच की समस्या raise करती है: ख़ाली Array, 100 से ज़्यादा संदेश, translate वाले 10 से ज़्यादा संदेश, कुंजी या scope की विफलता, या सर्वर की ख़राबी। बीच में आई सर्वर की ख़राबी पहले के आइटम जा चुकने के बाद आती है, और क्लाइंट उसी कुंजी से उस पर पुनः प्रयास करता है, जो उन आइटम को दो बार भेजने के बजाय replay करता है।
आइटम एक ही रिक्वेस्ट के अंदर एक के बाद एक भेजे जाते हैं, इसलिए तुरंत वाले sends का बड़ा बैच एक send से काफ़ी ज़्यादा समय लेता है। क्लाइंट का timeout: उदार रखें।
पैरामीटर: emails.send_batch
emailsArray<Hash>आवश्यक- एक से 100 संदेश, `{"emails": [...]}` के रूप में भेजे जाते हैं और दिए गए क्रम में एक-एक करके स्वीकार होते हैं। हर एक `emails.send` जैसी ही प्रक्रिया से गुज़रता है, इसलिए अकेला प्राप्तकर्ता लपेटा जाता है, Time एक क्षण बन जाता है और अटैचमेंट के बाइट्स एन्कोड होते हैं। ख़ाली Array, 100 से ज़्यादा, या `translate` वाले 10 से ज़्यादा संदेश पूरी कॉल को `emails` पर `validation_error` के साथ अस्वीकार कर देते हैं। ग़ायब `emails:send` scope और ग़लत बनी `idempotency_key:` भी पूरी कॉल को अस्वीकार कर देते हैं, एक भी संदेश भेजे जाने से पहले।
idempotency_keyString- प्रोसेस के पार बैच का दोहराव हटाता है। क्लाइंट हर हाल में हर कॉल पर एक नई बनी कुंजी जोड़ता है, ताकि उसके अपने पुनः प्रयास कभी दो बार न भेजें, और सर्वर उसे मिली कुंजी को हर आइटम के लिए `key/0`, `key/1` इत्यादि के रूप में आगे बढ़ाता है, slash से अलग किया हुआ, ऐसा वर्ण जो आपकी अपनी कुंजी में नहीं हो सकता, ताकि सौ संदेशों पर एक कुंजी उन सबको पहले वाले पर न समेट सके।
api_keyString- क्लाइंट की कुंजी के बजाय इस कुंजी से बैच भेजता है।
emails में हर संदेश
fromString or Hashआवश्यक- प्रेषक, सादे पते, `Name <addr@host>` या `email` और `name` वाले Hash के रूप में। कोई फ़ॉलबैक प्रेषक नहीं है और कुंजी को इस पते की अनुमति होनी चाहिए। अस्वीकार होने पर सिर्फ़ वह एक आइटम विफल होता है, `from_address_forbidden` कोड वाले `permission_error` के रूप में।
toString, Hash or Arrayआवश्यक- कम से कम एक प्राप्तकर्ता, और अकेले को क्लाइंट एक Array में लपेट देता है। `to`, `cc` और `bcc` मिलाकर अधिकतम 50 पते, जो पूरे बैच में नहीं बल्कि हर संदेश के हिसाब से गिने जाते हैं।
ccString, Hash or Array- डिफ़ॉल्ट रूप से कोई नहीं, और यह `to` तथा `bcc` वाली उसी 50-पतों की कुल सीमा में गिना जाता है।
bccString, Hash or Array- डिफ़ॉल्ट रूप से कोई नहीं, और यह उसी 50-पतों की कुल सीमा में गिना जाता है। `Bcc` उन नामों में से एक है जिन्हें `headers` सेट नहीं कर सकता, इसलिए blind-copy का यही एकमात्र तरीक़ा है। header वाला रूप उस प्रति-प्राप्तकर्ता लिफ़ाफ़े को उलट देता जो पते को छिपाए रखता है।
replyToString or Hash- उत्तर कहाँ जाएँ। यह `headers` के बाद लागू होता है, इसलिए वहाँ सेट किया गया `Reply-To` दूसरा जोड़ने के बजाय इससे बदल जाता है।
subjectString- अधिकतम 998 वर्ण, जो RFC 5322 की पंक्ति सीमा है, और डिफ़ॉल्ट एक ख़ाली String है। जब `template` विषय देता है तो ख़ाली विषय टेम्पलेट के अपने विषय पर चला जाता है।
htmlString- HTML हिस्सा, अधिकतम दस लाख वर्ण, और दोनों body दिए जाने पर प्राप्तकर्ता इसी को देखते हैं। `html`, `text`, `template` या `draftId` में से एक ज़रूरी है, और जिस आइटम में इनमें से कोई न हो वह `html` पर `validation_error` के रूप में विफल होता है।
textString- सादा-टेक्स्ट हिस्सा, अधिकतम दस लाख वर्ण। दोनों भेजे जा सकते हैं, और इस रास्ते का हर transport एक String से एक बॉडी बनाता है, इसलिए जहाँ `html` हो वहाँ वही जीतता है।
headersHash- सिर्फ़ `X-*`, `List-*`, Reply-To, Precedence, Auto-Submitted, Importance, Priority और Feedback-ID। transport जो कुछ ख़ुद सेट करता है (From, To, Bcc, Subject, Message-ID, DKIM और ARC हेडर) उसे चुपचाप हटाने के बजाय `reserved_header` के रूप में अस्वीकार किया जाता है। मान अधिकतम 998 वर्ण के होते हैं और उनमें CR, LF या NUL नहीं हो सकते, क्योंकि दूसरी पंक्ति यानी दूसरा हेडर।
attachmentsArray<Hash>- हर संदेश में अधिकतम 20 फ़ाइलें, डिकोड होने के बाद इनलाइन फ़ाइलें कुल 5 MB, हर संदेश के हिसाब से गिनी जाती हैं, बैच के हिसाब से नहीं। नेटवर्क पर `content` base64 है। बाइट्स को binary String, IO या Pathname के रूप में पास करें और क्लाइंट उन्हें एन्कोड कर देता है। सिर्फ़ `fileId` वाला Hash वर्कस्पेस में पहले से मौजूद फ़ाइल का नाम लेता है और इनलाइन सीमा में नहीं गिना जाता।
threadIdString- किसी मौजूदा thread में उत्तर दें, अधिकतम 256 वर्ण। transport इसी से In-Reply-To और References लिखता है, और यही वह चीज़ है जिससे उत्तर बातचीत के भीतर आता है, उसके बग़ल में नहीं।
draftIdString- सहेजे गए ड्राफ़्ट की सामग्री इस envelope के तहत भेजें, अधिकतम 256 वर्ण। यहाँ बनाए गए प्राप्तकर्ता, विषय और हेडर ही नेटवर्क पर जाते हैं।
templateHash- सहेजे गए टेम्पलेट को सर्वर पर रेंडर करें, id (`tpl_…`) या slug से, जहाँ `version` किसी संस्करण को पिन करता है और `props` तथा `slots` उसे भरते हैं। आइटम स्वीकार होते समय एक बार तय होता है, और `html` या `text` के साथ तथा `draftId` के साथ अस्वीकार किया जाता है, क्योंकि इनमें से हर एक इस सवाल का दूसरा जवाब है कि संदेश में क्या है।
scheduledAtTime, DateTime or String- एक Time या DateTime, ISO 8601 क्षण, या `PT1H` जैसी अवधि, भविष्य में कम से कम एक सेकंड और अधिकतम 365 दिन आगे। Ruby Date का मतलब उस दिन की UTC आधी रात है। आइटम अलग-अलग शेड्यूल होते हैं, इसलिए एक बैच में सौ अलग-अलग भेजने के समय हो सकते हैं।
cancellableForSecondsInteger- तुरंत वाले send पर सेकंड में undo विंडो, 0 से 900, डिफ़ॉल्ट 0। उसी आइटम पर `scheduledAt` के साथ 0 से ऊपर का कोई भी मान अस्वीकार होता है, क्योंकि शेड्यूल किया गया संदेश जाने तक पहले से ही रद्द किया जा सकता है।
trackingHash- `opens` और `clicks`, दोनों वैकल्पिक और दोनों सिर्फ़ इसी संदेश के लिए सेटिंग को बदलते हैं। जो कुंजी आप छोड़ देते हैं वह उस पते का अनुसरण करती है जिससे संदेश भेजा जाता है (या उसे पकड़ने वाले catch-all का), जो तब तक बंद है जब तक उस पते ने उसे चालू न किया हो।
tagsHash- अधिकतम 10 लेबल, जिनकी कुंजियाँ `A-Za-z0-9_-` में से 1 से 64 वर्णों की और मान 256 तक। संदेश पर वापस लौटाए जाते हैं और इनकी कभी व्याख्या नहीं होती: `emails.list` सिर्फ़ `status:`, `from:`, `broadcast_id:` और शेड्यूल विंडो पर फ़िल्टर करता है, और कुछ नहीं, इसलिए टैग ऐसी चीज़ है जिसे आप पहले से हाथ में मौजूद संदेश से पढ़ते हैं, उसे ढूँढने का तरीका नहीं।
translateHash- इस आइटम को दूसरी भाषा में भेजें, जो स्वीकार होते समय तय होता है ताकि जो शब्द स्वीकृत हुए वही बाहर जाएँ। एक बैच में अधिकतम 10 आइटम में यह हो सकता है: हर एक कई मॉडल कॉल ख़र्च करता है और आइटम क्रम से चलते हैं, इसलिए बड़ा बैच भेजते-भेजते बीच में ही ख़त्म कर दिया जाता। इससे ज़्यादा होने पर, कुछ भी भेजे जाने से पहले, पूरी कॉल `emails` पर `too_many_items` के रूप में अस्वीकार हो जाती है।
जवाब: OpenEmail::BatchResult
itemsArray<Hash>- हर संदेश के लिए एक Hash, उसी क्रम में जिसमें आपने उन्हें भेजा। कुछ भी वापस नहीं लिया जाता, इसलिए यह किसी transaction की रिपोर्ट नहीं बल्कि इस बात का रिकॉर्ड है कि हर संदेश के साथ क्या हुआ। API 207 जवाब देता है, चाहे हर संदेश स्वीकार हुआ हो, कुछ हुए हों या कोई नहीं, इसलिए कॉल हर हाल में लौटती है और शाखा हर आइटम के `status` पर बनानी है।
sentInteger- कितने आइटम “स्वीकार” हुए, जो इस बात के बराबर नहीं कि कितने निकले। कोई आइटम `ok` होकर भी ऐसा `email` लिए हो सकता है जिसका `status` `failed` या `partial` है, क्योंकि पंक्ति बन जाने के बाद संदेश को अस्वीकार करने वाला transport डिलीवरी का नतीजा है, अस्वीकृत रिक्वेस्ट नहीं।
failedInteger- कितने आइटम में `error` है। 0 से ऊपर की गिनती बैच को दोबारा भेजने का कारण नहीं, बल्कि कार्रवाई करने की सूची है। स्वीकार हुए संदेश पहले ही जा चुके हैं।
हर आइटम
indexInteger- आपकी भेजी Array में इस आइटम के संदेश की जगह। क्रम के साथ-साथ एक कुंजी के रूप में भी आती है, ताकि `items` को फ़िल्टर या सॉर्ट करने वाला कोड फिर भी बता सके कि कौन-सा संदेश विफल हुआ।
statusString- `ok` या `error`। `ok` में `email` होता है, `error` में `error`, और किसी आइटम में दोनों नहीं होते।
emailHash- स्वीकार हुआ संदेश, सिर्फ़ `ok` आइटम पर, उसी आकार में जो एक अकेला send लौटाता है। जब निकाली गई `Idempotency-Key` पहले से मौजूद send से मेल खाती है तो उसका `replayed` true होता है, यानी कुछ नया नहीं भेजा गया और यह मूल संदेश है। इसमें कोई `tracking` कुंजी नहीं होती, क्योंकि engagement की रिपोर्ट बाद में आती है और स्वीकार होते समय बताने को कुछ नहीं होता।
errorHash- यह एक संदेश क्यों अस्वीकार हुआ, सिर्फ़ `error` आइटम पर। यह API का error envelope है, `docUrl` और `requestId` के बिना: वे रिक्वेस्ट का वर्णन करते हैं, और रिक्वेस्ट कुल मिलाकर सफल रही।
किसी आइटम की error
typeString- वह श्रेणी जिस पर शाखा बनानी है: `validation_error`, `permission_error`, `not_found_error`, `conflict_error` और बाक़ी। यह सेट frozen है और बढ़ेगा नहीं, `code` के विपरीत।
codeString- विशिष्ट विफलता: `from_address_forbidden`, `invalid_email_address`, `too_many_recipients`, `reserved_header`, `message_too_large`, `unknown_parameter`। यह खुला और वर्धनशील है, इसलिए जिस कोड को आप न पहचानें उसे उसके `type` की तरह बरतें।
messageString- किसी व्यक्ति के लिए लिखा एक वाक्य, जो जहाँ कोई आपत्तिजनक मान हो वहाँ उसका नाम लेता है। यह स्थिर पहचानकर्ता नहीं है। शाखा `code` पर बनाएँ।
paramString- जो फ़ील्ड अस्वीकार हुआ, उसी संदेश के भीतर बिंदु-पथ के रूप में: `to.0`, `from`, `attachments`। जब विफलता किसी फ़ील्ड का नाम न ले तब अनुपस्थित, और इसके आगे batch की स्थिति कभी नहीं लगती। वह `index` का काम है।