Vérification d'e-mails dans Ruby on Rails
Ce tutoriel ajoute la vérification d'e-mails à une application Rails à l'aide d'un ActiveModel::EachValidator maison. Il s'insère dans le pipeline de validation standard de Rails, donc il fonctionne avec valid?, save! et create!.
Prérequis
- Ruby 3.0+, Rails 7+
- Une clé d'API Mailbeam (inscription gratuite)
Mise en place
# Gemfile — net/http (intégré) ou faraday
gem 'faraday' # facultatif, mais plus propre pour les appels d'APIAjoutez ceci à config/credentials.yml.enc (via rails credentials:edit) :
mailbeam:
key: mb_live_xxxxxxxxxxxxxxxxxxxxCréer le validateur
# app/validators/mailbeam_validator.rb
require 'faraday'
require 'json'
class MailbeamValidator < ActiveModel::EachValidator
MIN_SCORE = options[:min_score] || 60
def validate_each(record, attribute, value)
return if value.blank?
result = verify_email(value.downcase.strip)
return if result.nil? # erreur d'API — échec permissif
unless result['valid'] && result['score'].to_i >= MIN_SCORE
reason = result['reason']
message = case reason
when 'disposable_domain' then "ne doit pas être une adresse temporaire"
when 'no_mx_records' then "correspond à un domaine qui ne reçoit pas de courrier"
when 'smtp_rejected' then "ne semble pas exister"
else "n'est pas une adresse e-mail valide"
end
record.errors.add(attribute, message)
end
end
private
def verify_email(email)
conn = Faraday.new('https://api.mailbeam.dev') do |f|
f.request :json
f.response :json
f.adapter Faraday.default_adapter
end
response = conn.post('/v1/verify', { email: email }) do |req|
req.headers['Authorization'] = "Bearer #{Rails.application.credentials.mailbeam.key}"
req.options.timeout = 5
end
response.body if response.success?
rescue StandardError => e
Rails.logger.error "[Mailbeam] échec de la vérification : #{e.message}"
nil # échec permissif
end
endL'ajouter à votre modèle User
# app/models/user.rb
class User < ApplicationRecord
validates :email,
presence: true,
format: { with: URI::MailTo::EMAIL_REGEXP },
uniqueness: { case_sensitive: false },
mailbeam: true # notre validateur maison
endTests RSpec
# spec/validators/mailbeam_validator_spec.rb
RSpec.describe MailbeamValidator do
let(:user) { build(:user, email: email) }
before do
stub_request(:post, 'https://api.mailbeam.dev/v1/verify')
.to_return(status: 200, body: response_body.to_json)
end
context 'avec une adresse valide' do
let(:email) { 'user@example.com' }
let(:response_body) { { valid: true, score: 94, reason: nil } }
it { expect(user).to be_valid }
end
context 'avec une adresse jetable' do
let(:email) { 'temp@mailinator.com' }
let(:response_body) { { valid: false, score: 2, reason: 'disposable_domain' } }
it 'ajoute une erreur' do
user.valid?
expect(user.errors[:email]).to include("ne doit pas être une adresse temporaire")
end
end
context "quand l'API Mailbeam est indisponible" do
let(:email) { 'user@example.com' }
before { stub_request(:post, anything).to_raise(Faraday::Error) }
it 'échoue en mode permissif (aucune erreur ajoutée)' do
expect(user).to be_valid
end
end
end