Rails · Ruby
Block disposable email in Rails
Custom ActiveModel validator on User#email. Works with Devise, Sorcery, or hand-rolled signup controllers.
The code
# app/validators/not_disposable_email_validator.rb
class NotDisposableEmailValidator < ActiveModel::EachValidator
PIISEND_URL = "https://api.piisend.com/api/v1/intelligence/email"
def validate_each(record, attribute, value)
return if value.blank?
begin
response = HTTParty.post(
PIISEND_URL,
headers: {
"Authorization" => "Bearer #{ENV['PIISEND_API_KEY']}",
"Content-Type" => "application/json",
},
body: { email: value }.to_json,
timeout: 5,
)
if response.success? && response.parsed_response.dig("signals", "disposable")
record.errors.add(attribute, "Please use a permanent email address.")
end
rescue StandardError
# fail open
end
end
end
# app/models/user.rb
class User < ApplicationRecord
validates :email, not_disposable_email: true
endAPI key
Set `PIISEND_API_KEY` in credentials or ENV — use `dotenv-rails` locally.
Fail-open vs fail-closed
Rescue block skips validation on errors.
Pair with verification
Add the validator before Devise's `:validatable` or inside a custom RegistrationsController.
Send verification email with Piisend
After blocking disposable addresses, send OTP and verification mail through the same Piisend account. One API key for intelligence checks and transactional sends.