SDK
Wysyłka partii
`emails.sendBatch`: do 100 wiadomości, wyniki dla każdej pozycji.
emails.sendBatch
const result = await openemail.emails.sendBatch(invoices.map(toMessage)) console.log(result.sent, 'sent,', result.failed, 'failed') for (const item of result.items) { if (item.status === 'error') console.error(item.index, item.error.code, item.error.message) else console.log(item.index, item.email.id)}items zawiera po jednym wpisie na każde wejście, w kolejności, każdy albo ok ze swoją wiadomością, albo error z kopertą błędu, z jaką ta wiadomość zostałaby odrzucona. Nic nie jest wycofywane, więc failed > 0 to lista do obsłużenia, a nie powód do ponownego wysłania całej partii.
Jeden klucz idempotencji obejmuje całą partię, a serwer rozszerza go per pozycja, więc ponowiona partia odtwarza każdą wiadomość, zamiast zwijać je wszystkie do pierwszej.
Parametry: emails.sendBatch
emailsEmailSend[]wymagane- Od jednej do 100 wiadomości, serializowanych jako `{ "emails": [...] }` i przyjmowanych pojedynczo w podanej kolejności. Pusta tablica, więcej niż 100 albo więcej niż 10 pozycji niosących `translate` odrzuca całe wywołanie z `validation_error` na `emails`. Tak samo brakujący zakres `emails:send`, treść, która nie jest tablicą ani `{ emails: [...] }`, oraz źle sformułowany `Idempotency-Key` — wszystko to, zanim wyjdzie choć jedna wiadomość.
options.idempotencyKeystring- Deduplikuje partię między procesami. Klient i tak dołącza świeżo wygenerowany klucz przy każdym wywołaniu, więc jego własne ponowienia nigdy nie wysyłają podwójnie, a serwer rozszerza otrzymany klucz per pozycja jako `key/0`, `key/1` i tak dalej, rozdzielając ukośnikiem — znakiem, którego Twój własny klucz nie może zawierać — więc jeden klucz na sto wiadomości nie może zwinąć ich do pierwszej.
emails[].fromRecipientInputwymagane- Nadawca, jako sam adres, `Name <addr@host>` albo obiekt. Nie ma nadawcy zapasowego, a klucz musi mieć prawo do tego adresu; odmowa wywraca tę jedną pozycję jako `permission_error` z kodem `from_address_forbidden`.
emails[].toRecipientInput | RecipientInput[]wymagane- Co najmniej jeden odbiorca, a pojedynczy jest przez klienta opakowywany w tablicę. Najwyżej 50 adresów łącznie w `to`, `cc` i `bcc`, liczone na wiadomość, a nie na całą partię.
emails[].ccRecipientInput | RecipientInput[]- Domyślnie brak; liczy się do tej samej puli 50 adresów co `to` i `bcc`.
emails[].bccRecipientInput | RecipientInput[]- Domyślnie brak; liczy się do tej samej puli 50 adresów. `Bcc` to jedna z nazw, których `headers` nie może ustawić, więc to jedyny sposób na ukrytą kopię. Forma nagłówkowa zniweczyłaby kopertę per odbiorca, która utrzymuje adres w ukryciu.
emails[].replyToRecipientInput- Dokąd trafiają odpowiedzi. Stosowane po `headers`, więc nadpisuje `Reply-To` ustawione też tam, zamiast dodawać drugie.
emails[].subjectstring- Najwyżej 998 znaków, czyli limit linii z RFC 5322, domyślnie pusty ciąg. Pusty temat przechodzi na temat samego szablonu, gdy `template` go dostarcza.
emails[].htmlstring- Część HTML, najwyżej milion znaków, i ta, którą widzą odbiorcy, gdy podano obie treści. Wymagane jest jedno z `html`, `text`, `template` albo `draftId`, a pozycja bez żadnego z nich wywraca się jako `validation_error` na `html`.
emails[].textstring- Część tekstowa, najwyżej milion znaków. Można wysłać obie, a każdy transport na tej ścieżce buduje jedną treść z jednego ciągu, więc `html` wygrywa tam, gdzie jest.
emails[].headersRecord<string, string>- Tylko `X-*`, `List-*`, Reply-To, Precedence, Auto-Submitted, Importance, Priority i Feedback-ID; wszystko, co transport ustawia sam (From, To, Bcc, Subject, Message-ID, nagłówki DKIM i ARC), jest odrzucane jako `reserved_header`, a nie po cichu pomijane. Wartości mają najwyżej 998 znaków i nie mogą zawierać CR, LF ani NUL, bo druga linia to drugi nagłówek.
emails[].attachmentsAttachmentInput[]- Najwyżej 20 plików na wiadomość, przy czym pliki inline łącznie do 5 MB po zdekodowaniu, liczone na wiadomość, a nie na partię. `content` jest na łączu w base64; przekaż bajty, a klient je zakoduje — to jedno z miejsc, gdzie ręcznie pisany base64 niezawodnie przepełnia stos wywołań. Wpis `{ fileId }` nazywa plik już obecny w przestrzeni roboczej i nie liczy się do limitu inline.
emails[].threadIdstring- Odpowiedź w istniejącym wątku, najwyżej 256 znaków. Transport zapisuje z tego In-Reply-To i References, co sprawia, że odpowiedź ląduje w konwersacji, a nie obok niej.
emails[].draftIdstring- Wyślij treść zapisanej wersji roboczej pod tą kopertą, najwyżej 256 znaków. To odbiorcy, temat i nagłówki zbudowane tutaj idą na łącze.
emails[].template{ id, version?, props?, slots? }- Wyrenderuj zapisany szablon po stronie serwera, po identyfikatorze (`tpl_…`) albo po slugu, z `version` przypinającym wersję i `props`/`slots` ją wypełniającymi. Rozwiązywane raz, w chwili przyjęcia pozycji, i odrzucane obok `html`/`text` oraz obok `draftId`, bo każde z nich jest drugą odpowiedzią na pytanie, co zawiera wiadomość.
emails[].scheduledAtDate | string- `Date`, instant ISO-8601 albo czas trwania w rodzaju `PT1H`; co najmniej sekundę w przyszłości i najwyżej 365 dni naprzód. Pozycje planują się niezależnie, więc jedna partia może nieść sto różnych czasów wysyłki.
emails[].cancellableForSecondsnumber- Okno cofnięcia w sekundach przy wysyłce natychmiastowej, liczba całkowita od 0 do 900, domyślnie 0. Cokolwiek powyżej 0 jest odrzucane obok `scheduledAt` w tej samej pozycji, bo zaplanowaną wiadomość i tak można anulować do chwili wyjścia.
emails[].trackingTrackingRequest- `opens` i `clicks`, każde niezależnie opcjonalne i każde nadpisujące ustawienie dla tej jednej wiadomości. Przełącznik, który pominiesz, spada do ustawienia adresu, z którego wiadomość jest wysyłana, a dalej do ustawienia Wszystkich adresów, które jest włączone, o ile nikt go tam nie wyłączył.
emails[].tagsRecord<string, string>- Najwyżej 10 etykiet, klucze od 1 do 64 znaków z zakresu `A-Za-z0-9_-`, wartości do 256. Odsyłane na wiadomości i nigdy nieinterpretowane: `emails.list` przyjmuje `status`, `from`, `limit` i `cursor` i nic więcej, więc etykieta to coś, co odczytujesz z wiadomości, którą już masz, a nie sposób na jej znalezienie.
emails[].translateSendTranslateOptions- Wyślij tę pozycję w innym języku, rozwiązywane w chwili przyjęcia, żeby słowa, które zatwierdzono, były słowami, które wychodzą. Najwyżej 10 pozycji w jednej partii może to nieść: każda kosztuje kilka wywołań modelu, a pozycje idą po kolei, więc większa partia zostałaby ubita w połowie wysyłki. Powyżej tego całe wywołanie jest odrzucane jako `too_many_items` na `emails`, zanim cokolwiek wyjdzie.
Odpowiedź: BatchResultResource
itemsBatchItemResource[]- Po jednym wpisie na każde wejście, w kolejności wysłania. Nic nie jest wycofywane, więc to zapis tego, co stało się z każdą wiadomością, a nie raport o transakcji. API odpowiada 207 niezależnie od tego, czy przyjęto każdą wiadomość, niektóre czy żadną, więc obietnica rozwiązuje się tak czy inaczej, a rozgałęziać należy się na `status` poszczególnych pozycji.
sentnumber- Ile pozycji PRZYJĘTO, co nie jest tym samym co to, ile wyszło. Pozycja może być `ok` i wciąż nieść `email.status` równe `failed` albo `partial`, bo transport, który odrzuca wiadomość po powstaniu wiersza, to wynik doręczenia, a nie odrzucone żądanie.
failednumber- Ile wpisów niesie `error`. `failed > 0` to lista do obsłużenia, a nie powód do ponownego wysłania partii. Przyjęte wiadomości już poszły.
items[].indexnumber- Pozycja, jaką wiadomość tego wpisu zajmowała w przesłanej przez Ciebie tablicy. Niesiona jako pole, a nie tylko jako kolejność, żeby kod filtrujący albo sortujący `items` nadal mógł powiedzieć, które wejście się wywróciło.
items[].status'ok' | 'error'- Dyskryminator unii: `ok` niesie `email`, `error` niesie `error`, a żaden wpis nie niesie obu.
items[].emailSentEmailResource- Przyjęta wiadomość, wyłącznie we wpisie `ok`, w tej samej postaci, jaką zwraca pojedyncza wysyłka. Nie niesie klucza `tracking`, bo zaangażowanie raportowane jest później, a w chwili przyjęcia nie ma czego raportować.
items[].email.replayedboolean- True, gdy wyprowadzony `Idempotency-Key` pasował do wysyłki, która już istniała, więc nic nowego nie wysłano, a to jest oryginalna wiadomość.
items[].error{ type: string; code: string; message: string; param?: string }- Dlaczego ta jedna wiadomość została odrzucona, wyłącznie we wpisie `error`. To koperta błędu API bez `docUrl` i `requestId`: one opisują żądanie, a żądanie jako całość się powiodło.
items[].error.typestring- Kategoria, na której klient może się rozgałęzić: `validation_error`, `permission_error`, `not_found_error`, `conflict_error` i reszta. Zbiór jest zamrożony i nie będzie rósł, w odróżnieniu od `code`.
items[].error.codestring- Konkretna porażka: `from_address_forbidden`, `invalid_email_address`, `too_many_recipients`, `reserved_header`, `message_too_large`, `unknown_parameter`. Zbiór otwarty i przyrostowy, więc kod, którego nie rozpoznajesz, traktuj jak jego `type`.
items[].error.messagestring- Jedno zdanie napisane dla człowieka, nazywające wadliwą wartość, jeśli taka jest. Nie jest stabilnym identyfikatorem. Przełączaj się na `code`.
items[].error.paramstring- Pole, które odrzucono, jako ścieżka z kropkami wewnątrz TAMTEJ wiadomości: `to.0`, `from`, `attachments`. Nieobecne, gdy porażka nie nazywa żadnego pola, i nigdy niepoprzedzone pozycją w partii, od czego jest `index`.