E-mail küldése
POST /emails: egy üzenet, most vagy később.
A valódi hívást futtatja le a munkaterületén, a saját kulcsával.
A kérés
A from kötelező. A szerkesztővel ellentétben itt nincs tartalék feladó, mert az a tartalék a munkaterület alapértelmezett címe, és láthatatlanul változik, ahogy a címek jönnek-mennek.
| Mező | Kötelező | Megjegyzések |
|---|---|---|
| from | igen | Puszta cím vagy Name <addr>. Olyannak kell lennie, amellyel a kulcs küldhet. |
| to | igen | Összesen legfeljebb 50 címzett a to, a cc és a bcc mezőkben. |
| cc, bcc | nem | A bcc címzettek soha nem szerepelnek névvel azokban a bájtokban, amelyeket bárki más megkap. |
| subject | nem | Alapértelmezetten üres. |
| html, text | az egyik | Mindkettő is mehet. A HTML az, amit a címzettek látnak. |
| template | az egyik | { id, version?, props?, slots? }. Tárolt törzs, azonosító vagy slug alapján. A html, a text vagy a draftId mellett elutasítjuk. Lásd a Küldés sablonnal részt. |
| replyTo | nem | Egyetlen cím. |
| headers | nem | X-*, List-*, Reply-To, Precedence, Auto-Submitted, Importance, Priority, Feedback-Id. |
| attachments | nem | { filename, content, contentType } base64 formában, összesen 5 MB, vagy { fileId }, amely a munkaterületen már meglévő fájlt nevez meg. 20 fájl. |
| attachmentDelivery | nem | mime, link vagy auto. Az auto linkeli a fájlokat, amint 2 MB fölé érnek egy aktív fájldomainnel rendelkező domainen. Alapértelmezetten a postafiók beállítása. |
| threadId | nem | Válasz egy meglévő üzenetszálba. |
| draftId | nem | Meglévő piszkozat küldése. |
| scheduledAt | nem | ISO időpont vagy időtartam. Lásd az Ütemezés részt. |
| cancellableForSeconds | nem | 0 és 900 másodperc közötti visszavonási ablak az azonnali küldésnél. A scheduledAt mellett elutasítjuk, mert az amúgy is visszavonható marad az elküldéséig. Lásd az Ütemezés részt. |
| signature | nem | A false lehagyja az aláírást erről az üzenetről. Egyébként annak a címnek az aláírását viszi, amelyről küldik, vagyis a cím sajátját, vagy ha nincs, az Összes címhez beállítottat. |
| tags | nem | Legfeljebb 10 saját címke. Visszaadjuk őket, de soha nem értelmezzük. |
| tracking | nem | { opens?, clicks? }. Bármelyik felülírja a beállítást erre az üzenetre; ha egy mezőt kihagysz, az a fél visszaesik annak a címnek a beállítására, amelyről küldik, vagy az Összes címre, és bekapcsolt állapotú, hacsak valamelyik ki nem kapcsolta. |
| translate | nem | { to, from?, subject?, includeOriginal? }. A címzett nyelvén küldi el. A kérés elfogadásakor oldódik fel, és a draftId mellett elutasítjuk. |
Az ismeretlen mezőket elutasítjuk, nem figyelmen kívül hagyjuk, így egy elgépelt név most 422, nem később meglepetés. Azokat a fejléceket, amelyek kijátszanák a feladó engedélyezését (From, Sender, Bcc, Message-ID, Return-Path és mások), reserved_header hibával utasítjuk el.
A válasz
200, ha az üzenet már elment, 202, ha még történnie kell vele valaminek. A státuszkódra elágazó hívó mindkettőben helyesen jár el.
{ "object": "email", "id": "msg_c5f21cc6bfec4e848caf905b", "status": "sent", "mode": "live", "from": "[email protected]", "subject": "Your September invoice", "messageId": "<2598…@acme.com>", "transport": "ses", "sentAt": "2026-08-29T08:19:08.000Z", "source": "api", "replayed": false}Az id a tartós fogantyú, amit megtartasz, és ezen érkezik vissza egy kézbesítési esemény is, hiszen egy visszapattanási webhook emailId néven nevezi meg. A messageId az RFC 5322 Message-ID, és addig null, amíg a MIME nem létezik. Ne erre korrelálj: a küldő szolgáltatás kimenet közben átírja ezt a fejlécet, így az itteni érték egyetlen visszapattanási vagy kézbesítési jelentésben sem jelenik meg, és az illesztés rá soha nem sül el.
A címzett nyelvén
A translate valaki más nyelvén írja meg az üzenetet, mielőtt elmegy. A törzset, és ha ezt ki nem kapcsolod, a tárgyat is, a kérés ELFOGADÁSÁNAK pillanatában fordítjuk le, ugyanazzal a szabállyal, amelyet a template követ, és ugyanazokból az okokból teherviselő: az ütemezett üzenet azokat a szavakat viszi, amelyeket jóváhagytak, nem azt, amit egy modell kedden előállít, a le nem fordítható fordítás pedig elutasítja a küldést, mielőtt sor jönne létre. Semmit nem kézbesítünk olyan nyelven, amelyet a feladója nem választott.
translate
tostringkötelező- A nyelv, amelyen írni kell: BCP-47 kód (`de`), angol név („German”) vagy a nyelv saját neve („Deutsch”), 2 és 60 karakter között. Mindhármat a táblázatbeli kódra normalizáljuk, mielőtt bármi más történne, tehát egy kérésnek számítanak, ami azért fontos, mert az Idempotency-Key ujjlenyomatát a feldolgozott kérésen vesszük. Az aliasok is feloldódnak: a `zh-TW` `zh-Hant` lesz. Az, amelyik semmire nem oldódik fel, 422 a `translate.to` mezőn.
fromstring- Az, amelyen írtad, ugyanabban a három formában. Tisztán optimalizáció. Ha kihagyod, beolvassuk a törzset és kikövetkeztetjük a nyelvet, ami egy rövid modellhívásba kerül. Nagy forgalmú útvonalon érdemes megadni, és akkor is, ha a törzs főleg nevekből, számokból és linkekből áll: a felismerés inkább tartózkodik, mint találgat, a meghatározatlan forrás pedig semmibe nem kerül azon kívül, hogy az eredetid fölötti feliratban nem szerepel nyelv. Nem azonos a felső szintű `from` mezővel, amely egy cím.
subjectboolean- A tárgysor lefordítása is. Alapértelmezetten igaz; a false pontosan úgy küldi a tárgyat, ahogy megírtad.
includeOriginalboolean- Tedd oda azt, amit valójában írtál, a fordítás alá, elválasztó mögé, a címzett nyelvén feliratozva. Alapértelmezetten igaz, és érdemes bekapcsolva hagyni. Egyedül ez teszi lehetővé az olvasónak, hogy ellenőrizzen egy furcsán ható mondatot, ahelyett hogy egy olyan modellben kellene bíznia, amelynek kimenetét egyikőtök sem látja.
curl -X POST "$OE/emails" -H "$AUTH" -H "Content-Type: application/json" \ -d '{ "from": "[email protected]", "to": ["[email protected]"], "subject": "Your September invoice", "html": "<p>Invoice attached. Payment is due on the 14th.</p>", "translate": { "to": "de" } }'{ "object": "email", "id": "msg_c5f21cc6bfec4e848caf905b", "status": "sent", "from": "[email protected]", "subject": "Ihre Rechnung für September", "translation": { "language": "de", "languageName": "German", "detectedSourceLanguage": "en", "subject": true, "includeOriginal": true }}A translation kiegészítő mező, és csak lefordított üzeneten jelenik meg: ezen a válaszon és a GET /emails/{id} válaszán, listasoron soha, mert a lista nem kéri le a tárolt kérést, így az ottani hallgatása egyik irányba sem mond semmit. Kódokat visz, nem teljes nyelvsorokat: arról szóló feljegyzés, mi történt, az endonim pedig a GET /languages válaszában él. A válaszon a subject a lefordított tárgy, így egy konzol soha nem listáz üzenetet olyan szöveg alatt, amelyet a címzett nem látott.
- Működik a
templatemezővel, és ez a hasznos eset: a MEGJELENÍTETT kimenetet fordítjuk le, így egyetlen tárolt törzs minden nyelvet kiszolgál, amelyen az ügyfeleid olvasnak. A teljes dokumentumot megjelenítő sablont előbb szétszedjük: csak a<body>belseje jut el a modellhez, a doctype, a<style>blokkok és az@font-faceszabályok pedig visszakerülnek a válasz köré. Ezért is a prózát méri a 30 000 karakteres korlát, nem a dokumentumot: a márkás stíluslapba csomagolt kétsoros üzenet kétsoros üzenet. - Egy sablonból egyedül a
<title>marad lefordítatlanul, amelyet egyetlen levelezőkliens sem jelenít meg. A react-email<Preview>eleme a törzsbe rendereli magát, és a többivel együtt lefordul. - A
draftIdmellett elutasítjuk: 422 atranslatemezőn, ezzel a szöveggel: „A draft is sent as it was written; translate a body or send a draft, not both”. A piszkozatot ember írta, és úgy megy el, ahogy hagyta. - Szándékosan nem része az idempotencia-ujjlenyomatnak. Az általad küldött kérést hasheljük, a
translatemezővel együtt; azt, amit a modell előállított, nem. Így egy megválaszolatlan küldés újrapróbálása ugyanazzal azIdempotency-Keykulccsal visszajátssza az eredetit. A már létező üzenet jön vissza, második küldés és második fordítás nélkül. A szöveg hashelése ezzel szemben minden alkalommal más ujjlenyomatot adna egy becsületes újrapróbálkozásnak, és így megy ki kétszer ugyanaz az üzenet. - A sorban álló vagy ütemezett lefordított üzenet be van fagyasztva a szövegváltoztatás ellen. Helyezd át vagy vond vissza; a tartalmának megváltoztatása annyit tesz, hogy visszavonod és újraküldöd, olyasvalaki előtt, aki el tudja olvasni az új szöveget.
- A jobbról balra író célnyelvet jobbról balra állítjuk elő: a fordítás
dir="rtl"attribútumba csomagolva, alatta az eredetid a saját irányában. Az attribútum túléli a kimenő tisztítót, amely pontosan ezért engedélyezi adirattribútumot, így a hálózatra kerülő üzenet azt az irányt viszi, amelyet az előnézet mutatott.
| Kód | Státusz | Mikor |
|---|---|---|
| `invalid_parameter` | 422 | A translate.to vagy a translate.from olyan nyelvet nevez meg, amelyet nem tudunk elhelyezni. Az üzenet megmondja, melyik három forma elfogadott, és a GET /languages hívásra mutat. |
| `unknown_language` | 422 | Ugyanaz a hiba egy lépéssel később elkapva, a séma helyett a szolgáltatás által. Védőháló, a translate.to mezőn. |
| `translation_too_long` | 422 | Több mint 30 000 karakter a modellhívás bármelyik végén. Elutasítás, nem csonkolás: a fél lefordított üzeneten nincs varrat, amely megmutatná, hol állt meg, az olvasó pedig a kapott feléből cselekszik. |
| `translation_not_configured` | 409 | A munkaterületnek nincs AI kulcsa, és a platform AI ki van kapcsolva. 409, nem 503, mert az újrapróbálkozás ugyanígy bukna el. Semmit nem küldtünk el. Küldd translate nélkül, ha úgy akartad küldeni, ahogy megírtad. |
| `translation_failed` | 503 | A szolgáltató nem válaszolt, vagy használhatatlan választ adott. Semmit nem küldtünk el; az üzenetet soha nem tesszük ki tartalékként lefordítatlanul. Ez a mienk, és érdemes újrapróbálni. |
| `unknown_parameter` | 422 | Ismeretlen kulcs a translate objektumon belül, amely a kérés többi részéhez hasonlóan szigorú objektum. |
A kódból indított küldésnél senki nem olvassa el előbb a fordítást. A POST /emails/translate ugyanaz a körút, egy lépéssel korábban megállítva, arra, hogy megmutasd valakinek, mit készül elküldeni. Utána azt küldd el, amit jóváhagytak, közönséges html/subject formában, a kérésen translate nélkül.