Enviar um email
`emails.send`: uma mensagem, agora ou mais tarde.
emails.send
email = client.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: Pathname("invoice.pdf")}], threadId: "CAHk7pQ2x9LmZ4-mail.example.com", scheduledAt: "PT1H", tags: {order: "4021"}, tracking: {opens: true, clicks: true}) puts email[:id], email[:status]to, cc e bcc aceitam um destinatário ou um Array deles, e um único é envolvido automaticamente. Cada um pode ser um endereço simples, Name <addr@host> ou um Hash com email e name.
A mensagem é passada como argumentos nomeados ou como um único Hash. Os argumentos nomeados ao lado de um Hash fundem-se com ele e prevalecem quando ambos indicam um campo, por isso client.emails.send(message, subject: "Re: your invoice") altera um campo de uma mensagem que construiu antes. As chaves mantêm os nomes da API, e é por isso que replyTo e scheduledAt continuam em camelCase, enquanto idempotency_key: e api_key: são opções da chamada e nunca fazem parte da mensagem.
Parâmetros
fromString or Hashobrigatório- O remetente. Um endereço simples, `Name <addr@host>`, ou um Hash com `email` e `name`. Tem de ser um a partir do qual esta chave possa enviar, ou a chamada lança um 403 `from_address_forbidden`. Não há remetente alternativo, por isso um envio indica sempre o endereço de onde sai.
toString, Hash or Arrayobrigatório- Um destinatário ou um Array deles, e um único é envolvido automaticamente. No máximo 50 no total de `to`, `cc` e `bcc`, e mais do que isso é um 422 `too_many_recipients`.
ccString, Hash or Array- Conta para o limite de 50 destinatários.
bccString, Hash or Array- Nunca aparece nos bytes que qualquer outra pessoa recebe, porque é transmitido um envelope por destinatário. Também conta para os 50.
replyToString or Hash- 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 omissão, e um assunto vazio recorre ao do modelo ou ao do rascunho.
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. No máximo 1 000 000 de caracteres.
textString- A parte de texto simples, no máximo 1 000 000 de caracteres.
templateHash- Renderizar um modelo guardado no servidor: um Hash com `id`, que aceita um id ou um slug, e `version` (um Integer), `props` e `slots` opcionais. `version` fixa uma revisã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, tal como foi escrito. Não pode ser combinado com `template` nem com `translate`.
headersHash- Nome de cabeçalho para valor String, limitado a `X-*`, `List-*`, Reply-To, Precedence, Auto-Submitted, Importance, Priority e Feedback-ID. Tudo o que o transporte define por si próprio é recusado com um 422 `reserved_header` em vez de ser descartado silenciosamente.
attachmentsArray<Hash>- Cada um é um Hash com `filename`, `content` e um `contentType` opcional, ou um Hash só com `fileId`, que refere um ficheiro já existente no espaço de trabalho, como um de `files.upload`. 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.
attachmentDeliveryString- `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.
scheduledAtTime, DateTime or String- Um Time ou um DateTime, enviado como instante ISO 8601 em UTC, um instante ISO 8601 como String, ou uma duração como `PT1H`. Até um ano no futuro, nunca no passado. Não pode ser combinado com `cancellableForSeconds`. Uma Date do Ruby é enviada como uma data simples, que a API lê como meia-noite UTC desse dia, por isso passe um Time quando a hora importa.
cancellableForSecondsInteger- 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.
tagsHash- Até 10 etiquetas, com chaves de 1 a 64 letras, algarismos, `_` ou `-` e valores String de até 256 caracteres. Devolvidas tal como estão em cada leitura e nunca interpretadas.
signatureBoolean- Se esta mensagem leva a assinatura do endereço de onde é enviada: a dele, senão a do catch-all para um endereço que um catch-all apanhou, senão o rodapé do OpenEmail, a menos que esse endereço o tenha desligado. Se for omitido, um corpo `html` sai exatamente como foi escrito, sem assinatura, e um corpo só `text` leva-a. Defina `false` no 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 quer a assinatura de uma pessoa por baixo. Os envios com modelo e os envios cifrados nunca a levam.
trackingHash- Um Hash com os Boolean opcionais `opens` e `clicks`: indica se deve ser adicionado um píxel de abertura e se as ligações desta mensagem devem ser reescritas. Inativo a menos que o rastreio tenha sido ativado para o endereço a partir do qual é enviada (ou para o catch-all que o apanhou), e qualquer uma das chaves indicadas aqui decide para essa mensagem, independentemente da definição do endereço.
translateHash- Enviar na língua do destinatário: um Hash com `to` e `from`, `subject` e `includeOriginal` opcionais. `to` aceita um código, um nome em inglês ou o nome da língua na própria língua, e `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`.
idempotency_keyString- A sua própria chave para este envio, de 1 a 255 caracteres entre letras, algarismos, `_`, `.`, `:` ou `-`. Sem ela, o cliente gera uma chave para cada chamada, por isso as suas próprias repetições nunca enviam duas vezes, e com ela um envio que corre de novo noutro processo é reproduzido em vez de repetido.
api_keyString- Envia com esta chave em vez da do cliente, para um processo que envia em nome de vários espaços de trabalho.
Resposta
Um Hash com chaves Symbol, por isso email[:status] lê o estado.
idString- O id do envio, `msg_` seguido de 24 caracteres hexadecimais. Use-o para `get`, `cancel`, `reschedule` e `get_tracking`.
statusString- queued, scheduled, sending, sent, partial, bounced, cancelled ou failed. Leia este campo em vez de se basear no facto de a chamada ter terminado: um envio imediato é despachado dentro do pedido e normalmente volta como `sent`, `partial` ou `failed`, e um retido volta como `queued` ou `scheduled`. `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.
modeString- `live` ou `test`: que tipo de chave o enviou. Um envio de teste é registado e nunca transmitido. Aparece como `sent`, com `transport` igual a `test`, por isso verifique a resposta e não uma caixa de entrada.
fromString- O endereço efetivamente autorizado e colocado na linha, que nem sempre é o que foi pedido.
subjectString or nil- Tal como foi enviado.
messageIdString or nil- O Message-ID RFC 5322. nil 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 or nil- A thread em que ficou.
transportString or nil- Como a mensagem saiu. nil até ao despacho.
attemptsInteger- Quantas vezes o despacho foi tentado.
lastErrorString or nil- Porque falhou a última tentativa, literalmente.
scheduledAtString or nil- O instante ISO 8601 em que deve sair.
cancellableUntilString or nil- Enquanto o momento atual for anterior a este, `cancel` continua a funcionar.
sentAtString or nil- O instante ISO 8601 em que saiu.
tagsHash- O que enviou, devolvido tal e qual.
sourceString- composer, api, mcp, ai ou queue: que superfície o pediu. `api` é este cliente.
createdAtString- O instante ISO 8601 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 tal como está agora.
translationHash- Presente apenas numa mensagem que foi traduzida, e apenas onde todo o pedido guardado é transportado: esta resposta e `get`. Contém `language`, `languageName`, `detectedSourceLanguage`, `subject` e `includeOriginal`, com códigos em vez de linhas de idioma completas. 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.
email = client.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"}) p email[:translation]email[:translation] contém então {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.
preview = client.emails.translate( subject: "Your September invoice", html: "<p>Invoice attached. Payment is due on the 14th.</p>", to: "de") puts preview.dig(:language, :native), preview[:subject], preview[:html]print "Send it as it is? [y/N] " if $stdin.gets.to_s.strip.casecmp?("y") client.emails.send( from: "[email protected]", to: "[email protected]", subject: preview[:subject], html: preview[:html] )endp OpenEmail::LANGUAGES.size current = client.languages.listp current.size p OpenEmail.resolve_language("Deutsch")&.fetch(:code)p OpenEmail.resolve_language("zh-TW")&.fetch(:code)p OpenEmail.language_by_code("DE")&.fetch(:native)p OpenEmail.rtl_language?("ar")Essas linhas de código imprimem 200, o número de linhas com que esta versão vem, depois quantas a API tem agora, e depois "de", "zh-Hant", "Deutsch" e true. A tabela vem incluída, pela ordem do seletor, como OpenEmail::LANGUAGES, um Array congelado de Hashes com code, label, native, flag e rtl, para que um seletor possa ser preenchido antes do primeiro pedido. languages.list devolve as mesmas linhas vindas da rede sob a forma de um Array simples, para quem prefira as atuais às que esta versão trouxe. OpenEmail.resolve_language 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) e devolve nil quando nada corresponde, OpenEmail.language_by_code 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 a API não consegue identificar é 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, um 429ai_quota_exceededquando o espaço de trabalho já gastou as ações de IA de hoje (é reposta à meia-noite UTC e não é repetido),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 mantém o texto aprovado.
emails.reschedulecontinua a movê-la, enquantoemails.updaterecusa um texto novo com um 409translation_locked, por isso mudar o que diz significa cancelar e enviar de novo.
Anexos
content segue em base64 pela rede. Passe os bytes e são codificados automaticamente: uma String binária como a que File.binread devolve, um IO como um File aberto, ou um Pathname, que é lido automaticamente.
attachments = [ {filename: "invoice.pdf", content: File.binread("invoice.pdf"), contentType: "application/pdf"}, {filename: "report.pdf", content: Pathname("report.pdf")}, {fileId: "file_6bb640f5b99e47deb758f1f5"}] client.emails.send( from: "[email protected]", to: "[email protected]", subject: "Your documents", text: "Both are attached.", attachments:)Uma String marcada como texto, como a que File.read devolve, é tomada como já estando em base64, e uma que não esteja em base64 lança ArgumentError antes de qualquer envio. Leia os ficheiros com File.binread, ou chame .b sobre os bytes que chegaram marcados como texto.
OpenEmail.to_base64 está disponível se precisar da mesma codificação noutro sítio. Aceita uma String binária, um IO ou um Pathname e devolve base64 estrito, sem quebras de linha.