Pular para o conteúdo principal
Documentation

SDK Ruby

RubyGems: coffeemail v0.1.0

Referência completa da gem oficial coffeemail para Ruby 3.3+. Sem dependências de runtime, modelos imutáveis, retorno seguro data, error, tipagem RBS e verificação de webhooks.

Buscando a documentação para Node.js ou TypeScript? Acesse a referência oficial do pacote @coffeemail/node.

SDK Node.js
bundle add coffeemail

Inicialização do Cliente

Rails • Sinatra • Hanami • Sidekiq

Sem api_key:, a chave é lida da variável de ambiente COFFEEMAIL_API_KEY. O client é imutável e pode ser compartilhado entre threads.

CoffeeMail::Client.new(api_key: nil, locale: "pt-BR", timeout: 10, retry_policy: nil, transport: nil)
send_email.rb
require "coffeemail" # Sem api_key:, o SDK lê COFFEEMAIL_API_KEY do ambiente.client = CoffeeMail::Client.new data, error = client.emails.send(  from: "contato@seudominio.com.br",  to: "cliente@gmail.com",  subject: "Bem-vindo ao CoffeeMail!",  html: "<h1>Olá!</h1><p>Sua conta está ativa.</p>",) abort("Erro ao enviar [#{error.code}]: #{error.message}") if error puts "E-mail enfileirado: #{data.id}"

Retorno Seguro e Tratamento de Erros

Padrão Seguro data, error

Toda operação devolve um CoffeeMail::Response com data ou error. Desestruture com data, error = ..., use pattern matching ou chame unwrap! para levantar o erro tipado.

error_handling.rb
response = client.emails.get(email_id) data, error = response          # desestruturaçãoresponse => { data: }           # pattern matchingemail = response.unwrap!        # levanta CoffeeMail::Error na falha case response.errorwhen CoffeeMail::RateLimitError  sleep(response.error.retry_after_seconds || 60)when CoffeeMail::NotFoundError  puts "E-mail não encontrado (request_id=#{response.error.request_id})"end

Validação Criptográfica de Webhooks

HMAC SHA-256 (fixed_length_secure_compare)

CoffeeMail::Webhook.from_rack valida o header x-webhook-signature (HMAC SHA-256 de timestamp, chave de idempotência e corpo bruto) em tempo constante e rejeita entregas fora da janela de 5 minutos.

coffee_mail_webhooks_controller.rb
class CoffeeMailWebhooksController < ApplicationController  skip_forgery_protection   def create    result = CoffeeMail::Webhook.from_rack(request, secret: ENV.fetch("COFFEEMAIL_WEBHOOK_SECRET"))    return head(:bad_request) if result.failure?     Rails.logger.info("#{result.data.event_type}: #{result.data.data}")    head(:no_content)  endend

Catálogo de Métodos

Referência das operações mais usadas do client oficial para Ruby.

Emails

.send— Enviar e-mail transacional
client.emails.send(from:, to:, subject: nil, html: nil, text: nil, idempotency_key: nil, sandbox: false, **) -> Response[SendEmailResult]
emails_send.rb
data, error = client.emails.send(  from: { email: "noreply@seudominio.com.br", name: "Minha App" },  to: "cliente@example.com",  subject: "Confirmação do pedido #123",  html: "<h1>Obrigado!</h1><p>Seu pedido está em processamento.</p>",  idempotency_key: "pedido-123",) return warn("Erro [#{error.code}]: #{error.message}") if error puts "E-mail #{data.id} #{data.status}"
.send_batch— Enviar e-mails em lote
client.emails.send_batch(items) -> Response[Array[BatchSendItem]]
emails_send_batch.rb
data, error = client.emails.send_batch([  { from: "noreply@seudominio.com.br", to: "ana@example.com", subject: "Oi, Ana", text: "Olá!" },  { from: "noreply@seudominio.com.br", to: "bruno@example.com", subject: "Oi, Bruno", text: "Olá!" },]) data.each { |item| puts item.ok ? item.data.id : item.error }
.get— Consultar status do e-mail
client.emails.get(id) -> Response[EmailDetail]
emails_get.rb
email = client.emails.get("8b0f6a4e-3c2d-4f1a-9b7e-1a2b3c4d5e6f").unwrap!puts "#{email.status} em #{email.delivered_at}"
.list— Listar histórico de envios com paginação automática
client.emails.list(status: nil, after: nil, limit: nil, **) -> Response[EmailList]
emails_list.rb
client.emails.pages(status: CoffeeMail::EmailStatus::BOUNCED, limit: 100).each do |page|  break warn(page.error.message) if page.failure?   page.data.emails.each { |email| puts email.id }end

