Saltar para a documentação
SDK

Enviar um lote

`emails.sendBatch`: até 100 mensagens, resultados por item.

emails.sendBatch

send-batch.ts
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 contém uma entrada por cada elemento enviado, pela mesma ordem, cada uma ok com a sua mensagem ou error com o envelope com que essa mensagem teria sido recusada. Nada é revertido, pelo que failed > 0 é uma lista sobre a qual agir e não um motivo para reenviar o lote.

Uma única chave de idempotência cobre o lote e o servidor estende-a por item, pelo que um lote repetido reproduz todas as mensagens em vez de as reduzir à primeira.

Parâmetros: emails.sendBatch

emailsEmailSend[]obrigatório
De 1 a 100 mensagens, serializadas como `{ "emails": [...] }` e aceites uma de cada vez pela ordem indicada. Um array vazio, mais de 100 mensagens, ou mais de 10 itens com `translate` fazem recusar a chamada inteira com um `validation_error` em `emails`. O mesmo acontece com a falta do âmbito `emails:send`, um corpo que não seja um array nem `{ emails: [...] }` e um `Idempotency-Key` mal formado, tudo antes de ser enviada uma única mensagem.
options.idempotencyKeystring
Elimina duplicados do lote entre processos. O cliente anexa sempre uma chave acabada de gerar em cada chamada, pelo que as suas próprias novas tentativas nunca enviam em duplicado, e o servidor estende a chave que receber por item como `key/0`, `key/1` e assim por diante, separadas por uma barra, um carácter que a sua própria chave não pode conter, pelo que uma chave para cem mensagens não as pode reduzir à primeira.
emails[].fromRecipientInputobrigatório
O remetente, como endereço simples, `Name <addr@host>` ou um objeto. Não existe remetente alternativo e a chave tem de ter permissão para este endereço; uma recusa faz falhar apenas esse item, como `permission_error` com o código `from_address_forbidden`.
emails[].toRecipientInput | RecipientInput[]obrigatório
Pelo menos um destinatário, e um único é envolvido num array pelo cliente. No máximo 50 endereços em `to`, `cc` e `bcc` combinados, contados por mensagem e não em todo o lote.
emails[].ccRecipientInput | RecipientInput[]
Por predefinição, nenhum, e conta para o mesmo total de 50 endereços que `to` e `bcc`.
emails[].bccRecipientInput | RecipientInput[]
Por predefinição, nenhum, e conta para o mesmo total de 50 endereços. `Bcc` é um dos nomes que `headers` não pode definir, pelo que esta é a única forma de enviar uma cópia oculta. A forma de cabeçalho anularia o envelope por destinatário que mantém o endereço oculto.
emails[].replyToRecipientInput
Para onde vão as respostas. É aplicado depois de `headers`, pelo que substitui um `Reply-To` que também tenha definido aí em vez de acrescentar um segundo.
emails[].subjectstring
No máximo 998 caracteres, o limite de linha do RFC 5322, e a predefinição é uma string vazia. Um assunto vazio dá lugar ao do próprio modelo quando `template` fornece um.
emails[].htmlstring
A parte HTML, com no máximo um milhão de caracteres, e a parte que os destinatários veem quando ambos os corpos são fornecidos. É obrigatório um de `html`, `text`, `template` ou `draftId`, e um item sem nenhum deles falha com um `validation_error` em `html`.
emails[].textstring
A parte em texto simples, com no máximo um milhão de caracteres. Podem ser enviadas ambas, e cada transporte neste percurso constrói um corpo a partir de uma string, pelo que `html` prevalece quando existe.
emails[].headersRecord<string, string>
Apenas `X-*`, `List-*`, Reply-To, Precedence, Auto-Submitted, Importance, Priority e Feedback-ID; tudo o que o transporte define por si próprio (From, To, Bcc, Subject, Message-ID, os cabeçalhos DKIM e ARC) é recusado como `reserved_header` em vez de ser descartado silenciosamente. Os valores têm no máximo 998 caracteres e não podem conter CR, LF nem NUL, porque uma segunda linha é um segundo cabeçalho.
emails[].attachmentsAttachmentInput[]
No máximo 20 ficheiros por mensagem, com os ficheiros inline a totalizarem 5 MB depois de descodificados, contados por mensagem e não por lote. `content` segue em base64; passe bytes e o cliente codifica-os, que é precisamente o sítio onde um base64 feito à mão rebenta sistematicamente a pilha de chamadas. Uma entrada `{ fileId }` refere um ficheiro que já está no espaço de trabalho e não conta para o limite inline.
emails[].threadIdstring
Responder numa conversa existente, com no máximo 256 caracteres. O transporte escreve In-Reply-To e References a partir dele, e é isso que faz a resposta ficar na conversa e não ao lado dela.
emails[].draftIdstring
Enviar o conteúdo de um rascunho guardado com este envelope, com no máximo 256 caracteres. Os destinatários, o assunto e os cabeçalhos construídos aqui são o que é efetivamente enviado.
emails[].template{ id, version?, props?, slots? }
Renderizar um modelo guardado no servidor, por id (`tpl_…`) ou slug, com `version` a fixar uma revisão e `props`/`slots` a preenchê-lo. Resolvido uma vez, quando o item é aceite, e recusado em conjunto com `html`/`text` e com `draftId`, já que cada um desses é uma segunda resposta ao que a mensagem contém.
emails[].scheduledAtDate | string
Um `Date`, um instante ISO-8601 ou uma duração como `PT1H`; pelo menos um segundo no futuro e no máximo 365 dias à frente. Os itens são agendados de forma independente, pelo que um lote pode conter cem horas de envio diferentes.
emails[].cancellableForSecondsnumber
Uma janela para anular, em segundos, num envio imediato: um inteiro de 0 a 900, com 0 por predefinição. Qualquer valor acima de 0 é recusado em conjunto com `scheduledAt` no mesmo item, já que uma mensagem agendada já pode ser cancelada até sair.
emails[].trackingTrackingRequest
`opens` e `clicks`, cada um opcional de forma independente e cada um a substituir a definição apenas para esta mensagem. Um interruptor omitido recorre à definição do endereço a partir do qual a mensagem é enviada, ou então a Todos os endereços, que está ativo a menos que uma dessas definições o tenha desativado.
emails[].tagsRecord<string, string>
No máximo 10 etiquetas, com chaves de 1 a 64 caracteres de `A-Za-z0-9_-` e valores até 256. Devolvidas na mensagem e nunca interpretadas: `emails.list` aceita `status`, `from`, `limit` e `cursor` e nada mais, pelo que uma etiqueta é algo a ler numa mensagem que já tem e não uma forma de a encontrar.
emails[].translateSendTranslateOptions
Enviar este item noutra língua, resolvido no momento da aceitação para que as palavras aprovadas sejam as palavras que saem. No máximo 10 itens num lote podem incluí-lo: cada um gasta várias chamadas ao modelo e os itens são executados por ordem, pelo que um lote maior seria interrompido a meio do envio. Acima disso, a chamada inteira é recusada como `too_many_items` em `emails`, antes de qualquer envio.

