Enviar um email
`emails.send`: uma mensagem, agora ou mais tarde.
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 e bcc aceitam um ou vários destinatários, e um único é envolvido num array automaticamente. Cada um pode ser um endereço simples, Name <addr@host> ou { email, name }.
Parâmetros
fromRecipientInputobrigatório- O remetente. Um endereço simples, `Name <addr@host>`, ou um objeto. Tem de ser um a partir do qual esta chave possa enviar. Não há remetente alternativo, porque a alternativa seria o endereço predefinido do espaço de trabalho, que muda à medida que os endereços vão e vêm.
toRecipientInput | RecipientInput[]obrigatório- Um ou vários destinatários; um único é envolvido num array automaticamente. No máximo 50 no total de to, cc e bcc.
ccRecipientInput | RecipientInput[]- Conta para o limite de 50 destinatários.
bccRecipientInput | RecipientInput[]- Nunca aparece nos bytes que qualquer outra pessoa recebe, porque é transmitido um envelope por destinatário.
replyToRecipientInput- Um único endereço, enviado como cabeçalho Reply-To.
subjectstring- No máximo 998 caracteres, o limite de linha do RFC 5322. Vazio por predefinição.
htmlstring- É obrigatório um de html, text, draftId ou template. O HTML é o que os destinatários veem quando html e text são ambos fornecidos.
textstring- A parte em texto simples.
template{ id, version?, props?, slots? }- Renderizar um modelo guardado no servidor. `version` fixa a versão; omita-o para usar a que estiver publicada quando o pedido for aceite. Uma prop desconhecida ou em falta dá 422 em vez de um espaço em branco na mensagem.
draftIdstring- Enviar um rascunho guardado com este envelope.
headersRecord<string, string>- `X-*`, `List-*`, Reply-To, Precedence, Auto-Submitted, Importance, Priority e Feedback-Id. Tudo o que o transporte define por si próprio é recusado em vez de ser descartado silenciosamente.
attachmentsAttachmentInput[]- `{ filename, content, contentType? }` ou `{ fileId }`, que refere um ficheiro já existente no espaço de trabalho. Passe bytes em content e são codificados em base64 automaticamente. 20 ficheiros, com os ficheiros inline limitados a 5 MB no total depois de descodificados. Um ficheiro guardado pode ser maior e segue como ligação de transferência.
attachmentDeliveryAttachmentDeliveryMode- `mime`, `link` ou `auto`. `auto` envia os ficheiros como ligações de transferência quando ultrapassam 2 MB num domínio com um domínio de ficheiros ativo, e dentro da mensagem nos restantes casos. Se for omitido, aplica-se a definição da caixa de correio, cuja predefinição é `auto`.
threadIdstring- Responder numa conversa existente. O transporte escreve In-Reply-To e References.
scheduledAtDate | string- Um Date, um instante ISO-8601 ou uma duração como `PT1H`. Até um ano à frente, nunca no passado. Não pode ser combinado com cancellableForSeconds.
cancellableForSecondsnumber- De 0 a 900. Uma janela para anular num envio imediato: o mecanismo de anulação do editor de mensagens, exposto em vez de fixo no código.
tagsRecord<string, string>- Até 10 etiquetas, devolvidas e filtráveis. Nunca interpretadas.
signatureboolean- Indica se esta mensagem inclui a assinatura do endereço a partir do qual é enviada, que é a assinatura própria desse endereço ou, na falta dela, a definida para Todos os endereços. A predefinição é true, porque uma assinatura pertence ao endereço e não ao cliente que enviou a mensagem. Defina `false` para o correio que um programa envia em nome de alguém, como um recibo, uma reposição de palavra-passe ou um resumo, nenhum dos quais deve levar a despedida de uma pessoa.
tracking{ opens?, clicks? }- Indica se deve ser adicionado um píxel de abertura e se as ligações desta mensagem devem ser reescritas. Ativo a menos que o proprietário do espaço de trabalho tenha desativado o rastreio para o endereço a partir do qual é enviada ou para Todos os endereços, e qualquer um dos campos indicados aqui decide para essa mensagem, independentemente da definição do endereço.
translate{ to, from?, subject?, includeOriginal? }- Enviar na língua do destinatário. `to` aceita um código, um nome em inglês ou o nome da língua na própria língua; `subject` e `includeOriginal` são ambos true por predefinição. Resolvido quando o pedido é aceite, pelo que uma mensagem agendada leva as palavras que foram aprovadas. Recusado em conjunto com `draftId`.
Resposta
idstring- O id do envio, `msg_…`. Use-o para `get`, `cancel`, `reschedule` e `getTracking`.
statusEmailStatus- queued, scheduled, sending, sent, partial, cancelled ou failed. Leia este campo em vez de se basear no facto de a promise ter sido resolvida. `partial` é um estado próprio: alguns destinatários já a têm e não é possível anular o envio, pelo que tentar de novo é errado e reportar falha é falso.
mode'live' | 'test'- Que tipo de chave o enviou. Um envio de teste é registado e nunca transmitido.
fromstring- O endereço efetivamente autorizado e colocado na linha, que nem sempre é o que foi pedido.
subjectstring | null- Tal como foi enviado.
messageIdstring | null- O Message-ID RFC 5322. Null até o MIME existir. O serviço de envio reescreve o cabeçalho à saída, por isso nenhuma devolução nem relatório de entrega transporta este valor. É em `id` que um evento regressa.
threadIdstring | null- A thread em que ficou.
transportstring | null- Como a mensagem saiu. Null até ao despacho.
attemptsnumber- Quantas vezes o despacho foi tentado.
lastErrorstring | null- Porque falhou a última tentativa, literalmente.
scheduledAtstring | null- Instante ISO em que deve sair.
cancellableUntilstring | null- Enquanto o momento atual for anterior a este, cancel continua a funcionar.
sentAtstring | null- Instante ISO em que saiu.
tagsRecord<string, string>- O que enviou, devolvido tal e qual.
sourceEmailSource- composer, api, mcp, ai ou queue: que superfície o pediu. `api` é este cliente.
createdAtstring- Instante ISO em que o registo foi escrito.
replayedboolean- True quando uma Idempotency-Key correspondeu a um envio que já existia. Nada de novo foi enviado, e esta é a mensagem original.
translationEmailTranslationResource | undefined- Presente apenas numa mensagem que foi traduzida, e apenas onde todo o pedido guardado é transportado: esta resposta e `get`. `{ language, languageName, detectedSourceLanguage, subject, includeOriginal }`, todos códigos em vez de linhas de idioma. Uma linha de listagem nunca o tem, por isso a sua ausência aí não diz nada num sentido nem no outro.
Na língua do destinatário
translate escreve a mensagem na língua de outra pessoa antes de ela partir. O corpo, e o assunto a menos que o desative, é traduzido quando a API aceita o pedido, e o que saiu é o que vai sair: uma tradução que não pôde ser produzida recusa o envio em vez de o publicar na língua em que o escreveu.
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 }Ninguém leu aquilo antes de partir. emails.translate é a mesma ida e volta parada um passo antes. Mostre-a a uma pessoa, deixe-a alterá-la e depois envie o que ela aprovou sem qualquer translate na chamada. Passá-lo outra vez traduziria uma segunda vez e deitaria fora as edições dela.
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') // trueA tabela vem incluída, pela ordem do seletor, para que um seletor possa ser preenchido antes do primeiro pedido. languages.list() resolve para as mesmas linhas vindas da rede sob a forma de um array simples, para quem prefira as atuais às que esta versão trouxe. resolveLanguage aceita um código, um nome em inglês, um endónimo ou um alias (zh-TW é um alias de um código que já não é listado), languageByCode faz corresponder um código exato sem distinguir maiúsculas de minúsculas, e dezasseis das linhas são da direita para a esquerda. Pesquise native, label e code em conjunto, mostre native primeiro e guarde o código.
emails.translate não é repetido automaticamente. Gasta chamadas ao modelo e não escreve nada, por isso não há nada para tornar idempotente e uma repetição após um pedido sem resposta só compraria a mesma resposta duas vezes.
- Um idioma que não resolve para nada é um
validation_erroremtranslate.to, antes de seja o que for ser enviado. translation_too_longacima de 30 000 caracteres,translation_not_configuredquando a instalação não tem IA configurada,translation_failedquando o fornecedor não respondeu. Nenhum deles envia a mensagem por traduzir como alternativa.- Funciona com
template: é o resultado RENDERIZADO que é traduzido, por isso um corpo guardado serve todas as línguas em que os seus clientes leem. Um template que renderiza um documento inteiro mantém o seu doctype, os seus blocos<style>e as suas regras@font-face: só o corpo vai para o modelo e o resto é reposto à volta dele. O seu<title>fica intacto, e nada o mostra de qualquer forma. - Uma repetição não custa nada a mais. A tradução não faz parte da impressão digital de idempotência (o pedido faz,
translateincluído), por isso repetir um envio sem resposta com a mesmaIdempotency-Keyreproduz a mensagem que já existe em vez de traduzir e enviar uma segunda. - Uma mensagem traduzida que esteja em fila ou agendada fica congelada contra alterações de texto.
emails.reschedulecontinua a movê-la; mudar o que diz significa cancelar e enviar de novo.
Anexos
content vai em base64 na rede. Passe bytes e são codificados por si.
attachments: [ { filename: 'invoice.pdf', content: pdfBytes, contentType: 'application/pdf' },]toBase64 é exportado se precisar dele noutro sítio. Divide em blocos, o que btoa(String.fromCharCode(...bytes)) não faz. Esse falha em qualquer coisa acima de cerca de 100 kB, e falha no ficheiro real e não naquele com que testou.