valid_email-0.2.1/0000755000004100000410000000000014620063664014017 5ustar www-datawww-datavalid_email-0.2.1/.gitignore0000644000004100000410000000004714620063664016010 0ustar www-datawww-data*.swp *.gem .bundle Gemfile.lock pkg/* valid_email-0.2.1/.github/0000755000004100000410000000000014620063664015357 5ustar www-datawww-datavalid_email-0.2.1/.github/workflows/0000755000004100000410000000000014620063664017414 5ustar www-datawww-datavalid_email-0.2.1/.github/workflows/ci.yaml0000644000004100000410000000152214620063664020673 0ustar www-datawww-dataname: CI on: workflow_dispatch: push: permissions: checks: write contents: read pull-requests: write jobs: rspec: name: RSpec (ruby ${{ matrix.ruby-version }}) runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: ruby-version: - '1.9.3' - '2.0' - '2.1' - '2.2' - '2.3' - '2.4' - '2.5' - '2.6' - '2.7' - '3.0' - '3.1' - '3.2' - 'jruby-head' - 'truffleruby-head' env: CI: true steps: - name: Checkout uses: actions/checkout@v3 - name: Setup ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true - name: Run tests run: bundle exec rake valid_email-0.2.1/lib/0000755000004100000410000000000014620063664014565 5ustar www-datawww-datavalid_email-0.2.1/lib/valid_email/0000755000004100000410000000000014620063664017033 5ustar www-datawww-datavalid_email-0.2.1/lib/valid_email/validate_email.rb0000644000004100000410000001054514620063664022325 0ustar www-datawww-datarequire 'mail' require 'simpleidn' class ValidateEmail class << self SPECIAL_CHARS = %w(( ) , : ; < > @ [ ]) SPECIAL_ESCAPED_CHARS = %w(\ \\ ") LOCAL_MAX_LEN = 64 DOMAIN_REGEX = /\A(?:[[:alnum:]](?:[[[:alnum:]]-]{0,61}[[:alnum:]])?)(?:\.(?:[[:alnum:]](?:[[[:alnum:]]-]{0,61}[[:alnum:]])?))+\z/ def valid?(value, user_options={}) options = { :mx => false, :domain => true, :message => nil }.merge(user_options) m = Mail::Address.new(value) # We must check that value contains a domain and that value is an email address return false unless m.domain && m.address == value # Check that domain consists of dot-atom-text elements > 1 and does not # contain spaces. # # In mail 2.6.1, domains are invalid per rfc2822 are parsed when they shouldn't # This is to make sure we cover those cases return false unless m.domain.match(/^\S+$/) domain_dot_elements = m.domain.split(/\./) return false unless domain_dot_elements.size > 1 && domain_dot_elements.none?(&:empty?) # Ensure that the local segment adheres to adheres to RFC-5322 return false unless valid_local?(m.local) # Check if domain has DNS MX record if options[:mx] require 'valid_email/mx_validator' return mx_valid?(value) end if options[:domain] require 'valid_email/domain_validator' return domain_valid?(value) end true rescue Mail::Field::ParseError false rescue ArgumentError => error if error.message == 'bad value for range' false else raise error end end def valid_local?(local) return false unless local.length <= LOCAL_MAX_LEN # Emails can be validated by segments delineated by '.', referred to as dot atoms. # See http://tools.ietf.org/html/rfc5322#section-3.2.3 return local.split('.', -1).all? { |da| valid_dot_atom?(da) } end def valid_dot_atom?(dot_atom) # Leading, trailing, and double '.'s aren't allowed return false if dot_atom.empty? # A dot atom can be quoted, which allows use of the SPECIAL_CHARS if dot_atom[0] == '"' || dot_atom[-1] == '"' # A quoted segment must have leading and trailing '"#"'s return false if dot_atom[0] != dot_atom[-1] # Excluding the bounding quotes, all of the SPECIAL_ESCAPED_CHARS must have a leading '\' index = dot_atom.length - 2 while index > 0 if SPECIAL_ESCAPED_CHARS.include? dot_atom[index] return false if index == 1 || dot_atom[index - 1] != '\\' # On an escaped special character, skip an index to ignore the '\' that's doing the escaping index -= 1 end index -= 1 end else # If we're not in a quoted dot atom then no special characters are allowed. return false unless ((SPECIAL_CHARS | SPECIAL_ESCAPED_CHARS) & dot_atom.split('')).empty? end return true end def mx_valid?(value, fallback=false) m = Mail::Address.new(value) return false unless m.domain if m.domain.ascii_only? ascii_domain = m.domain else ascii_domain = SimpleIDN.to_ascii(m.domain) end Resolv::DNS.open do |dns| dns.timeouts = MxValidator.config[:timeouts] unless MxValidator.config[:timeouts].empty? return dns.getresources(ascii_domain, Resolv::DNS::Resource::IN::MX).size > 0 || ( fallback && dns.getresources(ascii_domain, Resolv::DNS::Resource::IN::A).size > 0 ) end rescue Mail::Field::ParseError false end def mx_valid_with_fallback?(value) mx_valid?(value, true) end def domain_valid?(value) m = Mail::Address.new(value) return false unless m.domain !(m.domain =~ DOMAIN_REGEX).nil? rescue Mail::Field::ParseError false end def ban_disposable_email?(value) m = Mail::Address.new(value) m.domain && !BanDisposableEmailValidator.config.include?(m.domain) rescue Mail::Field::ParseError false end def ban_partial_disposable_email?(value) m = Mail::Address.new(value) m.domain && !BanDisposableEmailValidator.config.any? do |bde| next if bde == nil m.domain.end_with?(bde) end rescue Mail::Field::ParseError false end end end valid_email-0.2.1/lib/valid_email/email_validator.rb0000644000004100000410000000232714620063664022520 0ustar www-datawww-datarequire 'active_model' require 'active_model/validations' require 'valid_email/validate_email' class EmailValidator < ActiveModel::EachValidator def validate_each(record,attribute,value) return if options[:allow_nil] && value.nil? return if options[:allow_blank] && value.blank? r = ValidateEmail.valid?(value) # Check if domain has DNS MX record if r && options[:mx] require 'valid_email/mx_validator' r = MxValidator.new(:attributes => attributes, message: options[:message]).validate(record) elsif r && options[:mx_with_fallback] require 'valid_email/mx_with_fallback_validator' r = MxWithFallbackValidator.new(:attributes => attributes, message: options[:message]).validate(record) end # Check if domain is disposable if r && options[:ban_disposable_email] require 'valid_email/ban_disposable_email_validator' r = BanDisposableEmailValidator.new(:attributes => attributes, message: options[:message], partial: options[:partial]).validate(record) end unless r msg = (options[:message] || I18n.t(:invalid, :scope => "valid_email.validations.email")) record.errors.add attribute, message: I18n.interpolate(msg, value: value) end end end valid_email-0.2.1/lib/valid_email/mx_with_fallback_validator.rb0000644000004100000410000000056214620063664024726 0ustar www-datawww-datarequire 'valid_email/mx_validator' require 'valid_email/validate_email' class MxWithFallbackValidator < ActiveModel::EachValidator def validate_each(record,attribute,value) r = ValidateEmail.mx_valid_with_fallback?(value) record.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => "valid_email.validations.email")) unless r r end end valid_email-0.2.1/lib/valid_email/mx_validator.rb0000644000004100000410000000074014620063664022052 0ustar www-datawww-datarequire 'active_model' require 'active_model/validations' require 'resolv' require 'valid_email/validate_email' class MxValidator < ActiveModel::EachValidator def self.config @@config = { timeouts: [] } unless defined? @@config @@config end def validate_each(record,attribute,value) r = ValidateEmail.mx_valid?(value) record.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => "valid_email.validations.email")) unless r r end end valid_email-0.2.1/lib/valid_email/ban_disposable_email_validator.rb0000644000004100000410000000165714620063664025552 0ustar www-datawww-datarequire 'active_model' require 'active_model/validations' require 'valid_email/validate_email' class BanDisposableEmailValidator < ActiveModel::EachValidator # A list of disposable email domains def self.config=(options) @@config = options end # Required to use config outside def self.config @@config = [] unless defined? @@config @@config end def validate_each(record, attribute, value) # Check if part of domain is in disposable_email_services yml list if options[:partial] r = ValidateEmail.ban_partial_disposable_email?(value) record.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => "valid_email.validations.email")) unless r r else r = ValidateEmail.ban_disposable_email?(value) record.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => "valid_email.validations.email")) unless r r end end end valid_email-0.2.1/lib/valid_email/all_with_extensions.rb0000644000004100000410000000025614620063664023445 0ustar www-datawww-datarequire 'valid_email' class String def email?(options={}) ValidateEmail.valid?(self, options) end end class NilClass def email?(options={}) false end endvalid_email-0.2.1/lib/valid_email/all.rb0000644000004100000410000000037314620063664020133 0ustar www-datawww-datarequire 'valid_email/validate_email' require 'valid_email/email_validator' require 'valid_email/mx_validator' require 'valid_email/mx_with_fallback_validator' require 'valid_email/ban_disposable_email_validator' require 'valid_email/domain_validator' valid_email-0.2.1/lib/valid_email/version.rb0000644000004100000410000000003414620063664021042 0ustar www-datawww-dataValidEmailVersion = "0.2.1" valid_email-0.2.1/lib/valid_email/domain_validator.rb0000644000004100000410000000057314620063664022701 0ustar www-datawww-datarequire 'active_model' require 'active_model/validations' require 'valid_email/validate_email' class DomainValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) r = ValidateEmail.domain_valid?(value) record.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => "valid_email.validations.email")) unless r r end end valid_email-0.2.1/lib/valid_email.rb0000644000004100000410000000047214620063664017363 0ustar www-datawww-datarequire 'valid_email/all' I18n.load_path += Dir.glob(File.expand_path('../../config/locales/**/*',__FILE__)) # Load list of disposable email domains config = File.expand_path('../../config/valid_email.yml',__FILE__) BanDisposableEmailValidator.config= YAML.load_file(config)['disposable_email_services'] rescue [] valid_email-0.2.1/spec/0000755000004100000410000000000014620063664014751 5ustar www-datawww-datavalid_email-0.2.1/spec/spec_helper.rb0000644000004100000410000000036614620063664017574 0ustar www-datawww-data$:.unshift File.expand_path('../../lib',__FILE__) require 'valid_email' RSpec.configure do |config| config.order = :random config.raise_errors_for_deprecations! Kernel.srand config.seed if ENV['CI'] config.warnings = true end end valid_email-0.2.1/spec/email_validator_spec.rb0000644000004100000410000002445614620063664021457 0ustar www-datawww-datarequire 'spec_helper' RSpec::Matchers.define :have_error_messages do |field, expected| match do |model| errors = model.errors[field] messages = errors.map do |error| case error when String then error when Hash then error[:message] else fail ArgumentError, "Unknown model error type #{error.class}" end end expect(messages).to eq expected end end describe EmailValidator do email_class = Class.new do include ActiveModel::Validations attr_accessor :email def self.model_name ActiveModel::Name.new(self, nil, "TestModel") end end person_class = Class.new(email_class) do validates :email, :email => true end person_class_mx = Class.new(email_class) do validates :email, :email => {:mx => true} end person_class_mx_with_fallback = Class.new(email_class) do validates :email, :email => {:mx_with_fallback => true} end person_class_disposable_email = Class.new(email_class) do validates :email, :email => {:ban_disposable_email => true} end person_class_partial_disposable_email = Class.new(email_class) do validates :email, :email => {:ban_disposable_email => true, :partial => true} end person_class_nil_allowed = Class.new(email_class) do validates :email, :email => {:allow_nil => true} end person_class_blank_allowed = Class.new(email_class) do validates :email, :email => {:allow_blank => true} end person_class_mx_separated = Class.new(email_class) do validates :email, :mx => true end person_class_mx_with_fallback_separated = Class.new(email_class) do validates :email, :mx_with_fallback => true end person_class_domain = Class.new(email_class) do validates :email, :domain => true end person_message_specified = Class.new(email_class) do validates :email, :email => { :message => 'custom message', :ban_disposable_email => true } end shared_examples_for "Invalid model" do before { subject.valid? } it { is_expected.not_to be_valid } specify { expect(subject.errors[:email]).to match_array errors } end shared_examples_for "Validating emails" do before :each do I18n.locale = locale end describe "validating email" do subject { person_class.new } it "fails when email empty" do expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "fails when email is not valid" do subject.email = 'joh@doe' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "fails when email domain is prefixed with dot" do subject.email = 'john@.doe' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "fails when email domain contains two consecutive dots" do subject.email = 'john@doe-two..com' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "fails when email ends with a period" do subject.email = 'john@doe.com.' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "fails when email ends with special characters" do subject.email = 'john@doe.com&' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "fails when email is valid with information" do subject.email = '"John Doe" ' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "passes when email is simple email address" do subject.email = 'john@doe.com' expect(subject.valid?).to be_truthy expect(subject.errors[:email]).to be_empty end it "fails when email is simple email address not stripped" do subject.email = 'john@doe.com ' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "fails when domain contains a space" do subject.email = 'john@doe .com' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "fails when passing multiple simple email addresses" do subject.email = 'john@doe.com, maria@doe.com' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end end describe "validating email with MX and fallback to A" do let(:dns) { instance_double('Resolv::DNS', :dns) } subject { person_class_mx_with_fallback.new } before do allow(Resolv::DNS).to receive(:open).and_yield(dns) end it "passes when email domain has MX record" do allow(dns).to receive(:getresources).with('has-mx-record.org', Resolv::DNS::Resource::IN::MX).and_return(['1.2.3.4']) subject.email = 'john@has-mx-record.org' expect(subject.valid?).to be_truthy expect(subject.errors[:email]).to be_empty end it "passes when email domain has no MX record but has an A record" do allow(dns).to receive(:getresources).with('has-a-record.org', Resolv::DNS::Resource::IN::MX).and_return([]) allow(dns).to receive(:getresources).with('has-a-record.org', Resolv::DNS::Resource::IN::A).and_return(['1.2.3.4']) subject.email = 'john@has-a-record.org' expect(subject.valid?).to be_truthy expect(subject.errors[:email]).to be_empty end it "fails when domain does not exists" do allow(dns).to receive(:getresources).with('does-not-exist.org', anything).and_return([]) subject.email = 'john@does-not-exist.org' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end end describe "validating email with MX" do subject { person_class_mx.new } it "passes when email domain has MX record" do subject.email = 'john@gmail.com' expect(subject.valid?).to be_truthy expect(subject.errors[:email]).to be_empty end it "fails when email domain has no MX record" do subject.email = 'john@subdomain.rubyonrails.org' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "fails when domain does not exists" do subject.email = 'john@nonexistentdomain.abc' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end end describe "validating MX with fallback to A" do subject { person_class_mx_with_fallback_separated.new } context "when domain is not specified" do before { subject.email = 'john' } it_behaves_like "Invalid model" end context "when domain is not specified but @ is" do before { subject.email = 'john@' } it_behaves_like "Invalid model" end end describe "validating MX" do subject { person_class_mx_separated.new } context "when domain is not specified" do before { subject.email = 'john' } it_behaves_like "Invalid model" end context "when domain is not specified but @ is" do before { subject.email = 'john@' } it_behaves_like "Invalid model" end end describe "validating email from disposable service" do subject { person_class_disposable_email.new } it "passes when email from trusted email services" do subject.email = 'john@mail.ru' expect(subject.valid?).to be_truthy expect(subject.errors[:email]).to be_empty end it "fails when email from disposable email services" do subject.email = 'john@grr.la' expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end end describe "validating email against partial disposable service match" do subject { person_class_partial_disposable_email.new } it "passes when email from trusted email services" do subject.email = 'john@test.mail.ru' expect(subject.valid?).to be_truthy expect(subject.errors[:email]).to be_empty end it "fails when disposable email services partially matches email domain" do subject.email = 'john@sub.grr.la' expect(subject.valid?).to be_falsey expect(subject.errors[:email]).to eq errors end end describe "validating domain" do subject { person_class_domain.new } it "does not pass with an invalid domain" do subject.email = "test@example.org$\'" expect(subject.valid?).to be_falsey expect(subject).to have_error_messages(:email, errors) end it "passes with valid domain" do subject.email = 'john@example.org' expect(subject.valid?).to be_truthy expect(subject.errors[:email]).to be_empty end end end describe "Can allow nil" do subject { person_class_nil_allowed.new } it "passes even if mail isn't set" do subject.email = nil expect(subject).to be_valid expect(subject.errors[:email]).to be_empty end end describe "Can allow blank" do subject { person_class_blank_allowed.new } it "passes even if mail is a blank string set" do subject.email = '' expect(subject).to be_valid expect(subject.errors[:email]).to be_empty end end describe "Accepts custom messages" do subject { person_message_specified.new } it "adds only the custom error" do subject.email = 'bad@mailnator.com' expect(subject.valid?).to be_falsey expect(subject.errors[:email]).to match_array [ 'custom message' ] end end describe "Translating in english" do let!(:locale){ :en } let!(:errors) { [ "is invalid" ] } it_behaves_like "Validating emails" end describe "Translating in french" do let!(:locale){ :fr } let!(:errors) { [ "est invalide" ] } it_behaves_like "Validating emails" end describe 'Translating in czech' do let!(:locale){ :cs } let!(:errors) do [ I18n.t( :invalid, locale: locale, scope: [:valid_email, :validations, :email] ) ] end it_behaves_like 'Validating emails' end end valid_email-0.2.1/spec/validate_email_spec.rb0000644000004100000410000001140614620063664021252 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' describe ValidateEmail do describe '.valid?' do it 'returns true when passed email has valid format' do expect(ValidateEmail.valid?('user@gmail.com')).to be_truthy expect(ValidateEmail.valid?('valid.user@gmail.com')).to be_truthy end it 'returns false when passed email has invalid format' do expect(ValidateEmail.valid?('user@gmail.com.')).to be_falsey expect(ValidateEmail.valid?('user.@gmail.com')).to be_falsey expect(ValidateEmail.valid?('Hgft@(()).com')).to be_falsey end context 'when mx: true option passed' do let(:dns) { Resolv::DNS.new } def mock_dns_mx allow(dns).to receive(:getresources).and_return([]) allow(Resolv::DNS).to receive(:new).and_return(dns) end it 'returns true when mx record exist' do expect(ValidateEmail.valid?('user@gmail.com', mx: true)).to be_truthy end it "returns false when mx record doesn't exist" do mock_dns_mx expect(ValidateEmail.valid?('user@example.com', mx: true)).to be_falsey end it "IDN-encodes the domain name if it contains multibyte characters" do mock_dns_mx ValidateEmail.valid?("user@\u{1F600}.com", mx: true) expect(dns).to have_received(:getresources).with('xn--e28h.com', anything) end end context 'when domain: true option passed' do context 'with valid domains' do valid_domains = [ 'example.org', '0-mail.com', '0815.ru', '0clickemail.com', 'test.co.uk', 'fux0ringduh.com', 'girlsundertheinfluence.com', 'h.mintemail.com', 'mail-temporaire.fr', 'mt2009.com', 'mega.zik.dj', '0.test.com', 'e.test.com', 'mail.e.test.com', 'a.aa', 'test.xn--clchc0ea0b2g2a9gcd', 'my-domain.com', 'тест.рф', 'mail.тест.рф', 'umläüt-domain.de', ] valid_domains.each do |valid_domain| it "returns true for #{valid_domain}" do email = "john@#{valid_domain}" expect(ValidateEmail.valid?(email, domain: true)).to be_truthy end end end context 'with invalid domain' do invalid_domains = [ '-eouae.test', 'oue-.test', 'oeuoue.-oeuoue', 'oueaaoeu.oeue-', 'ouoeu.eou_ueoe', '.test.com', 'test..com', 'test@test.com', "example.org$\'", "foo bar.com", ] invalid_domains.each do |invalid_domain| it "returns false for #{invalid_domain}" do email = "john@#{invalid_domain}" expect(ValidateEmail.valid?(email, domain: true)).to be_falsey end end end end end describe '.valid_local?' do it 'returns false if the local segment is too long' do expect( ValidateEmail.valid_local?( 'abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde' ) ).to be_falsey end it 'returns false if the local segment has an empty dot atom' do expect(ValidateEmail.valid_local?('.user')).to be_falsey expect(ValidateEmail.valid_local?('.user.')).to be_falsey expect(ValidateEmail.valid_local?('user.')).to be_falsey expect(ValidateEmail.valid_local?('us..er')).to be_falsey end it 'returns false if the local segment has a special character in an unquoted dot atom' do expect(ValidateEmail.valid_local?('us@er')).to be_falsey expect(ValidateEmail.valid_local?('user.\\.name')).to be_falsey expect(ValidateEmail.valid_local?('user."name')).to be_falsey end it 'returns false if the local segment has an unescaped special character in a quoted dot atom' do expect(ValidateEmail.valid_local?('test." test".test')).to be_falsey expect(ValidateEmail.valid_local?('test."test\".test')).to be_falsey expect(ValidateEmail.valid_local?('test."te"st".test')).to be_falsey expect(ValidateEmail.valid_local?('test."\".test')).to be_falsey end it 'returns true if special characters exist but are properly quoted and escaped' do expect(ValidateEmail.valid_local?('"\ test"')).to be_truthy expect(ValidateEmail.valid_local?('"\\\\"')).to be_truthy expect(ValidateEmail.valid_local?('test."te@st".test')).to be_truthy expect(ValidateEmail.valid_local?('test."\\\\\"".test')).to be_truthy expect(ValidateEmail.valid_local?('test."blah\"\ \\\\"')).to be_truthy end it 'returns true if all characters are within the set of allowed characters' do expect(ValidateEmail.valid_local?('!#$%&\'*+-/=?^_`{|}~."\\\\\ \"(),:;<>@[]"')).to be_truthy end end end valid_email-0.2.1/spec/extensions_validator_spec.rb0000644000004100000410000000067714620063664022566 0ustar www-datawww-datarequire 'spec_helper' require 'valid_email/all_with_extensions' describe String do it { expect("mymail@gmail").to respond_to(:email?) } it "is a valid e-mail" do expect("mymail@gmail.com".email?).to be_truthy end it "is not valid when text is not a real e-mail" do expect("invalidMail".email?).to be_falsey end context "when nil" do it "is invalid e-mail" do expect(nil.email?).to be_falsey end end end valid_email-0.2.1/.rspec0000644000004100000410000000000014620063664015122 0ustar www-datawww-datavalid_email-0.2.1/Rakefile0000644000004100000410000000030514620063664015462 0ustar www-datawww-datarequire "bundler/gem_tasks" require 'rspec/core/rake_task' desc "Run specs" RSpec::Core::RakeTask.new do |t| t.pattern = 'spec/**/*_spec.rb' end task :default => [:spec] task :build => [:spec] valid_email-0.2.1/valid_email.gemspec0000644000004100000410000000233514620063664017635 0ustar www-datawww-data# -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) require "valid_email/version" Gem::Specification.new do |s| s.name = "valid_email" s.version = ValidEmailVersion s.authors = ["Ramihajamalala Hery"] s.email = ["hery@rails-royce.org"] s.homepage = "https://github.com/hallelujah/valid_email" s.summary = %q{ActiveModel Validation for email} s.description = %q{ActiveModel Validation for email} s.license = 'MIT' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] # specify any dependencies here; for example: s.add_development_dependency "rspec", "~> 3.10" s.add_development_dependency "rake" s.add_runtime_dependency "mail", ">= 2.6.1" s.add_runtime_dependency "simpleidn" if Gem::Version.new(RUBY_VERSION.dup) <= Gem::Version.new('2.0') s.add_runtime_dependency 'mime-types', '<= 2.6.2' end if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.2.2') s.add_runtime_dependency "activemodel", '< 5.0.0' else s.add_runtime_dependency "activemodel" end end valid_email-0.2.1/Gemfile0000644000004100000410000000014314620063664015310 0ustar www-datawww-datasource "http://rubygems.org" # Specify your gem's dependencies in email_validator.gemspec gemspec valid_email-0.2.1/LICENSE0000644000004100000410000000206414620063664015026 0ustar www-datawww-dataCopyright (c) 2011 hallelujah [Ramihajamalala Hery] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. valid_email-0.2.1/README.md0000644000004100000410000001043714620063664015303 0ustar www-datawww-data# Valid Email ## Purpose It validates email for application use (registering a new account for example). ## Usage In your `Gemfile`: ```ruby gem 'valid_email' ``` In your code: ```ruby require 'valid_email' class Person include ActiveModel::Validations attr_accessor :name, :email validates :name, presence: true, length: { maximum: 100 } validates :email, presence: true, email: true end person = Person.new person.name = 'hallelujah' person.email = 'john@doe.com' person.valid? # => true person.email = 'john@doe' person.valid? # => false person.email = 'John Does ' person.valid? # => false ``` You can check if email domain has MX record: ```ruby validates :email, email: { mx: true, message: I18n.t('validations.errors.models.user.invalid_email') } ``` Or ```ruby validates :email, email: { message: I18n.t('validations.errors.models.user.invalid_email') }, mx: { message: I18n.t('validations.errors.models.user.invalid_mx') } ``` By default, the email domain is validated using a regular expression, which does not require an external service and improves performance. Alternatively, you can check if an email domain has a MX or A record by using `:mx_with_fallback` instead of `:mx`. ```ruby validates :email, email: { mx_with_fallback: true } ``` You can detect disposable accounts ```ruby validates :email, email: { ban_disposable_email: true, message: I18n.t('validations.errors.models.user.invalid_email') } ``` You can also detect a partial match on disposable accounts, good for services that use subdomains. ```ruby validates :email, email: { message: I18n.t('validations.errors.models.user.invalid_email') ban_disposable_email: true, partial: true } ``` If you don't want the MX validator stuff, just require the right file ```ruby require 'valid_email/email_validator' ``` Or in your `Gemfile` ```ruby gem 'valid_email', require: 'valid_email/email_validator' ``` ### Usage outside of model validation There is a chance that you want to use e-mail validator outside of model validation. If that's the case, you can use the following methods: ```ruby options = {} # You can optionally pass a hash of options, same as validator ValidateEmail.valid?('email@randommail.com', options) ValidateEmail.mx_valid?('email@randommail.com') ValidateEmail.mx_valid_with_fallback?('email@randommail.com') ValidateEmail.valid?('email@randommail.com') ``` Load it (and not the Rails extensions) with ```ruby gem 'valid_email', require: 'valid_email/validate_email' ``` ### String and Nil object extensions There is also a String and Nil class extension, if you require the gem in this way in `Gemfile`: ```ruby gem 'valid_email', require: 'valid_email/all_with_extensions' ``` You will be able to use the following methods: ```ruby nil.email? # => false 'john@gmail.com'.email? # => May return true if it exists. # It accepts a hash of options like ValidateEmail.valid? ``` ## Code Status [![Build Status](https://github.com/hallelujah/valid_email/actions/workflows/ci.yaml/badge.svg)](https://github.com/hallelujah/valid_email/actions/workflows/ci.yaml) ## Credits * Ramihajamalala Hery hery[at]rails-royce.org * Fire-Dragon-DoL francesco.belladonna[at]gmail.com * dush dusanek[at]iquest.cz * MIke Carter mike[at]mcarter.me * Heng heng[at]reamaze.com * Marco Perrando mperrando[at]soluzioninrete.it * Jörg Thalheim joerg[at]higgsboson.tk * Andrey Deryabin deriabin[at]gmail.com * Nicholas Rutherford nick.rutherford[at]gmail.com * Oleg Shur workshur[at]gmail.com * Joel Chippindale joel[at]joelchippindale.com * Sami Haahtinen sami[at]haahtinen.name * Jean Boussier jean.boussier[at]gmail.com * Masaki Hara - @qnighy ## Pull Requests 1. Fork the project. 2. Make your feature addition or bug fix. 3. Add tests for it. This is important so I don’t break it in a future version unintentionally. 4. Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull) 5. Send me a pull request. Bonus points for topic branches. ## Copyright Copyright © 2011 Ramihajamalala Hery. See LICENSE for details valid_email-0.2.1/config/0000755000004100000410000000000014620063664015264 5ustar www-datawww-datavalid_email-0.2.1/config/locales/0000755000004100000410000000000014620063664016706 5ustar www-datawww-datavalid_email-0.2.1/config/locales/fi.yml0000644000004100000410000000012514620063664020025 0ustar www-datawww-datafi: valid_email: validations: email: invalid: ei ole kelvollinen valid_email-0.2.1/config/locales/ru.yml0000644000004100000410000000015114620063664020054 0ustar www-datawww-dataru: valid_email: validations: email: invalid: "неправильный формат"valid_email-0.2.1/config/locales/cs.yml0000644000004100000410000000011714620063664020035 0ustar www-datawww-datacs: valid_email: validations: email: invalid: je neplatný valid_email-0.2.1/config/locales/uk.yml0000644000004100000410000000015214620063664020046 0ustar www-datawww-datauk: valid_email: validations: email: invalid: "неправильний формат" valid_email-0.2.1/config/locales/nb.yml0000644000004100000410000000011714620063664020027 0ustar www-datawww-datanb: valid_email: validations: email: invalid: "er ugyldig" valid_email-0.2.1/config/locales/pt-BR.yml0000644000004100000410000000012414620063664020352 0ustar www-datawww-datapt-BR: valid_email: validations: email: invalid: "é inválido" valid_email-0.2.1/config/locales/en.yml0000644000004100000410000000011714620063664020032 0ustar www-datawww-dataen: valid_email: validations: email: invalid: "is invalid" valid_email-0.2.1/config/locales/ja.yml0000644000004100000410000000012714620063664020023 0ustar www-datawww-dataja: valid_email: validations: email: invalid: "不正な値です" valid_email-0.2.1/config/locales/sv.yml0000644000004100000410000000012014620063664020052 0ustar www-datawww-datasv: valid_email: validations: email: invalid: "är ogiltig" valid_email-0.2.1/config/locales/id.yml0000644000004100000410000000012014620063664020016 0ustar www-datawww-dataid: valid_email: validations: email: invalid: "tidak valid" valid_email-0.2.1/config/locales/fr.yml0000644000004100000410000000012114620063664020032 0ustar www-datawww-datafr: valid_email: validations: email: invalid: "est invalide" valid_email-0.2.1/config/locales/de.yml0000644000004100000410000000012214620063664020014 0ustar www-datawww-datade: valid_email: validations: email: invalid: "ist ungültig" valid_email-0.2.1/config/locales/pl.yml0000644000004100000410000000013014620063664020036 0ustar www-datawww-datapl: valid_email: validations: email: invalid: "jest nieprawidłowy" valid_email-0.2.1/config/locales/es.yml0000644000004100000410000000012214620063664020033 0ustar www-datawww-dataes: valid_email: validations: email: invalid: "no es válido" valid_email-0.2.1/config/locales/hu.yml0000644000004100000410000000013514620063664020044 0ustar www-datawww-datahu: valid_email: validations: email: invalid: "érvénytelen email cím" valid_email-0.2.1/config/valid_email.yml0000644000004100000410000002251414620063664020261 0ustar www-datawww-datadisposable_email_services: - 0-mail.com - 0815.ru - 0clickemail.com - 0wnd.net - 0wnd.org - 10minutemail.com - 20minutemail.com - 2prong.com - 30minutemail.com - 33mail.com - 3d-painting.com - 4warding.com - 4warding.net - 4warding.org - 60minutemail.com - 675hosting.com - 675hosting.net - 675hosting.org - 6paq.com - 6url.com - 75hosting.com - 75hosting.net - 75hosting.org - 7tags.com - 9ox.net - a-bc.net - acentri.com - afrobacon.com - ajaxapp.net - amail.club - amail4.me - amilegit.com - amiri.net - amiriindustries.com - anonbox.net - anonymbox.com - antichef.com - antichef.net - antispam.de - appixie.com - armyspy.com - azmeil.tk - banit.club - banit.me - baxomale.ht.cx - beefmilk.com - binkmail.com - bio-muesli.net - bobmail.info - bodhi.lawlita.com - bofthew.com - boun.cr - bouncr.com - brefmail.com - broadbandninja.com - bsnow.net - bugmenot.com - bumpymail.com - cars2.club - casualdx.com - centermail.com - centermail.net - chogmail.com - choicemail1.com - cmail.club - cool.fr.nf - correo.blogos.net - cosmorph.com - courriel.fr.nf - courrieltemporaire.com - cubiclink.com - curryworld.de - cust.in - cuvox.de - dacoolest.com - daddymail.biz - dandikmail.com - dayrep.com - deadaddress.com - deadspam.com - despam.it - despammed.com - devnullmail.com - dfgh.net - digitalsanctuary.com - discardmail.com - discardmail.de - disposableaddress.com - disposableemailaddresses.com - disposeamail.com - disposemail.com - dispostable.com - dm.w3internet.co.ukexample.com - dodgeit.com - dodgit.com - dodgit.org - donemail.ru - dontreg.com - dontsendmespam.de - drdrb.com - drdrb.net - droplar.com - duck2.club - dump-email.info - dumpandjunk.com - dumpmail.de - dumpyemail.com - e4ward.com - einrot.com - email60.com - emaildienst.de - emailias.com - emailigo.de - emailinfive.com - emailmiser.com - emailsensei.com - emailtemporario.com.br - emailto.de - emailwarden.com - emailx.at.hm - emailxfer.com - emeil.in - emeil.ir - emz.net - enterto.com - ephemail.net - etranquil.com - etranquil.net - etranquil.org - evopo.com - explodemail.com - fakeinbox.com - fakeinformation.com - fastacura.com - fastchevy.com - fastchrysler.com - fastkawasaki.com - fastmazda.com - fastmitsubishi.com - fastnissan.com - fastsubaru.com - fastsuzuki.com - fasttoyota.com - fastyamaha.com - filzmail.com - fizmail.com - fleckens.hu - fr33mail.info - frapmail.com - front14.org - fux0ringduh.com - garliclife.com - get1mail.com - get2mail.fr - getairmail.com - getnada.com - getonemail.com - getonemail.net - ghosttexter.de - girlsundertheinfluence.com - gishpuppy.com - gowikibooks.com - gowikicampus.com - gowikicars.com - gowikifilms.com - gowikigames.com - gowikimusic.com - gowikinetwork.com - gowikitravel.com - gowikitv.com - great-host.in - greensloth.com - grr.la - gsrv.co.uk - guerillamail.biz - guerillamail.com - guerillamail.net - guerillamail.org - guerrillamail.biz - guerrillamail.com - guerrillamail.de - guerrillamail.net - guerrillamail.org - guerrillamailblock.com - gustr.com - h.mintemail.com - h8s.org - haltospam.com - hatespam.org - hidemail.de - hochsitze.com - hotpop.com - hulapla.de - ieatspam.eu - ieatspam.info - ihateyoualot.info - iheartspam.org - imails.info - inbax.tk - inboxalias.com - inboxclean.com - inboxclean.org - incognitomail.com - incognitomail.net - incognitomail.org - insorg-mail.info - ipoo.org - irish2me.com - iwi.net - jetable.com - jetable.fr.nf - jetable.net - jetable.org - jnxjn.com - jourrapide.com - junk1e.com - kasmail.com - kaspop.com - keepmymail.com - killmail.com - killmail.net - kir.ch.tc - klassmaster.com - klassmaster.net - klzlk.com - koszmail.pl - kulturbetrieb.info - kurzepost.de - letthemeatspam.com - lhsdv.com - lifebyfood.com - link2mail.net - litedrop.com - lol.ovpn.to - lookugly.com - lopl.co.cc - lortemail.dk - lr78.com - m4ilweb.info - maboard.com - mail-temporaire.fr - mail.by - mail.mezimages.net - mail2rss.org - mail333.com - mail4trash.com - mailbidon.com - mailblocks.com - mailcatch.com - maildrop.cc - maileater.com - mailexpire.com - mailfa.tk - mailfreeonline.com - mailhazard.com - mailhazard.us - mailhz.me - mailin8r.com - mailinater.com - mailinator.com - mailinator.net - mailinator2.com - mailincubator.com - mailme.ir - mailme.lv - mailmetrash.com - mailmoat.com - mailnator.com - mailnesia.com - mailnull.com - mailshell.com - mailsiphon.com - mailslite.com - mailzilla.com - mailzilla.org - mbx.cc - mega.zik.dj - meinspamschutz.de - meltmail.com - messagebeamer.de - mierdamail.com - mintemail.com - moburl.com - moncourrier.fr.nf - monemail.fr.nf - monmail.fr.nf - msa.minsmail.com - mt2009.com - mx0.wwwnew.eu - mycleaninbox.net - mypartyclip.de - myphantomemail.com - myspaceinc.com - myspaceinc.net - myspaceinc.org - myspacepimpedup.com - myspamless.com - mytrashmail.com - nada.email - nada.ltd - neomailbox.com - nepwk.com - nervmich.net - nervtmich.net - netmails.com - netmails.net - netzidiot.de - neverbox.com - no-spam.ws - nobulk.com - noclickemail.com - nogmailspam.info - nomail.xl.cx - nomail2me.com - nomorespamemails.com - nospam.ze.tc - nospam4.us - nospamfor.us - nospamthanks.info - notmailinator.com - nowmymail.com - nurfuerspam.de - nus.edu.sg - nwldx.com - objectmail.com - obobbo.com - oneoffemail.com - onewaymail.com - online.ms - oopi.org - ordinaryamerican.net - otherinbox.com - ourklips.com - outlawspam.com - ovpn.to - owlpic.com - pancakemail.com - paplease.com - pimpedupmyspace.com - pjjkp.com - politikerclub.de - poofy.org - pookmail.com - privacy.net - proxymail.eu - prtnx.com - punkass.com - putthisinyourspamdatabase.com - quickinbox.com - rcpt.at - recode.me - recursor.net - regbypass.com - regbypass.comsafe-mail.net - rejectmail.com - rhyta.com - rklips.com - rmqkr.net - rppkn.com - rtrtr.com - s0ny.net - safe-mail.net - safersignup.de - safetymail.info - safetypost.de - sandelf.de - saynotospams.com - selfdestructingmail.com - sendspamhere.com - sharklasers.com - shiftmail.com - shitmail.me - shortmail.net - sibmail.com - skeefmail.com - slaskpost.se - slopsbox.com - smellfear.com - snakemail.com - sneakemail.com - sofimail.com - sofort-mail.de - sogetthis.com - soodonims.com - spam.la - spam.su - spam4.me - spamavert.com - spambob.com - spambob.net - spambob.org - spambog.com - spambog.de - spambog.ru - spambox.info - spambox.irishspringrealty.com - spambox.us - spamcannon.com - spamcannon.net - spamcero.com - spamcon.org - spamcorptastic.com - spamcowboy.com - spamcowboy.net - spamcowboy.org - spamday.com - spamex.com - spamfree24.com - spamfree24.de - spamfree24.eu - spamfree24.info - spamfree24.net - spamfree24.org - spamgourmet.com - spamgourmet.net - spamgourmet.org - spamherelots.com - spamhereplease.com - spamhole.com - spamify.com - spaminator.de - spamkill.info - spaml.com - spaml.de - spammotel.com - spamobox.com - spamoff.de - spamslicer.com - spamspot.com - spamthis.co.uk - spamthisplease.com - spamtrail.com - speed.1s.fr - supergreatmail.com - supermailer.jp - superrito.com - suremail.info - tagyourself.com - teewars.org - teleworm.com - teleworm.us - tempalias.com - tempe-mail.com - tempemail.biz - tempemail.com - tempemail.net - tempinbox.co.uk - tempinbox.com - tempmail.it - tempmail2.com - tempomail.fr - temporarily.de - temporarioemail.com.br - temporaryemail.net - temporaryforwarding.com - temporaryinbox.com - thanksnospam.info - thankyou2010.com - thisisnotmyrealemail.com - throwawayemailaddress.com - tilien.com - tmailinator.com - tradermail.info - trash-amil.com - trash-mail.at - trash-mail.com - trash-mail.de - trash2009.com - trashemail.de - trashmail.at - trashmail.com - trashmail.de - trashmail.me - trashmail.net - trashmail.org - trashmail.ws - trashmailer.com - trashymail.com - trashymail.net - trbvm.com - trillianpro.com - turual.com - twinmail.de - tyldd.com - uggsrock.com - upliftnow.com - uplipht.com - venompen.com - veryrealemail.com - viditag.com - viewcastmedia.com - viewcastmedia.net - viewcastmedia.org - webm4il.info - wegwerfadresse.de - wegwerfemail.de - wegwerfmail.de - wegwerfmail.net - wegwerfmail.org - wetrainbayarea.com - wetrainbayarea.org - wh4f.org - whatpaas.com - whyspam.me - willselfdestruct.com - winemaven.info - wmail.club - wronghead.com - wuzup.net - wuzupmail.net - wwwnew.eu - xagloo.com - xemaps.com - xents.com - xmaily.com - xoxy.net - yep.it - yogamaven.com - yopmail.com - yopmail.fr - yopmail.net - ypmail.webarnak.fr.eu.org - yuurok.com - zebins.com - zebins.eu - zehnminutenmail.de - zippymail.info - zoaxe.com - zoemail.org - valid_email-0.2.1/History.md0000644000004100000410000000061314620063664016002 0ustar www-datawww-data 0.1.0 / 2017-09-27 ================== * #86 Change dependency on mail to >= 2.6.1 * #85 adding disposable email domains from getnada * #84 ValidateEmail.valid?: make domain validation true by default * #83 Allow to configure timeouts for dns * #82 Travis CI. Support for more Ruby versions * #80 rescue Mail::Field::ParseError also in domain_valid? * #78 Added pt-BR translation