Saltar al contenido principal
Documentation

SDK Ruby

RubyGems: coffeemail v0.1.0

Referencia completa de la gema oficial coffeemail para Ruby 3.3+. Sin dependencias de runtime, modelos inmutables, retorno seguro data, error, tipos RBS y verificación de webhooks.

¿Buscas la documentación para Node.js o TypeScript? Consulta la referencia oficial del paquete @coffeemail/node.

SDK Node.js
bundle add coffeemail

Inicialización del Cliente

Rails • Sinatra • Hanami • Sidekiq

Sin api_key:, la clave se lee de la variable de entorno COFFEEMAIL_API_KEY. El cliente es inmutable y puede compartirse entre hilos.

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 y Manejo de Errores

Patrón Seguro data, error

Cada operación devuelve un CoffeeMail::Response con data o error. Desestructura con data, error = ..., usa pattern matching o llama a unwrap! para lanzar el error 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

Validación Criptográfica de Webhooks

HMAC SHA-256 (fixed_length_secure_compare)

CoffeeMail::Webhook.from_rack valida el header x-webhook-signature (HMAC SHA-256 de timestamp, clave de idempotencia y cuerpo bruto) en tiempo constante y rechaza entregas fuera de la ventana 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

Referencia de las operaciones más usadas del cliente oficial para Ruby.

Emails

.send— Enviar email transaccional
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 emails en 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 estado del email
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 historial de envíos con paginación 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

Dominios

.create— Registrar dominio
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 del dominio
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}"

Plantillas

.create— Crear plantilla
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— Previsualizar plantilla con variables
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

Audiencias y Contactos

.contacts.create— Agregar contacto a la audiencia
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— Crear y enviar campaña
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)

Supresiones

.create— Suprimir destinatario
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— Registrar 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 firma 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 entregabilidad
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}%"