Tutorial
Invia email con Ruby on Rails
Consegna le email di Action Mailer tramite Emailit con la gem emailit o con le impostazioni SMTP, chiama direttamente l’API e verifica i webhook di Emailit in Rails.
Questa guida mostra come inviare le email di Rails tramite Emailit. Puoi usare il delivery method di Action Mailer della gem emailit, che invia tramite l’API, oppure indirizzare le impostazioni SMTP di Action Mailer al relay di Emailit. Spiega anche come chiamare direttamente l’API e come verificare i webhook.
Prerequisiti
- Ruby 3.0 o versioni successive e un’app Rails.
- Un dominio di invio verificato, ad esempio
acme.com. - Una chiave API. Basta una chiave di solo invio limitata al tuo dominio.
- Finché il workspace non ha l’accesso alla produzione, puoi inviare solo agli indirizzi email degli account dei membri del workspace.
Installa la gem
bundle add emailitLa gem non ha dipendenze di runtime oltre alla libreria standard di Ruby.
Configura la chiave API
Salva la chiave nell’ambiente o nelle credentials di Rails:
bin/rails credentials:editemailit:
api_key: secret_••••••••••••••••••••••••••••••••
webhook_secret: whsec_••••••••Gli esempi seguenti leggono Rails.application.credentials.dig(:emailit, :api_key). Se usi le variabili d’ambiente, leggi invece ENV.fetch("EMAILIT_API_KEY").
Invia con Action Mailer
Quando la gem rileva Rails, registra un delivery method :emailit. Attivalo per ambiente:
config.action_mailer.delivery_method = :emailit
config.action_mailer.emailit_settings = {
api_key: Rails.application.credentials.dig(:emailit, :api_key)
}I tuoi mailer non cambiano. L’indirizzo from deve appartenere a un dominio di invio verificato:
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_laterIl delivery method converte ogni messaggio in una richiesta API, compresi from, to, cc, bcc, reply_to, l’oggetto, le parti HTML e di testo e gli allegati.
Chiama direttamente l’API
Per le funzioni che Action Mailer non prevede, come i template salvati o gli invii programmati, usa il client:
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_…"Gli errori vengono sollevati come eccezioni tipizzate: Emailit::AuthenticationError (401), Emailit::RateLimitError (429), Emailit::UnprocessableEntityError (422) e Emailit::ApiError per tutto il resto.
Invia con SMTP
Per usare il semplice SMTP, configura la consegna SMTP di 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
}I mailer e deliver_later funzionano allo stesso modo. Se il tuo host blocca la porta 587, usa la 2525 o la 2587. Vedi Impostazioni SMTP.
Ricevi i webhook
Crea un webhook che punta a https://your-app.com/webhooks/emailit. Aggiungi una route e un controller che verifica la firma sul corpo grezzo:
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
endEreditare da ActionController::API salta la protezione CSRF, che Emailit non può soddisfare. Restituisci un 2xx entro 30 secondi e sposta il lavoro lento in Active Job. Vedi Firma delle richieste.
Consigli per la produzione
- Consegna in differita. Usa
deliver_latercosì le richieste web non attendono le email, e limita la velocità dei job massivi per restare entro i limiti di invio (2 email al secondo per impostazione predefinita). - Rendi sicuro lo sviluppo. In sviluppo usa
:letter_opener,:testo una chiave di staging separata, così non invii email a utenti reali per sbaglio. - Elimina i webhook duplicati. Salva ogni
event_idche elabori; le consegne non riuscite vengono ritentate e possono arrivare più di una volta. - Ruota le chiavi senza interruzioni distribuendo una nuova chiave prima di eliminare quella vecchia. Vedi Chiavi API.