Tutorial
Enviar e-mails com Ruby on Rails
Entregue os e-mails do Action Mailer pelo Emailit com a gem emailit ou com configurações de SMTP, chame a API diretamente e verifique os webhooks do Emailit no Rails.
Este guia mostra como enviar os e-mails do Rails pelo Emailit. Você pode usar o delivery method do Action Mailer da gem emailit, que envia pela API, ou apontar as configurações de SMTP do Action Mailer para o relay do Emailit. Ele também aborda como chamar a API diretamente e verificar webhooks.
Pré-requisitos
- Ruby 3.0 ou mais recente e uma aplicação Rails.
- Um domínio de envio verificado, por exemplo,
acme.com. - Uma chave de API. Uma chave Sending Only restrita ao seu domínio é suficiente.
- Até o seu workspace ter acesso de produção, você só pode enviar para os e-mails das contas dos membros do workspace.
Instalar a gem
bundle add emailitA gem não tem dependências de runtime além da biblioteca padrão do Ruby.
Configurar a chave de API
Guarde a chave no seu ambiente ou nas credentials do Rails:
bin/rails credentials:editemailit:
api_key: secret_••••••••••••••••••••••••••••••••
webhook_secret: whsec_••••••••Os exemplos abaixo leem Rails.application.credentials.dig(:emailit, :api_key). Se você usa variáveis de ambiente, leia ENV.fetch("EMAILIT_API_KEY").
Enviar com o Action Mailer
Quando a gem detecta o Rails, ela registra um delivery method :emailit. Ative-o por ambiente:
config.action_mailer.delivery_method = :emailit
config.action_mailer.emailit_settings = {
api_key: Rails.application.credentials.dig(:emailit, :api_key)
}Os seus mailers não mudam. O endereço from deve estar em um domínio de envio verificado:
class UserMailer < ApplicationMailer
default from: "Acme <hello@acme.com>"
def welcome(user)
@user = user
mail(to: @user.email, subject: "Welcome to Acme")
end
endUserMailer.welcome(user).deliver_laterO delivery method converte cada mensagem em uma requisição à API, incluindo from, to, cc, bcc, reply_to, o assunto, as partes HTML e de texto e os anexos.
Chamar a API diretamente
Para recursos que o Action Mailer não modela, como templates salvos ou envios agendados, use o cliente:
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_…"Os erros são lançados como exceções tipadas: Emailit::AuthenticationError (401), Emailit::RateLimitError (429), Emailit::UnprocessableEntityError (422) e Emailit::ApiError para todo o resto.
Enviar por SMTP como alternativa
Para usar SMTP simples, configure a entrega SMTP do Action Mailer:
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
}Os mailers e o deliver_later funcionam da mesma forma. Se o seu host bloquear a porta 587, use 2525 ou 2587. Consulte Configurações de SMTP.
Receber webhooks
Crie um webhook que aponte para https://your-app.com/webhooks/emailit. Adicione uma rota e um controller que verifique a assinatura com base no corpo bruto:
post "/webhooks/emailit", to: "emailit_webhooks#create"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
endHerdar de ActionController::API dispensa a proteção contra CSRF, que o Emailit não consegue atender. Retorne um 2xx em até 30 segundos e passe o trabalho demorado para o Active Job. Consulte Assinatura das requisições.
Dicas para produção
- Entregue depois. Use
deliver_laterpara que as requisições web não esperem pelo e-mail e limite o ritmo dos jobs em massa para ficar dentro dos seus limites de envio (2 e-mails por segundo por padrão). - Mantenha o desenvolvimento seguro. Use
:letter_opener,:testou uma chave de homologação separada em desenvolvimento para não enviar e-mails a usuários reais por engano. - Elimine webhooks duplicados. Guarde cada
event_idque você processa; as entregas com falha recebem novas tentativas e podem chegar mais de uma vez. - Faça a rotação das chaves sem interrupção fazendo o deploy de uma chave nova antes de excluir a antiga. Consulte Chaves de API.