Saltar al contenido
Docs

Tutorial

Enviar emails con Ruby on Rails

Entrega el correo de Action Mailer a través de Emailit con la gema emailit o la configuración SMTP, llama directamente a la API y verifica los webhooks de Emailit en Rails.

Actualizado el 1 oct 2026

En esta guía se explica cómo enviar el correo de Rails a través de Emailit. Puedes usar el método de entrega de Action Mailer de la gema emailit, que envía a través de la API, o apuntar la configuración SMTP de Action Mailer al relay de Emailit. También se explica cómo llamar directamente a la API y cómo verificar los webhooks.

Requisitos previos

  • Ruby 3.0 o posterior y una aplicación Rails.
  • Un dominio de envío verificado, por ejemplo acme.com.
  • Una clave de API. Basta con una clave Sending Only limitada a tu dominio.
  • Hasta que tu espacio de trabajo tenga acceso de producción, solo puedes enviar a las direcciones de email de las cuentas de los miembros del espacio de trabajo.

Instalar la gema

Terminal
bundle add emailit

La gema no tiene dependencias en tiempo de ejecución aparte de la biblioteca estándar de Ruby.

Configurar la clave de API

Guarda la clave en tu entorno o en las credenciales de Rails:

Terminal
bin/rails credentials:edit
YAML
emailit:
  api_key: secret_••••••••••••••••••••••••••••••••
  webhook_secret: whsec_••••••••

Los ejemplos siguientes leen Rails.application.credentials.dig(:emailit, :api_key). Si usas variables de entorno, lee en su lugar ENV.fetch("EMAILIT_API_KEY").

Enviar con Action Mailer

Cuando la gema detecta Rails, registra un método de entrega :emailit. Actívalo en cada entorno:

config/environments/production.rb
config.action_mailer.delivery_method = :emailit
config.action_mailer.emailit_settings = {
  api_key: Rails.application.credentials.dig(:emailit, :api_key)
}

Tus mailers no cambian. La dirección from debe pertenecer a un dominio de envío verificado:

app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
  default from: "Acme <hello@acme.com>"

  def welcome(user)
    @user = user
    mail(to: @user.email, subject: "Welcome to Acme")
  end
end
Ruby
UserMailer.welcome(user).deliver_later

El método de entrega convierte cada mensaje en una petición a la API, con from, to, cc, bcc, reply_to, el asunto, las partes HTML y de texto, y los adjuntos.

Llamar directamente a la API

Para las funciones que Action Mailer no contempla, como las plantillas guardadas o los envíos programados, usa el cliente:

Ruby
client = Emailit::EmailitClient.new(Rails.application.credentials.dig(:emailit, :api_key))

email = client.emails.send(
  from: "Acme <hello@acme.com>",
  to: user.email,
  template: "welcome",
  variables: { first_name: user.first_name },
  scheduled_at: "tomorrow at 9am"
)

email.id # => "em_…"

Los errores se lanzan como excepciones tipadas: Emailit::AuthenticationError (401), Emailit::RateLimitError (429), Emailit::UnprocessableEntityError (422) y Emailit::ApiError para todo lo demás.

Enviar por SMTP

Para usar SMTP sin más, configura la entrega SMTP de Action Mailer:

config/environments/production.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address: "smtp.emailit.com",
  port: 587,
  user_name: "emailit",
  password: Rails.application.credentials.dig(:emailit, :api_key),
  authentication: :plain,
  enable_starttls_auto: true
}

Los mailers y deliver_later funcionan igual. Si tu proveedor de hosting bloquea el puerto 587, usa el 2525 o el 2587. Consulta Configuración SMTP.

Recibir webhooks

Crea un webhook que apunte a https://your-app.com/webhooks/emailit. Añade una ruta y un controlador que verifique la firma con el cuerpo en bruto:

config/routes.rb
post "/webhooks/emailit", to: "emailit_webhooks#create"
app/controllers/emailit_webhooks_controller.rb
class EmailitWebhooksController < ActionController::API
  def create
    payload = request.raw_post
    signature = request.headers["X-Emailit-Signature"].to_s
    timestamp = request.headers["X-Emailit-Timestamp"].to_s

    return head :unauthorized unless valid_signature?(payload, signature, timestamp)

    # The body is a JSON array of up to 100 events.
    JSON.parse(payload).each do |event|
      case event["type"]
      when "email.bounced", "email.complained"
        address = event.dig("data", "object", "to")
        # Stop emailing this address.
      end
    end

    head :ok
  end

  private

  def valid_signature?(payload, signature, timestamp)
    return false if signature.empty? || timestamp.empty?
    return false if (Time.now.to_i - timestamp.to_i).abs > 300

    secret = Rails.application.credentials.dig(:emailit, :webhook_secret)
    expected = OpenSSL::HMAC.hexdigest("SHA256", secret, "#{timestamp}.#{payload}")
    ActiveSupport::SecurityUtils.secure_compare(expected, signature)
  end
end

Al heredar de ActionController::API se omite la protección CSRF, que Emailit no puede satisfacer. Devuelve un 2xx en menos de 30 segundos y pasa el trabajo lento a Active Job. Consulta Firma de las peticiones.

Consejos para producción

  • Entrega más tarde. Usa deliver_later para que las peticiones web no esperen al email, y limita el ritmo de los jobs masivos para no superar tus límites de envío (2 emails por segundo por defecto).
  • Mantén el desarrollo seguro. En desarrollo, usa :letter_opener, :test o una clave de preproducción aparte para no enviar emails a usuarios reales por accidente.
  • Elimina los webhooks duplicados. Guarda cada event_id que procesas; las entregas fallidas se reintentan y pueden llegar más de una vez.
  • Rota las claves sin interrupciones desplegando una clave nueva antes de eliminar la antigua. Consulta Claves de API.

Próximos pasos

Adjuntos, programación y seguimiento.
Diseña emails en Emailit y envíalos por su alias.
Todos los eventos y su payload.
Corrige los errores de autenticación y de conexión.

¿Te ha resultado útil esta página?

Gracias por tu opinión.

Gracias. Leemos todos los mensajes.