ईमेल भेजें
`emails.send`: एक संदेश, अभी या बाद में।
emails.send
const email = await openemail.emails.send({ from: { email: '[email protected]', name: 'Acme Billing' }, to: ['[email protected]', 'Grace <[email protected]>'], cc: '[email protected]', bcc: [{ email: '[email protected]' }], replyTo: '[email protected]', subject: 'Your September invoice', html: '<p>Invoice attached.</p>', text: 'Invoice attached.', headers: { 'X-Campaign': 'invoices' }, attachments: [{ filename: 'invoice.pdf', content: pdfBytes }], threadId: 'thread_…', scheduledAt: 'PT1H', tags: { order: '4021' }, tracking: { opens: true, clicks: true },})to, cc और bcc एक प्राप्तकर्ता लेते हैं या कई, और अकेले को आपके लिए लपेट दिया जाता है। हर एक सादा पता हो सकता है, Name <addr@host>, या { email, name }।
पैरामीटर
fromRecipientInputआवश्यक- भेजने वाला। सादा पता, `Name <addr@host>`, या कोई ऑब्जेक्ट। यह ऐसा होना चाहिए जिसके रूप में यह कुंजी भेज सकती है। कोई फ़ॉलबैक प्रेषक नहीं है, क्योंकि फ़ॉलबैक वर्कस्पेस का डिफ़ॉल्ट पता होता, जो पतों के आने-जाने के साथ बदलता रहता है।
toRecipientInput | RecipientInput[]आवश्यक- एक प्राप्तकर्ता या कई; अकेले को आपके लिए लपेट दिया जाता है। to, cc और bcc को मिलाकर अधिकतम 50।
ccRecipientInput | RecipientInput[]- यह 50 प्राप्तकर्ताओं की सीमा में गिना जाता है।
bccRecipientInput | RecipientInput[]- बाक़ी लोगों को मिलने वाले bytes में इसका नाम कभी नहीं आता, क्योंकि प्रति प्राप्तकर्ता एक लिफ़ाफ़ा प्रेषित होता है।
replyToRecipientInput- एक अकेला पता, जो Reply-To header के रूप में भेजा जाता है।
subjectstring- अधिकतम 998 वर्ण, यानी RFC 5322 की पंक्ति-सीमा। डिफ़ॉल्ट खाली।
htmlstring- html, text, draftId या template में से एक ज़रूरी है। जब html और text दोनों दिए जाएँ तो प्राप्तकर्ता HTML ही देखते हैं।
textstring- सादा-पाठ हिस्सा।
template{ id, version?, props?, slots? }- सर्वर पर संग्रहित template को render करें। `version` उसे पिन करता है; इसे छोड़ दें तो रिक्वेस्ट स्वीकार होते समय जो प्रकाशित हो वही उपयोग होता है। अनजान या ग़ायब prop संदेश में ख़ाली जगह नहीं, 422 देता है।
draftIdstring- इस लिफ़ाफ़े के तहत कोई सहेजा गया draft भेजें।
headersRecord<string, string>- `X-*`, `List-*`, Reply-To, Precedence, Auto-Submitted, Importance, Priority और Feedback-Id। जो कुछ transport ख़ुद सेट करता है उसे चुपचाप गिराने के बजाय अस्वीकार किया जाता है।
attachmentsAttachmentInput[]- `{ filename, content, contentType? }`, या workspace में पहले से मौजूद किसी फ़ाइल का नाम लेता `{ fileId }`। content के लिए bytes दें और वे आपके लिए base64 में बदल दिए जाते हैं। 20 फ़ाइलें, जिनमें inline फ़ाइलें decode होने के बाद कुल 5 MB तक सीमित। संग्रहित फ़ाइल इससे बड़ी हो सकती है और डाउनलोड लिंक के रूप में जाती है।
attachmentDeliveryAttachmentDeliveryMode- `mime`, `link` या `auto`। `auto` फ़ाइलों को डाउनलोड लिंक के रूप में तब ले जाता है जब वे सक्रिय files domain वाले किसी domain पर 2 MB पार कर जाएँ, और बाक़ी हालत में संदेश के भीतर। छोड़ देने पर मेलबॉक्स की सेटिंग लागू होती है, और उसका डिफ़ॉल्ट `auto` है।
threadIdstring- किसी मौजूदा thread में उत्तर दें। transport In-Reply-To और References लिखता है।
scheduledAtDate | string- एक Date, एक ISO-8601 क्षण, या `PT1H` जैसी कोई अवधि। एक साल तक आगे, अतीत में कभी नहीं। इसे cancellableForSeconds के साथ नहीं मिलाया जा सकता।
cancellableForSecondsnumber- 0 से 900 तक। तत्काल send पर एक undo खिड़की: composer की undo व्यवस्था, hardcode किए जाने के बजाय उजागर की हुई।
tagsRecord<string, string>- अधिकतम 10 लेबल, वापस लौटाए जाने वाले और फ़िल्टर करने योग्य। इनकी कभी व्याख्या नहीं होती।
signatureboolean- यह संदेश उस पते का हस्ताक्षर ले जाए या नहीं जिससे वह भेजा जा रहा है — यानी उसी पते का अपना हस्ताक्षर, और वह न हो तो All addresses के लिए तय किया गया। डिफ़ॉल्ट true, क्योंकि हस्ताक्षर उस पते का होता है, न कि उस क्लाइंट का जिसने संदेश भेजा। जो मेल कोई प्रोग्राम किसी की ओर से भेजता है — जैसे रसीद, पासवर्ड रीसेट या digest — उसके लिए इसे `false` रखें, क्योंकि इनमें से किसी के नीचे किसी व्यक्ति के दस्तख़त नहीं चाहिए।
tracking{ opens?, clicks? }- इस संदेश में open pixel जोड़ा जाए और लिंक दोबारा लिखे जाएँ या नहीं। यह तब तक चालू रहता है जब तक workspace के मालिक ने उस पते के लिए या All addresses के लिए tracking बंद न की हो, और यहाँ बताया गया कोई भी फ़ील्ड उस एक संदेश के लिए फ़ैसला कर देता है, चाहे पते की सेटिंग जो भी हो।
translate{ to, from?, subject?, includeOriginal? }- इसे प्राप्तकर्ता की भाषा में भेजें। `to` कोई कोड, अंग्रेज़ी नाम या भाषा का अपना नाम लेता है; `subject` और `includeOriginal` दोनों डिफ़ॉल्ट रूप से true हैं। यह रिक्वेस्ट स्वीकार होते समय हल किया जाता है, इसलिए निर्धारित संदेश वही शब्द ले जाता है जो मंज़ूर हुए थे। `draftId` के साथ अस्वीकार।
प्रतिक्रिया
idstring- send की id, `msg_…`। इसका उपयोग `get`, `cancel`, `reschedule` और `getTracking` के लिए करें।
statusEmailStatus- queued, scheduled, sending, sent, partial, cancelled या failed। promise के resolve हो जाने के तथ्य के बजाय इसे पढ़ें। `partial` अपने आप में एक स्थिति है: कुछ प्राप्तकर्ताओं के पास संदेश है और उसे वापस नहीं लिया जा सकता, इसलिए दोबारा कोशिश करना ग़लत है और विफलता बताना झूठ।
mode'live' | 'test'- किस प्रकार की कुंजी ने इसे भेजा। test send दर्ज होता है और कभी प्रेषित नहीं होता।
fromstring- वह पता जो असल में अधिकृत हुआ और तार पर गया, जो हमेशा वही नहीं होता जो माँगा गया था।
subjectstring | null- जैसा भेजा गया।
messageIdstring | null- RFC 5322 Message-ID। MIME बनने तक null। sending सेवा बाहर जाते समय इस header को दोबारा लिख देती है, इसलिए कोई bounce या delivery report यह मान नहीं ढोती। event `id` पर ही वापस आता है।
threadIdstring | null- वह thread जिसमें यह उतरा।
transportstring | null- संदेश कैसे रवाना हुआ। dispatch तक null।
attemptsnumber- dispatch कितनी बार आज़माया जा चुका है।
lastErrorstring | null- आख़िरी प्रयास क्यों विफल हुआ, शब्दशः।
scheduledAtstring | null- ISO क्षण जब यह जाने वाला है।
cancellableUntilstring | null- जब तक अभी का समय इससे पहले है, cancel काम करता है।
sentAtstring | null- ISO क्षण जब यह रवाना हुआ।
tagsRecord<string, string>- आपने जो भेजा, वही वापस लौटाया हुआ।
sourceEmailSource- composer, api, mcp, ai या queue: किस सतह ने माँगा। `api` यही क्लाइंट है।
createdAtstring- ISO क्षण जब रिकॉर्ड लिखा गया।
replayedboolean- true तब जब कोई Idempotency-Key पहले से मौजूद किसी send से मेल खा गई। कुछ भी नया नहीं भेजा गया, और यह मूल संदेश है।
translationEmailTranslationResource | undefined- केवल उसी संदेश पर मौजूद जो अनूदित हुआ था, और केवल वहाँ जहाँ पूरी संग्रहित रिक्वेस्ट साथ चलती है: यह प्रतिक्रिया और `get`। `{ language, languageName, detectedSourceLanguage, subject, includeOriginal }`, सब भाषा-पंक्तियों के बजाय कोड। list की पंक्ति पर यह कभी नहीं होता, इसलिए वहाँ इसकी अनुपस्थिति किसी भी दिशा में कुछ नहीं कहती।
प्राप्तकर्ता की भाषा में
translate संदेश को जाने से पहले किसी और की भाषा में लिख देता है। body, और जब तक आप उसे बंद न करें तब तक विषय भी, तब अनूदित होता है जब API रिक्वेस्ट स्वीकार करता है, और जो निकला वही बाहर जाता है: जो अनुवाद बन ही नहीं सका, वह संदेश को आपकी लिखी भाषा में भेजने के बजाय send को अस्वीकार कर देता है।
const email = await openemail.emails.send({ from: '[email protected]', to: '[email protected]', subject: 'Your September invoice', html: '<p>Invoice attached. Payment is due on the 14th.</p>', translate: { to: 'de' },}) console.log(email.translation)// { language: 'de', languageName: 'German', detectedSourceLanguage: 'en', subject: true, includeOriginal: true }जाने से पहले उसे किसी ने पढ़ा ही नहीं। emails.translate वही चक्कर है, बस एक क़दम पहले रोक दिया गया। इसे किसी व्यक्ति को दिखाएँ, उसे बदलने दें, फिर जो उसने मंज़ूर किया वही भेजें — कॉल पर translate बिल्कुल लगाए बिना। दोबारा उसे पास करना दूसरी बार अनुवाद कर देता और उनके संपादन फेंक देता।
const preview = await openemail.emails.translate({ subject: 'Your September invoice', html: '<p>Invoice attached. Payment is due on the 14th.</p>', to: 'de',}) console.log(preview.language.native, preview.detectedSourceLanguage) const approved = await showToSomebody(preview) await openemail.emails.send({ from: '[email protected]', to: '[email protected]', subject: approved.subject, html: approved.html,})import { LANGUAGES, isRtlLanguage, languageByCode, openemail, resolveLanguage } from '@openemail/sdk' LANGUAGES.length // 200 const current = await openemail.languages.list() resolveLanguage('Deutsch')?.code // 'de'resolveLanguage('zh-TW')?.code // 'zh-Hant'languageByCode('DE')?.native // 'Deutsch'isRtlLanguage('ar') // trueतालिका picker के क्रम में बंडल की गई है, ताकि पहली रिक्वेस्ट से पहले ही picker भरा जा सके। languages.list() तार से आई उन्हीं पंक्तियों को एक सादे array के रूप में resolve करता है, उस कॉलर के लिए जो इस वर्शन के साथ आई पंक्तियों के बजाय मौजूदा पंक्तियाँ चाहता हो। resolveLanguage कोई कोड, अंग्रेज़ी नाम, स्वनाम या उपनाम लेता है (zh-TW अब सूचीबद्ध न रहे एक कोड का उपनाम है), languageByCode किसी सटीक कोड से केस की परवाह किए बिना मिलान करता है, और सोलह पंक्तियाँ दाएँ से बाएँ हैं। native, label और code को एक साथ खोजें, native पहले दिखाएँ, और code संग्रहित करें।
emails.translate अपने आप दोबारा नहीं आज़माया जाता। इसमें model कॉल ख़र्च होती हैं और यह कुछ लिखता नहीं, इसलिए idempotent बनाने को कुछ है ही नहीं और बिना उत्तर वाली रिक्वेस्ट के बाद का retry वही उत्तर दो बार ख़रीदने भर से ज़्यादा कुछ नहीं होता।
- जो भाषा किसी पर हल नहीं होती वह कुछ भी भेजे जाने से पहले
translate.toपरvalidation_errorहै। - 30,000 वर्ण से ऊपर
translation_too_long, जब install में कोई AI कॉन्फ़िगर न हो तबtranslation_not_configured, और जब provider ने उत्तर न दिया हो तबtranslation_failed। इनमें से कोई भी fallback के तौर पर संदेश बिना अनुवाद के नहीं भेजता। templateके साथ काम करता है: अनुवाद render किए गए आउटपुट का होता है, इसलिए एक संग्रहित body आपके ग्राहकों की हर पढ़ी जाने वाली भाषा में काम आता है। पूरा दस्तावेज़ render करने वाला template अपना doctype, अपने<style>ब्लॉक और अपने@font-faceनियम बनाए रखता है: model के पास केवल body जाता है और बाक़ी सब उसके चारों ओर वापस रख दिया जाता है। उसका<title>अछूता छोड़ दिया जाता है, जिसे वैसे भी कुछ नहीं दिखाता।- retry का कोई अतिरिक्त ख़र्च नहीं। अनुवाद idempotency fingerprint का हिस्सा नहीं है (रिक्वेस्ट है,
translateसहित), इसलिए बिना उत्तर वाले send को उसीIdempotency-Keyके साथ दोबारा भेजना पहले से मौजूद संदेश को दोहरा देता है, दूसरी बार अनुवाद करके भेजता नहीं। - जो अनूदित संदेश queued या scheduled है, उसके शब्द बदले नहीं जा सकते।
emails.rescheduleअब भी उसे खिसका सकता है; उसमें लिखी बात बदलने का मतलब है उसे रद्द करके दोबारा भेजना।
अटैचमेंट
तार पर content base64 होता है। आप bytes दें और वे आपके लिए encode कर दिए जाते हैं।
attachments: [ { filename: 'invoice.pdf', content: pdfBytes, contentType: 'application/pdf' },]toBase64 export किया गया है, अगर आपको कहीं और चाहिए हो। यह टुकड़ों में काम करता है, जो btoa(String.fromCharCode(...bytes)) नहीं करता। वह वाला लगभग 100 kB से बड़ी किसी भी चीज़ पर विफल हो जाता है, और वह असली फ़ाइल पर विफल होता है, उस पर नहीं जिससे आपने परीक्षण किया था।