Saltar para a documentação
Ruby

Enviar um lote

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

emails.send_batch

send_batch.rb
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)}"  endend

send_batch aceita um Array de Hashes de mensagem, cada um com exatamente a forma do corpo de emails.send, e devolve um OpenEmail::BatchResult. O seu items contém um Hash por cada mensagem, pela mesma ordem, cada um ok com a sua mensagem ou error com o envelope com que essa mensagem teria sido recusada. Nada é revertido, pelo que uma contagem failed acima de 0 é uma lista sobre a qual agir e não um motivo para reenviar o lote.

Uma só chave de idempotência cobre o lote e o servidor estende-a para cada item, por isso um lote repetido reproduz cada mensagem em vez de as reduzir à primeira. Envie o mesmo Array pela mesma ordem quando o repetir: um item que mudou de lugar fica ligado à chave de outra posição e volta como um erro idempotency_key_reuse.

Uma mensagem recusada não lança exceção. Só um problema com o lote no seu conjunto lança: um Array vazio, mais de 100 mensagens, mais de 10 com translate, uma falha de chave ou de âmbito, ou uma falha do servidor. Uma falha do servidor a meio chega depois de os itens anteriores terem saído, e o cliente repete-a com a mesma chave, o que reproduz esses itens em vez de os enviar duas vezes.

Os itens são enviados um a seguir ao outro dentro de um único pedido, por isso um lote grande de envios imediatos demora bastante mais do que um único send. Mantenha generoso o timeout: do cliente.

Parâmetros: emails.send_batch

emailsArray<Hash>obrigatório
De 1 a 100 mensagens, enviadas como `{"emails": [...]}` e aceites uma de cada vez pela ordem indicada. Cada uma passa pelo mesmo tratamento que `emails.send`, por isso um destinatário único é envolvido, um Time torna-se um instante e os bytes dos anexos são codificados. Um Array vazio, mais de 100, ou mais de 10 mensagens com `translate` fazem recusar a chamada inteira com um `validation_error` em `emails`. A falta do âmbito `emails:send` e um `idempotency_key:` mal formado também fazem recusar a chamada inteira, antes de ser enviada uma única mensagem.
idempotency_keyString
Elimina duplicados do lote entre processos. O cliente anexa sempre uma chave acabada de gerar em cada chamada, pelo que as suas próprias repetições nunca enviam em duplicado, e o servidor estende a chave que receber para cada 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.
api_keyString
Envia o lote com esta chave em vez da do cliente.

Cada mensagem em emails

fromString or Hashobrigatório
O remetente, como endereço simples, `Name <addr@host>` ou um Hash com `email` e `name`. 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`.
toString, Hash or Arrayobrigató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.
ccString, Hash or Array
Por predefinição, nenhum, e conta para o mesmo total de 50 endereços que `to` e `bcc`.
bccString, Hash or Array
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.
replyToString or Hash
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.
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.
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`.
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.
headersHash
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.
attachmentsArray<Hash>
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 pela rede. Passe os bytes como String binária, IO ou Pathname e o cliente codifica-os. Um Hash só com `fileId` refere um ficheiro que já está no espaço de trabalho e não conta para o limite inline.
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.
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.
templateHash
Renderizar um modelo guardado no servidor, por id (`tpl_…`) ou slug, com `version` a fixar uma revisão e `props` e `slots` a preenchê-lo. Resolvido uma vez, quando o item é aceite, e recusado em conjunto com `html` ou `text` e com `draftId`, já que cada um desses é uma segunda resposta ao que a mensagem contém.
scheduledAtTime, DateTime or String
Um Time ou um DateTime, um instante ISO 8601 ou uma duração como `PT1H`, pelo menos um segundo no futuro e no máximo 365 dias à frente. Uma Date do Ruby significa meia-noite UTC desse dia. Os itens são agendados de forma independente, pelo que um lote pode conter cem horas de envio diferentes.
cancellableForSecondsInteger
Uma janela para anular, em segundos, num envio imediato, de 0 a 900 e 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.
trackingHash
`opens` e `clicks`, cada um opcional e cada um a substituir a definição apenas para esta mensagem. Uma chave omitida segue o endereço a partir do qual a mensagem é enviada (ou o catch-all que o apanhou), em que o rastreio está inativo a menos que esse endereço o tenha ativado.
tagsHash
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` filtra por `status:`, `from:`, `broadcast_id:` e pela janela de agendamento e nada mais, pelo que uma etiqueta é algo a ler numa mensagem que já tem e não uma forma de a encontrar.
translateHash
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: OpenEmail::BatchResult

itemsArray<Hash>
Um Hash por cada mensagem, 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 chamada devolve o resultado em qualquer caso e é o `status` de cada item que deve orientar a lógica.
sentInteger
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` cujo `status` é `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.
failedInteger
Quantos itens têm um `error`. Uma contagem acima de 0 é uma lista sobre a qual agir e não um motivo para reenviar o lote. As mensagens aceites já foram enviadas.

Cada item

indexInteger
A posição que a mensagem deste item ocupava no Array que enviou. Transmitida como chave e também pela ordem, para que o código que filtra ou ordena `items` consiga ainda saber que mensagem falhou.
statusString
`ok` ou `error`. `ok` traz `email`, `error` traz `error`, e nenhum item traz ambos.
emailHash
A mensagem aceite, apenas num item `ok`, com a mesma forma que um envio individual devolve. O seu `replayed` é true quando a `Idempotency-Key` derivada correspondeu a um envio que já existia, por isso nada de novo foi enviado e esta é a mensagem original. Não inclui a chave `tracking`, porque o envolvimento é reportado mais tarde e não há nada a reportar no momento da aceitação.
errorHash
Porque é que esta mensagem foi recusada, apenas num item `error`. É o envelope de erro da API sem `docUrl` nem `requestId`: esses descrevem o pedido, e o pedido no seu conjunto foi bem-sucedido.

O erro de um item

typeString
A categoria em que 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`.
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`.
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`.
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`.