Resposta: BatchResultResource

itemsBatchItemResource[]
Uma entrada por cada mensagem enviada, pela ordem em que as enviou. Nada é revertido, pelo que isto é um registo do que aconteceu a cada mensagem e não um relatório sobre uma transação. A API responde 207 quer todas as mensagens tenham sido aceites, quer algumas, quer nenhuma, pelo que a promise resolve em qualquer caso e é o `status` de cada item que deve orientar a lógica.
sentnumber
Quantos itens foram ACEITES, o que não é o mesmo que quantos saíram. Um item pode ser `ok` e ter ainda assim um `email.status` de `failed` ou `partial`, porque um transporte que recusa a mensagem depois de a linha existir é um resultado de entrega e não um pedido rejeitado.
failednumber
Quantas entradas têm um `error`. `failed > 0` é uma lista sobre a qual agir e não um motivo para reenviar o lote. As mensagens aceites já foram enviadas.
items[].indexnumber
A posição que a mensagem desta entrada ocupava no array que enviou. Transmitida como campo e também pela ordem, para que o código que filtra ou ordena `items` consiga ainda saber que elemento falhou.
items[].status'ok' | 'error'
O discriminante da união: `ok` inclui `email`, `error` inclui `error`, e nenhuma entrada inclui ambos.
items[].emailSentEmailResource
A mensagem aceite, apenas numa entrada `ok`, com a mesma forma que um envio individual devolve. Não inclui a chave `tracking`, porque o envolvimento é reportado mais tarde e não há nada a reportar no momento da aceitação.
items[].email.replayedboolean
É true quando o `Idempotency-Key` derivado correspondeu a um envio que já existia, pelo que nada de novo foi enviado e esta é a mensagem original.
items[].error{ type: string; code: string; message: string; param?: string }
Porque é que esta mensagem foi recusada, apenas numa entrada `error`. É o envelope de erro da API sem `docUrl` nem `requestId`: esses descrevem o pedido, e o pedido no seu conjunto foi bem-sucedido.
items[].error.typestring
A categoria em que um cliente pode basear a lógica: `validation_error`, `permission_error`, `not_found_error`, `conflict_error` e as restantes. O conjunto está fixo e não vai crescer, ao contrário de `code`.
items[].error.codestring
A falha específica: `from_address_forbidden`, `invalid_email_address`, `too_many_recipients`, `reserved_header`, `message_too_large`, `unknown_parameter`. Aberto e cumulativo, por isso trate um código que não reconheça de acordo com o seu `type`.
items[].error.messagestring
Uma frase escrita para uma pessoa, que indica o valor problemático quando existe. Não é um identificador estável. Baseie a lógica em `code`.
items[].error.paramstring
O campo que foi recusado, como caminho com pontos dentro DESSA mensagem: `to.0`, `from`, `attachments`. Ausente quando a falha não se refere a nenhum campo, e nunca prefixado com a posição no lote, já que é para isso que serve `index`.