Domínios

.create— Cadastrar domínio
client.domains.create(name:) -> Response[CreatedDomain]
domains_create.rb
domain, error = client.domains.create(name: "seudominio.com.br") domain&.dkim_records_to_publish&.each { |record| puts "#{record.type} #{record.host} #{record.value}" }
.verify— Verificar registros DNS do domínio
client.domains.verify(id) -> Response[DomainVerification]
domains_verify.rb
result = client.domains.verify(domain_id).unwrap!puts "SPF: #{result.checks.spf.ok} · DKIM: #{result.checks.dkim.ok}"

Templates

.create— Criar template
client.templates.create(name:, html:, alias: nil, subject: nil, format: nil, **) -> Response[TemplateDetail]
templates_create.rb
template, error = client.templates.create(  name: "Boas-vindas",  alias: "welcome",  subject: "Bem-vindo, {{nome}}!",  html: "<h1>Olá, {{nome}}!</h1>",)
.preview_by_id— Pré-visualizar template com variáveis
client.templates.preview_by_id(id, variables: nil) -> Response[RenderedTemplate]
templates_preview.rb
preview = client.templates.preview_by_id(template_id, variables: { nome: "Ana" }).unwrap!puts preview.html

Audiências e Contatos

.contacts.create— Adicionar contato à audiência
client.audiences.contacts.create(audience_id, email:, first_name: nil, last_name: nil, metadata: nil) -> Response[Contact]
audiences_contacts_create.rb
contact, error = client.audiences.contacts.create(  audience_id,  email: "ana@example.com",  first_name: "Ana",  metadata: { plano: "pro" },)

Broadcasts

.create— Criar e disparar campanha
client.broadcasts.create(audience_id:, from_email:, template_id: nil, subject: nil, **) -> Response[BroadcastDetail]
broadcasts_create.rb
broadcast = client.broadcasts.create(  audience_id: audience_id,  from_email: "news@seudominio.com.br",  template_id: template_id,).unwrap! client.broadcasts.send(broadcast.id)

Supressões

.create— Suprimir destinatário
client.suppressions.create(email:, reason: nil, expires_at: nil) -> Response[SuppressionDetail]
suppressions_create.rb
client.suppressions.create(email: "nao-enviar@example.com", reason: "manual")

Webhooks

.create— Cadastrar webhook
client.webhooks.create(url:, events:, description: nil) -> Response[WebhookDetail]
webhooks_create.rb
webhook = client.webhooks.create(  url: "https://app.seudominio.com.br/webhooks/coffeemail",  events: [CoffeeMail::Webhook::EventType::EMAIL_DELIVERED, CoffeeMail::Webhook::EventType::EMAIL_BOUNCED],).unwrap! ENV["COFFEEMAIL_WEBHOOK_SECRET"] = webhook.secret
.Webhook.from_rack— Validar assinatura HMAC de webhook
CoffeeMail::Webhook.from_rack(request, secret:, tolerance: 300) -> Response[Webhook::Event]
webhooks_verify_signature.rb
result = CoffeeMail::Webhook.from_rack(request, secret: ENV.fetch("COFFEEMAIL_WEBHOOK_SECRET"))return head(:bad_request) if result.failure? puts result.data.event_type

Métricas

.get— Consultar métricas de entregabilidade
client.stats.get(start_date: nil, end_date: nil, granularity: nil, **) -> Response[Stats]
stats_get.rb
stats = client.stats.get(start_date: "2026-10-01", end_date: "2026-10-31", granularity: "day").unwrap!puts "Entrega: #{stats.delivery_rate}% · Abertura: #{stats.open_rate}%"