email_validator-2.2.4/0000755000004100000410000000000014452122003014674 5ustar www-datawww-dataemail_validator-2.2.4/README.md0000644000004100000410000001474514452122003016166 0ustar www-datawww-data# EmailValidator [![Build Status](https://travis-ci.com/K-and-R/email_validator.svg?branch=master)](http://travis-ci.com/K-and-R/email_validator) [![Code Climate](https://codeclimate.com/github/K-and-R/email_validator/badges/gpa.svg)](https://codeclimate.com/github/K-and-R/email_validator) [![Test Coverage](https://codeclimate.com/github/K-and-R/email_validator/badges/coverage.svg)](https://codeclimate.com/github/K-and-R/email_validator/coverage) An email validator for Rails 3+. Supports RFC-2822-compliant and RFC-5321-compliant email validation using RFC-3696 validation. Formerly found at: ## Validation philosophy The default validation provided by this gem (the `:loose` configuration option) is extremely loose. It just checks that there's an `@` with something before and after it without any whitespace. See [this article by David Gilbertson](https://medium.com/hackernoon/the-100-correct-way-to-validate-email-addresses-7c4818f24643) for an explanation of why. We understand that many use cases require an increased level of validation. This is supported by using the `:strict` validation mode. Additionally, the `:rfc` RFC-compliant mode will consider technically valid emails address as valid which may not be wanted, such as the valid `user` or `user@somehost` addresses. These would be valid in `:rfc` mode but not valid in `:loose` or `:strict`. ## Installation Add to your Gemfile: ```ruby gem 'email_validator' ``` Run: ```bash bundle install ``` ## Usage Add the following to your model: ```ruby validates :my_email_attribute, email: true ``` You may wish to allow domains without a FQDN, like `user@somehost`. While this is technically a valid address, it is uncommon to consider such address valid. We will consider them valid by default with the `:loose` checking. Disallowed by setting `require_fqdn: true` or by enabling `:strict` checking: ```ruby validates :my_email_attribute, email: {mode: :strict, require_fqdn: true} ``` You can also limit to a single domain (e.g: you have separate `User` and `AdminUser` models and want to ensure that `AdminUser` emails are on a specific domain): ```ruby validates :my_email_attribute, email: {domain: 'example.com'} ``` ## Configuration Default configuration can be overridden by setting options in `config/initializers/email_validator.rb`: ```ruby if defined?(EmailValidator) # To completely override the defaults EmailValidator.default_options = { allow_nil: false, domain: nil, require_fqdn: nil, mode: :loose } # or just a few options EmailValidator.default_options.merge!({ domain: 'mydomain.com' }) end ``` ### Loose mode This it the default validation mode of this gem. It is intentionally extremely loose (see the [Validation Philosophy section](#validation_philosophy) above. It just checks that there's an `@` with something before and after it without any whitespace. ### Strict mode Enabling `:strict` checking will check for a "normal" email format that would be expected in most common everyday usage. Strict mode basically checks for a properly sized and formatted mailbox label, a single "@" symbol, and a properly sized and formatted FQDN. Enabling `:strict` mode will also enable `:require_fqdn` configuration option. Strict mode can be enabled globally by requiring `email_validator/strict` in your `Gemfile`, by setting the option in `config/initializers/email_validator.rb`, or by specifying the option in a specific `validates` call. * `Gemfile`: ```ruby gem 'email_validator', require: 'email_validator/strict' ``` * `config/initializers/email_validator.rb`: ```ruby if defined?(EmailValidator) EmailValidator.default_options[:mode] = :strict end ``` * `validates` call: ```ruby validates :my_email_attribute, email: {mode: :strict} ``` ### RFC mode In order to have RFC-compliant validation (according to [http://www.remote.org/jochen/mail/info/chars.html](https://web.archive.org/web/20150508102948/http://www.remote.org/jochen/mail/info/chars.html)), enable `:rfc` mode. You can do this globally by requiring `email_validator/rfc` in your `Gemfile`, by setting the options in `config/initializers/email_validator.rb`, or you can do this in a specific `validates` call. * `Gemfile`: ```ruby gem 'email_validator', require: 'email_validator/rfc' ``` * `config/initializers/email_validator.rb`: ```ruby if defined?(EmailValidator) EmailValidator.default_options[:mode] = :rfc end ``` * `validates` call: ```ruby validates :my_email_attribute, email: {mode: :rfc} ``` ## Validation outside a model If you need to validate an email outside a model, you can get the regexp: ### Loose/default mode ```ruby EmailValidator.valid?('narf@example.com') # boolean ``` ### Requiring a FQDN ```ruby EmailValidator.valid?('narf@somehost') # boolean false EmailValidator.invalid?('narf@somehost', require_fqdn: false) # boolean true ``` _NB: Enabling strict mode (`mode: :strict`) enables `require_fqdn` (`require_fqdn: true`), overridding any `require_fqdn: false` while `mode: :strict` is set._ ### Requiring a specific domain ```ruby EmailValidator.valid?('narf@example.com', domain: 'foo.com') # boolean false EmailValidator.invalid?('narf@example.com', domain: 'foo.com') # boolean true ``` ### Strict mode ```ruby EmailValidator.regexp(mode: :strict) # returns the regex EmailValidator.valid?('narf@example.com', mode: :strict) # boolean ``` ### RFC mode ```ruby EmailValidator.regexp(mode: :rfc) # returns the regex EmailValidator.valid?('narf@example.com', mode: :rfc) # boolean ``` ## Thread safety This gem is thread safe, with one caveat: `EmailValidator.default_options` must be configured before use in a multi-threaded environment. If you configure `default_options` in a Rails initializer file, then you're good to go since initializers are run before worker threads are spawned. ## Alternative gems Do you prefer a different email validation gem? If so, open an issue with a brief explanation of how it differs from this gem. I'll add a link to it in this README. * [`email_address`](https://github.com/afair/email_address) () * [`email_verifier`](https://github.com/kamilc/email_verifier) () ## Maintainers All thanks is given to [Brian Alexander (balexand)](https://github.com/balexand) for is initial work on this gem. Currently maintained by: * Karl Wilbur () * K&R Software () email_validator-2.2.4/spec/0000755000004100000410000000000014452122003015626 5ustar www-datawww-dataemail_validator-2.2.4/spec/email_validator_spec.rb0000644000004100000410000011512314452122003022324 0ustar www-datawww-datarequire 'spec_helper' class DefaultUser < TestModel validates :email, :email => true end class StrictUser < TestModel validates :email, :email => { :mode => :strict } end class RfcUser < TestModel validates :email, :email => { :mode => :rfc } end class AllowNilDefaultUser < TestModel validates :email, :email => { :allow_nil => true } end class AllowNilStrictUser < TestModel validates :email, :email => { :allow_nil => true, :mode => :strict } end class AllowNilRfcUser < TestModel validates :email, :email => { :allow_nil => true, :mode => :rfc } end class DisallowNilDefaultUser < TestModel validates :email, :email => { :allow_nil => false } end class DisallowNilStrictUser < TestModel validates :email, :email => { :allow_nil => false, :mode => :strict } end class DisallowNilRfcUser < TestModel validates :email, :email => { :allow_nil => false, :mode => :rfc } end class DomainStrictUser < TestModel validates :email, :email => { :domain => 'example.com', :mode => :strict } end class DomainRfcUser < TestModel validates :email, :email => { :domain => 'example.com', :mode => :rfc } end class NonFqdnStrictUser < TestModel validates :email, :email => { :require_fqdn => false, :mode => :strict } end class NonFqdnRfcUser < TestModel validates :email, :email => { :require_fqdn => false, :mode => :rfc } end class RequireFqdnWithEmptyDomainUser < TestModel validates :email_address, :email => { :require_fqdn => true, :domain => '' } end class RequireEmptyDomainStrictUser < TestModel validates :email_address, :email => { :require_fqdn => true, :domain => '', :mode => :strict } end class RequireEmptyDomainRfcUser < TestModel validates :email_address, :email => { :require_fqdn => true, :domain => '', :mode => :rfc } end class DefaultUserWithMessage < TestModel validates :email_address, :email => { :message => 'is not looking very good!' } end RSpec.describe EmailValidator do describe 'validation' do valid_special_chars = { :ampersand => '&', :asterisk => '*', :backtick => '`', :braceleft => '{', :braceright => '}', :caret => '^', :dollar => '$', :equals => '=', :exclaim => '!', :hash => '#', :hyphen => '-', :percent => '%', :plus => '+', :pipe => '|', :question => '?', :quotedouble => '"', :quotesingle => "'", :slash => '/', :tilde => '~', :underscore => '_' } invalid_special_chars = { :backslash => '\\', :braketleft => '[', :braketright => ']', :colon => ':', :comma => ',', :greater => '>', :lesser => '<', :parenleft => '(', :parenright => ')', :semicolon => ';' } valid_includable = valid_special_chars.merge({ :dot => '.' }) valid_beginable = valid_special_chars valid_endable = valid_special_chars invalid_includable = { :at => '@' } whitespace = { :newline => "\n", :tab => "\t", :carriage_return => "\r", :space => ' ' } strictly_invalid_includable = invalid_special_chars strictly_invalid_beginable = strictly_invalid_includable.merge({ :dot => '.' }) strictly_invalid_endable = strictly_invalid_beginable domain_invalid_beginable = invalid_special_chars.merge(valid_special_chars) domain_invalid_endable = domain_invalid_beginable domain_invalid_includable = domain_invalid_beginable.reject { |k, _v| k == :hyphen } # rubocop:disable Layout/BlockEndNewline, Layout/MultilineBlockLayout, Layout/MultilineMethodCallBraceLayout, Style/BlockDelimiters, Style/MultilineBlockChain context 'when given the valid email' do valid_includable.map { |k, v| [ "include-#{v}-#{k}@valid-characters-in-local.dev" ]}.concat(valid_beginable.map { |k, v| [ "#{v}start-with-#{k}@valid-characters-in-local.dev" ]}).concat(valid_endable.map { |k, v| [ "end-with-#{k}-#{v}@valid-characters-in-local.dev" ]}).concat([ 'a+b@plus-in-local.com', 'a_b@underscore-in-local.com', 'user@example.com', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@letters-in-local.dev', '01234567890@numbers-in-local.dev', 'a@single-character-in-local.dev', 'one-character-third-level@a.example.com', 'single-character-in-sld@x.dev', 'local@dash-in-sld.com', 'numbers-in-sld@s123.com', 'one-letter-sld@x.dev', 'uncommon-tld@sld.museum', 'uncommon-tld@sld.travel', 'uncommon-tld@sld.mobi', 'country-code-tld@sld.uk', 'country-code-tld@sld.rw', 'local@sld.newTLD', 'local@sub.domains.com', 'aaa@bbb.co.jp', 'nigel.worthington@big.co.uk', 'f@c.com', 'f@s.c', 'someuser@somehost.somedomain', 'mixed-1234-in-{+^}-local@sld.dev', 'partially."quoted"@sld.com', 'areallylongnameaasdfasdfasdfasdf@asdfasdfasdfasdfasdf.ab.cd.ef.gh.co.ca', 'john.doe@2020.example.com', 'john.doe@2a.com', 'john.doe@a2.com', 'john.doe@2020.a-z.com', 'john.doe@2020.a2z.com', 'john.doe@2020.12345a6789.com', 'jonh.doe@163.com', 'test@umläut.com', # non-ASCII 'test@xn--umlut-ira.com' # ASCII-compatibale encoding of non-ASCII ]).flatten.each do |email| context 'when using defaults' do it "'#{email}' should be valid" do expect(DefaultUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp)).to be(true) end end context 'when in `:strict` mode' do it "'#{email}' should be valid" do expect(StrictUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email, :mode => :strict) end it "'#{email}' should not be invalid using EmailValidator.valid?" do expect(described_class).not_to be_invalid(email, :mode => :strict) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(true) end end context 'when in `:rfc` mode' do it "'#{email}' should be valid" do expect(RfcUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email, :mode => :rfc) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email, :mode => :rfc) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) end end end end context 'when given the valid host-only email' do [ 'f@s', 'user@localhost', 'someuser@somehost' ].each do |email| context 'when using defaults' do it "'#{email}' should be valid" do expect(DefaultUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp)).to be(true) end end context 'when in `:strict` mode' do it "'#{email}' should not be valid" do expect(StrictUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :strict) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :strict) end it "'#{email}' should not match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) end end context 'when in `:rfc` mode' do it "'#{email}' should be valid" do expect(RfcUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email, :mode => :rfc) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email, :mode => :rfc) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) end end end end context 'when given the numeric domain' do [ 'only-numbers-in-domain-label@sub.123.custom' ].each do |email| context 'when using defaults' do it "'#{email}' should be valid" do expect(DefaultUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp)).to be(true) end end context 'when in `:strict` mode' do it "'#{email}' should be valid" do expect(StrictUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email, :mode => :strict) end it "'#{email}' should be not invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email, :mode => :strict) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(true) end end context 'when in `:rfc` mode' do it "'#{email}' should be valid" do expect(RfcUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email, :mode => :rfc) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email, :mode => :rfc) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) end end end end context 'when given the valid mailbox-only email' do valid_includable.map { |k, v| [ "user-#{v}-#{k}-name" ]}.concat(valid_beginable.map { |k, v| [ "#{v}-start-with-#{k}-user" ]}).concat(valid_endable.map { |k, v| [ "end-with-#{k}-#{v}" ]}).concat([ 'user' ]).flatten.each do |email| context 'when using defaults' do it "'#{email}' should not be valid" do expect(DefaultUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email) end it "'#{email}' should not match the regexp" do expect(!!(email.strip =~ described_class.regexp)).to be(false) end end context 'when in `:strict` mode' do it "'#{email}' should not be valid" do expect(StrictUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :strict) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :strict) end it "'#{email}' should not match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) end end context 'when in `:rfc` mode' do it "'#{email}' should be valid" do expect(RfcUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email, :mode => :rfc) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email, :mode => :rfc) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) end end end end context 'when given the valid IP address email' do [ 'bracketed-IP@[127.0.0.1]', 'bracketed-and-labeled-IPv6@[IPv6:abcd:ef01:1234:5678:9abc:def0:1234:5678]' ].each do |email| context 'when using defaults' do it "'#{email}' should be valid" do expect(DefaultUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp)).to be(true) end end context 'when in `:strict` mode' do it "'#{email}' should not be valid" do expect(StrictUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :strict) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :strict) end it "'#{email}' should not match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) end end context 'when in `:rfc` mode' do it "'#{email}' should be valid" do expect(RfcUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email, :mode => :rfc) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email, :mode => :rfc) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) end end end end context 'when given the invalid email' do invalid_includable.map { |k, v| [ "include-#{v}-#{k}@invalid-characters-in-local.dev" ]}.concat(domain_invalid_beginable.map { |k, v| [ "start-with-#{k}@#{v}invalid-characters-in-domain.dev" ]}).concat(domain_invalid_endable.map { |k, v| [ "end-with-#{k}@invalid-characters-in-domain#{v}.dev" ]}).concat(domain_invalid_includable.map { |k, v| [ "include-#{k}@invalid-characters-#{v}-in-domain.dev" ]}).concat([ 'test@example.com@example.com', 'missing-sld@.com', 'missing-tld@sld.', 'unbracketed-IPv6@abcd:ef01:1234:5678:9abc:def0:1234:5678', 'unbracketed-and-labled-IPv6@IPv6:abcd:ef01:1234:5678:9abc:def0:1234:5678', 'bracketed-and-unlabeled-IPv6@[abcd:ef01:1234:5678:9abc:def0:1234:5678]', 'unbracketed-IPv4@127.0.0.1', 'invalid-IPv4@127.0.0.1.26', 'another-invalid-IPv4@127.0.0.256', 'IPv4-and-port@127.0.0.1:25', 'host-beginning-with-dot@.example.com', 'domain-beginning-with-dash@-example.com', 'domain-ending-with-dash@example-.com', 'the-local-part-is-invalid-if-it-is-longer-than-sixty-four-characters@sld.dev', "domain-too-long@t#{".#{'o' * 63}" * 5}.long", "user@example.com" ]).flatten.each do |email| context 'when using defaults' do it "'#{email}' should be valid" do expect(DefaultUser.new(:email => email)).to be_valid end it "'#{email}' should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email) end it "'#{email}' should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email) end it "'#{email}' should match the regexp" do expect(!!(email.strip =~ described_class.regexp)).to be(true) end end context 'when in `:strict` mode' do it "'#{email}' should not be valid" do expect(StrictUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :strict) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :strict) end it "'#{email}' should not match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) end end context 'when in `:rfc` mode' do it "'#{email}' should not be valid" do expect(RfcUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :rfc) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :rfc) end it "'#{email}' should not match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(false) end end end end context 'when given the invalid email with whitespace in parts' do whitespace.map { |k, v| [ "include-#{v}-#{k}@invalid-characters-in-local.dev" ]}.concat([ 'foo @bar.com', "foo\t@bar.com", "foo\n@bar.com", "foo\r@bar.com", 'test@ example.com', 'user@example .com', "user@example\t.com", "user@example\n.com", "user@example\r.com", 'user@exam ple.com', "user@exam\tple.com", "user@exam\nple.com", "user@exam\rple.com", 'us er@example.com', "us\ter@example.com", "us\ner@example.com", "us\rer@example.com", "user@example.com\n", "user@example.com\t", "user@example.com\r", "user@example.com ", ' leading-whitespace@example.com', 'trailing-whitespace@example.com ', ' leading-and-trailing-whitespace@example.com ', ' user-with-leading-whitespace-space@example.com', "\tuser-with-leading-whitespace-tab@example.com", " user-with-leading-whitespace-newline@example.com", 'domain-with-trailing-whitespace-space@example.com ', "domain-with-trailing-whitespace-tab@example.com\t", "domain-with-trailing-whitespace-newline@example.com " ]).flatten.each do |email| context 'when using defaults' do it "'#{email}' should not be valid" do expect(DefaultUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email) end it "'#{email}' should not match the regexp" do expect(!!(email =~ described_class.regexp)).to be(false) end end context 'when in `:strict` mode' do it "'#{email}' should not be valid" do expect(StrictUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :strict) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :strict) end it "'#{email}' should not match the regexp" do expect(!!(email =~ described_class.regexp(:mode => :strict))).to be(false) end end context 'when in `:rfc` mode' do it "'#{email}' should not be valid" do expect(RfcUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :rfc) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :rfc) end it "'#{email}' should not match the regexp" do expect(!!(email =~ described_class.regexp(:mode => :rfc))).to be(false) end end end end context 'when given the invalid email with missing parts' do [ '', '@bar.com', 'test@', '@missing-local.dev', ' ' ].each do |email| context 'when using defaults' do it "'#{email}' should not be valid" do expect(DefaultUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email) end it "'#{email}' should not match the regexp" do expect(!!(email.strip =~ described_class.regexp)).to be(false) end end context 'when in `:strict` mode' do it "'#{email}' should not be valid" do expect(StrictUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :strict) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :strict) end it "'#{email}' should not match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) end end context 'when in `:rfc` mode' do it "'#{email}' should not be valid" do expect(RfcUser.new(:email => email)).not_to be_valid end it "'#{email}' should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :rfc) end it "'#{email}' should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :rfc) end it "'#{email}' should not match the regexp" do expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(false) end end end end context 'when given the strictly invalid email' do strictly_invalid_includable.map { |k, v| [ "include-#{v}-#{k}@invalid-characters-in-local.dev" ]}.concat(strictly_invalid_beginable.map { |k, v| [ "#{v}start-with-#{k}@invalid-characters-in-local.dev" ]}).concat(strictly_invalid_endable.map { |k, v| [ "end-with-#{k}#{v}@invalid-characters-in-local.dev" ]}).concat([ 'user..-with-double-dots@example.com', '.user-beginning-with-dot@example.com', 'user-ending-with-dot.@example.com', 'fully-numeric-tld@example.123' ]).flatten.each do |email| context 'when using defaults' do it "#{email.strip} in a model should be valid" do expect(DefaultUser.new(:email => email)).to be_valid end it "#{email.strip} should be valid using EmailValidator.valid?" do expect(described_class).to be_valid(email) end it "#{email.strip} should not be invalid using EmailValidator.invalid?" do expect(described_class).not_to be_invalid(email) end it "#{email.strip} should match the regexp" do expect(!!(email =~ described_class.regexp)).to be(true) end end context 'when in `:strict` mode' do it "#{email.strip} in a model should not be valid" do expect(StrictUser.new(:email => email)).not_to be_valid end it "#{email.strip} should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :strict) end it "#{email.strip} should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :strict) end it "#{email.strip} should not match the regexp" do expect(!!(email =~ described_class.regexp(:mode => :strict))).to be(false) end end context 'when in `:rfc` mode' do it "#{email.strip} in a model should not be valid" do expect(RfcUser.new(:email => email)).not_to be_valid end it "#{email.strip} should not be valid using EmailValidator.valid?" do expect(described_class).not_to be_valid(email, :mode => :rfc) end it "#{email.strip} should be invalid using EmailValidator.invalid?" do expect(described_class).to be_invalid(email, :mode => :rfc) end it "#{email.strip} should not match the regexp" do expect(!!(email =~ described_class.regexp(:mode => :rfc))).to be(false) end end end end context 'when `require_fqdn` is explicitly enabled with a blank domain' do let(:opts) { { :require_fqdn => true, :domain => '' } } context 'when given a email containing any domain' do let(:email) { 'someuser@somehost' } context 'when using defaults' do it 'is not valid in a model' do expect(RequireFqdnWithEmptyDomainUser.new(:email => email)).not_to be_valid end it 'is not using EmailValidator.valid?' do expect(described_class).not_to be_valid(email, opts) end it 'is invalid using EmailValidator.invalid?' do expect(described_class).to be_invalid(email, opts) end it 'does not match the regexp' do expect(!!(email =~ described_class.regexp(opts))).to be(false) end end context 'when in `:strict` mode' do it 'is not valid in a model' do expect(RequireEmptyDomainStrictUser.new(:email => email)).not_to be_valid end it 'is not using EmailValidator.valid?' do expect(described_class).not_to be_valid(email, opts.merge({ :mode => :strict })) end it 'is invalid using EmailValidator.invalid?' do expect(described_class).to be_invalid(email, opts.merge({ :mode => :strict })) end it 'does not match the regexp' do expect(!!(email =~ described_class.regexp(opts.merge({ :mode => :strict })))).to be(false) end end context 'when in `:rfc` mode' do it 'is not valid in a model' do expect(RequireEmptyDomainRfcUser.new(:email => email)).not_to be_valid end it 'is not using EmailValidator.valid?' do expect(described_class).not_to be_valid(email, opts.merge({ :mode => :rfc })) end it 'is invalid using EmailValidator.invalid?' do expect(described_class).to be_invalid(email, opts.merge({ :mode => :rfc })) end it 'does not match the regexp' do expect(!!(email =~ described_class.regexp(opts.merge({ :mode => :rfc })))).to be(false) end end end end context 'when `require_fqdn` is explicitly disabled' do let(:opts) { { :require_fqdn => false } } context 'when given a valid hostname-only email' do let(:email) { 'someuser@somehost' } context 'when using defaults' do it 'is valid using EmailValidator.valid?' do expect(described_class).to be_valid(email, opts) end it 'is not invalid using EmailValidator.invalid?' do expect(described_class).not_to be_invalid(email, opts) end it 'matches the regexp' do expect(!!(email =~ described_class.regexp(opts))).to be(true) end end # Strict mode enables `require_fqdn` anyway context 'when in `:strict` mode' do let(:opts) { { :require_fqdn => false, :mode => :strict } } it 'is not valid' do expect(NonFqdnStrictUser.new(:email => email)).not_to be_valid end it 'is not valid using EmailValidator.valid?' do expect(described_class).not_to be_valid(email, opts) end it 'is invalid using EmailValidator.invalid?' do expect(described_class).to be_invalid(email, opts) end it 'matches the regexp' do expect(!!(email =~ described_class.regexp(opts))).to be(false) end end context 'when in `:rfc` mode' do let(:opts) { { :require_fqdn => false, :mode => :rfc } } it 'is valid' do expect(NonFqdnRfcUser.new(:email => email)).to be_valid end it 'is valid using EmailValidator.valid?' do expect(described_class).to be_valid(email, opts) end it 'is not invalid using EmailValidator.invalid?' do expect(described_class).not_to be_invalid(email, opts) end it 'matches the regexp' do expect(!!(email =~ described_class.regexp(opts))).to be(true) end end end context 'when given a valid email using an FQDN' do let(:email) { 'someuser@somehost.somedomain' } it 'is valid' do expect(NonFqdnStrictUser.new(:email => email)).to be_valid end # rubocop:disable RSpec/PredicateMatcher it 'is valid using EmailValidator.valid?' do expect(described_class.valid?(email, opts)).to be(true) end it 'is not invalid using EmailValidator.invalid?' do expect(described_class.invalid?(email, opts)).to be(false) end # rubocop:enable RSpec/PredicateMatcher it 'matches the regexp' do expect(!!(email =~ described_class.regexp(opts))).to be(true) end context 'when in `:rfc` mode' do let(:opts) { { :require_fqdn => false, :mode => :rfc } } # rubocop:disable RSpec/PredicateMatcher it 'is valid using EmailValidator.valid?' do expect(described_class.valid?(email, opts)).to be(true) end it 'is not invalid using EmailValidator.invalid?' do expect(described_class.invalid?(email, opts)).to be(false) end # rubocop:enable RSpec/PredicateMatcher it 'is valid' do expect(NonFqdnRfcUser.new(:email => email)).to be_valid end it 'matches the regexp' do expect(!!(email =~ described_class.regexp(opts))).to be(true) end end context 'when requiring a non-matching domain' do let(:domain) { 'example.com' } let(:opts) { { :domain => domain } } it 'is not valid' do expect(DomainStrictUser.new(:email => email)).not_to be_valid end it 'is not valid using EmailValidator.valid?' do expect(described_class).not_to be_valid(email, opts) end it 'is invalid using EmailValidator.invalid?' do expect(described_class).to be_invalid(email, opts) end it 'does not matches the regexp' do expect(!!(email =~ described_class.regexp(opts))).to be(false) end context 'when in `:rfc` mode' do let(:opts) { { :domain => domain, :require_fqdn => false, :mode => :rfc } } it 'is not valid using EmailValidator.valid?' do expect(described_class).not_to be_valid(email, opts) end it 'is invalid using EmailValidator.invalid?' do expect(described_class).to be_invalid(email, opts) end it 'is not valid' do expect(DomainRfcUser.new(:email => email)).not_to be_valid end it 'does not match the regexp' do expect(!!(email =~ described_class.regexp(opts))).to be(false) end end end end end end # rubocop:enable Layout/BlockEndNewline, Layout/MultilineBlockLayout, Layout/MultilineMethodCallBraceLayout, Style/BlockDelimiters, Style/MultilineBlockChain describe 'error messages' do context 'when the message is not defined' do let(:model) { DefaultUser.new :email => 'invalidemail@' } before { model.valid? } it 'adds the default message' do expect(model.errors[:email]).to include 'is invalid' end end context 'when the message is defined' do let(:model) { DefaultUserWithMessage.new :email_address => 'invalidemail@' } before { model.valid? } it 'adds the customized message' do expect(model.errors[:email_address]).to include 'is not looking very good!' end end end describe 'nil email' do it 'is not valid when :allow_nil option is missing' do expect(DefaultUser.new(:email => nil)).not_to be_valid end it 'is valid when :allow_nil options is set to true' do expect(AllowNilDefaultUser.new(:email => nil)).to be_valid end it 'is not valid when :allow_nil option is set to false' do expect(DisallowNilDefaultUser.new(:email => nil)).not_to be_valid end end describe 'limited to a domain' do context 'when in `:strict` mode' do it 'is not valid with mismatched domain' do expect(DomainStrictUser.new(:email => 'user@not-matching.io')).not_to be_valid end it 'is valid with matching domain' do expect(DomainStrictUser.new(:email => 'user@example.com')).to be_valid end it 'does not interpret the dot as any character' do expect(DomainStrictUser.new(:email => 'user@example-com')).not_to be_valid end end context 'when in `:rfc` mode' do it 'does not interpret the dot as any character' do expect(DomainRfcUser.new(:email => 'user@example-com')).not_to be_valid end it 'is valid with matching domain' do expect(DomainRfcUser.new(:email => 'user@example.com')).to be_valid end it 'is not valid with mismatched domain' do expect(DomainRfcUser.new(:email => 'user@not-matching.io')).not_to be_valid end end end describe 'default_options' do let(:valid_email) { 'valid-email@localhost.localdomain' } let(:invalid_email) { 'invalid email@localhost.localdomain' } it 'validates valid using `:loose` mode' do expect(DefaultUser.new(:email => valid_email)).to be_valid end it 'invalidates invalid using `:loose` mode' do expect(DefaultUser.new(:email => invalid_email)).to be_invalid end context 'when `email_validator/strict` has been required' do before { require 'email_validator/strict' } it 'validates valid using `:strict` mode' do expect(DefaultUser.new(:email => valid_email)).to be_valid end it 'invalidates invalid using `:strict` mode' do expect(DefaultUser.new(:email => invalid_email)).to be_invalid end end context 'when `email_validator/rfc` has been required' do before { require 'email_validator/rfc' } it 'validates valid using `:rfc` mode' do expect(DefaultUser.new(:email => valid_email)).to be_valid end it 'invalidates invalid using `:rfc` mode' do expect(DefaultUser.new(:email => invalid_email)).to be_invalid end end end context 'with regexp' do it 'returns a regexp when asked' do expect(described_class.regexp).to be_a(Regexp) end it 'returns a strict regexp when asked' do expect(described_class.regexp(:mode => :strict)).to be_a(Regexp) end it 'returns a RFC regexp when asked' do expect(described_class.regexp(:mode => :rfc)).to be_a(Regexp) end it 'has different regexp for strict and loose' do expect(described_class.regexp(:mode => :strict)).not_to eq(described_class.regexp(:mode => :loose)) end it 'has different regexp for RFC and loose' do expect(described_class.regexp(:mode => :rfc)).not_to eq(described_class.regexp(:mode => :loose)) end it 'has different regexp for RFC and strict' do expect(described_class.regexp(:mode => :rfc)).not_to eq(described_class.regexp(:mode => :strict)) end end context 'with invalid `:mode`' do it 'raises an error' do expect { described_class.regexp(:mode => :invalid) }.to raise_error(EmailValidator::Error) end end end email_validator-2.2.4/spec/spec_helper.rb0000644000004100000410000000106614452122003020447 0ustar www-datawww-data# frozen_string_literal: true require 'rubygems' require 'pry' require 'rspec' require 'active_model' I18n.enforce_available_locales = false require 'simplecov' SimpleCov.start 'rails' $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) $LOAD_PATH.unshift(File.dirname(__FILE__)) require 'email_validator' class TestModel include ActiveModel::Validations def initialize(attributes = {}) @attributes = attributes end def read_attribute_for_validation(key) @attributes[key] end end RSpec.configure(&:disable_monkey_patching!) email_validator-2.2.4/CHANGELOG.md0000644000004100000410000001267714452122003016522 0ustar www-datawww-data# CHANGELOG This file is used to list changes made in `email_validator`. All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## 2.2.4 (2022-11-09) * [karlwilbur] - Remove Ruby 2.4 from tested versions; add Ruby 3.0 and 3.1 to tested versions * [karlwilbur] - Fix issue where `domain: ''` wasn't requiring empty domain * [karlwilbur] - Remove checks for double hyphens (fixes [#87](https://github.com/K-and-R/email_validator/issues/87)) * [dependabot] - Security updates - [#89](https://github.com/K-and-R/email_validator/pull/89) + Bump `minimist` from `1.2.5` to `1.2.7` - [#86](https://github.com/K-and-R/email_validator/pull/86) + Bump `node-fetch` from `2.6.1` to `2.6.7` + Add `whatwg-url` at `5.0.0` + Add `tr46` at `0.0.3` + Add `webidl-conversions` at `3.0.0` - [#80](https://github.com/K-and-R/email_validator/pull/80) + Bump `tar` from `6.0.5` to `6.1.11` + Bump `minipass` from `3.1.3` to `3.1.5` - [#79](https://github.com/K-and-R/email_validator/pull/79) + Bump `path-parse` from `1.0.6` to `1.0.7` - [#76](https://github.com/K-and-R/email_validator/pull/76) + Bump `lodash` from `4.17.20` to `4.17.21` - [#75](https://github.com/K-and-R/email_validator/pull/75) + Bump `hosted-git-info` from `2.8.8` to `2.8.9` * [msands] - Fix URL in `README.md` [#81](https://github.com/K-and-R/email_validator/pull/81) * [kerolloz] - Fix typo in `README.md` [#73](https://github.com/K-and-R/email_validator/pull/73) ## 2.2.3 (2021-04-05) * [karlwilbur] - Fix regexp for numeric domains (fixes [#72](https://github.com/K-and-R/email_validator/issues/72)) - [delphaber] - Add checks for numeric-only domains in tests (should be considered valid) - [karlwilbur] - Fix specs for numeric-only domains labels (should be considered valid) - [karlwilbur] - Add checks for numeric-only TLDs in tests (should be considered invalid) - [karlwilbur] - Add tests to ensure that `regexp` returns expected value * [karlwilbur] - Add checks for double dash in domain (should be considered invalid) * [karlwilbur] - Add `EmailValidator::Error` class, raise `EmailValidator::Error` when invalid `mode` ## 2.2.2 (2020-12-10) * [karlwilbur] - Fix includes for `:rfc` and `:strict` modes from `Gemfile` ## 2.2.1 (2020-12-10) * [karlwilbur] - Modify regexp to: - allow numeric-only hosts [#68] - allow mailbox-only addresses in `:rfc` mode - enforce the 255-char domain limit (not in `:loose` mode unless using `:domain`) ## 2.2.0 (2020-12-09) * [karlwilbur] - Rename `:strict` -> `:rfc`; `:moderate` -> `:strict` ## 2.1.0 (2020-12-09) * [karlwilbur] - Add linters and commit hooks to validate code prior to commits * [karlwilbur] - Add `:mode` config option; values `:loose`, `:moderate`, `:strict`; default to `:loose` * [karlwilbur] - Merge in changes from fork ## 1.9.0.pre (2020-10-14) * [karlwilbur] - Add `require_fqdn` option, require FQDN by default * [karlwilbur] - Add support for IPv4 and IPv6 address hosts * [karlwilbur] - Add Rubocop, `.editorconfig`; code cleanup/linting ## 1.8.0 (2019-06-14) * [karlwilbur] - Refactor class methods for readability * [karlwilbur] - `gemspec` meta updates * [karlwilbur] - Use POSIX classes for better performance * [karlwilbur] - Refactored tests to check specical characters one at a time * [karlwilbur] - Refactored validation regex to be more techincally correct * [karlwilbur] - Add this `CHANGELOG` ## 1.7.0 (2019-04-20) * [karlwilbur] - Added test coverage badge to README * [karlwilbur] - Added I18n directive to remove warning message in testing * [karlwilbur] - Added RFC-2822 reference * [karlwilbur] - Ignore local rspec config file * [karlwilbur] - Check for invalid double dots in strict mode * [karlwilbur] - Updated spec_helper to remove Code Climate Test Reporter; it is to be run separately now * [karlwilbur] - Allow leading/trailing whitespace in normal, not strict * [karlwilbur] - Added `invalid?` as inverse of `valid?` * [karlwilbur] - Add the ability to limit to a domain * [karlwilbur] - Removed CodeShip badge * [karlwilbur] - Make the dot in the domain part non-conditional * [karlwilbur] - Fix domain label pattern to allow numbers per rfc5321 ## 1.6.0 (2015-06-14) * [karlwilbur] - Fixed validation to be closer to RFC-5321 * [karlwilbur] - Updated specs to use Rspec 3 syntax * [karlwilbur] - Added unicode suport to validation regexp * [karlwilbur] - Added class access to regexp, and `valid?` calss method * [karlwilbur] - Simplified code using new methods * [karlwilbur] - Added CodeClimate and SimpleCov * [karlwilbur] - Updated version and contact info *** Forked from ## 2.0.1 (2019-03-09) * Add email value to error details [f1sherman #50] * CI doesn't test Ruby versions that no longer receive updates [f1sherman #51] ## 2.0.0 (2019-03-02) * Looser validation [#49] ## 1.6.0 (2015-05-12) * Unicode characters support [i7an #24] ## 1.5.0 (2014-12-08) * Add a class method for simpler validation [TiteiKo and cluesque #19] * RSpec 3.0 syntax [strivedi183 #17] * Create Changes.md --- Check the [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) for help with Markdown. The [Github Flavored Markdown page](http://github.github.com/github-flavored-markdown/) describes the differences between markdown on github and standard markdown. email_validator-2.2.4/LICENSE0000644000004100000410000000204314452122003015700 0ustar www-datawww-dataCopyright (c) 2009 Brian Alexander 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. email_validator-2.2.4/lib/0000755000004100000410000000000014452122003015442 5ustar www-datawww-dataemail_validator-2.2.4/lib/email_validator/0000755000004100000410000000000014452122003020576 5ustar www-datawww-dataemail_validator-2.2.4/lib/email_validator/strict.rb0000644000004100000410000000020314452122003022426 0ustar www-datawww-data# require this file to enable `:strict` mode by default require 'email_validator' EmailValidator.default_options[:mode] = :strict email_validator-2.2.4/lib/email_validator/rfc.rb0000644000004100000410000000017514452122003021700 0ustar www-datawww-data# require this file to enable `:rfc` mode by default require 'email_validator' EmailValidator.default_options[:mode] = :rfc email_validator-2.2.4/lib/email_validator.rb0000644000004100000410000001101014452122003021114 0ustar www-datawww-data# Based on work from http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/ # EmailValidator class class EmailValidator < ActiveModel::EachValidator # rubocop:disable Style/ClassVars @@default_options = { :allow_nil => false, :domain => nil, :require_fqdn => nil, :mode => :loose } # rubocop:enable Style/ClassVars # EmailValidator::Error class class Error < StandardError def initialize(msg = 'EmailValidator error') super end end class << self def default_options @@default_options end def valid?(value, options = {}) options = parse_options(options) return true if value.nil? && options[:allow_nil] == true return false if value.nil? # quickly fail if domain is required but doesn't match return false unless options[:domain].nil? || value[/^.*@#{regexp_safe_domain(options)}$/] !!(value =~ regexp(options)) end def invalid?(value, options = {}) !valid?(value, options) end # Refs: # https://tools.ietf.org/html/rfc2822 : 3.2. Lexical Tokens, 3.4.1. Addr-spec specification # https://tools.ietf.org/html/rfc5321 : 4.1.2. Command Argument Syntax def regexp(options = {}) options = parse_options(options) case options[:mode] when :loose loose_regexp(options) when :rfc rfc_regexp(options) when :strict options[:require_fqdn] = true strict_regexp(options) else fail EmailValidator::Error, "Validation mode '#{options[:mode]}' is not supported by EmailValidator" end end protected def loose_regexp(options = {}) return /\A[^\s]+@[^\s]+\z/ if options[:domain].nil? /\A[^\s]+@#{domain_part_pattern(options)}\z/ end def strict_regexp(options = {}) /\A(?>#{local_part_pattern})@#{domain_part_pattern(options)}\z/i end def rfc_regexp(options = {}) /\A(?>#{local_part_pattern})(?:@#{domain_part_pattern(options)})?\z/i end def alpha '[[:alpha:]]' end def alnum '[[:alnum:]]' end def alnumhy "(?:#{alnum}|-)" end def ipv4 '\d{1,3}(?:\.\d{1,3}){3}' end def ipv6 # only supporting full IPv6 addresses right now 'IPv6:[[:xdigit:]]{1,4}(?::[[:xdigit:]]{1,4}){7}' end def address_literal "\\[(?:#{ipv4}|#{ipv6})\\]" end def host_label_pattern "#{label_is_correct_length}" \ "#{alnum}(?:#{alnumhy}{,61}#{alnum})?" end # splitting this up into separate regex pattern for performance; let's not # try the "contains" pattern unless we have to def domain_label_pattern "#{host_label_pattern}\\.#{tld_label_pattern}" end # While, techincally, TLDs can be numeric-only, this is not allowed by ICANN # Ref: ICANN Application Guidebook for new TLDs (June 2012) # says the following starting at page 64: # # > The ASCII label must consist entirely of letters (alphabetic characters a-z) # # -- https://newgtlds.icann.org/en/applicants/agb/guidebook-full-04jun12-en.pdf def tld_label_pattern "#{alpha}{1,64}" end def label_is_correct_length '(?=[^.]{1,63}(?:\.|$))' end def domain_part_is_correct_length '(?=.{1,255}$)' end def atom_char # The `atext` spec # We are looking at this without whitespace; no whitespace support here "[-#{alpha}#{alnum}+_!\"'#$%^&*{}/=?`|~]" end def local_part_pattern # the `dot-atom-text` spec, but with a 64 character limit "#{atom_char}(?:\\.?#{atom_char}){,63}" end def domain_part_pattern(options) return regexp_safe_domain(options) unless options[:domain].nil? return fqdn_pattern if options[:require_fqdn] "#{domain_part_is_correct_length}(?:#{address_literal}|(?:#{host_label_pattern}\\.)*#{tld_label_pattern})" end def fqdn_pattern "(?=.{1,255}$)(?:#{host_label_pattern}\\.)*#{domain_label_pattern}" end private def parse_options(options) # `:strict` mode enables `:require_fqdn`, unless it is already explicitly disabled options[:require_fqdn] = true if options[:require_fqdn].nil? && options[:mode] == :strict default_options.merge(options) end def regexp_safe_domain(options) options[:domain].sub(/\./, '\.') end end def validate_each(record, attribute, value) options = @@default_options.merge(self.options) record.errors.add(attribute, options[:message] || :invalid) unless self.class.valid?(value, options) end end email_validator-2.2.4/email_validator.gemspec0000644000004100000410000000323214452122003021375 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: email_validator 2.2.4 ruby lib Gem::Specification.new do |s| s.name = "email_validator".freeze s.version = "2.2.4" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Brian Alexander".freeze, "Karl Wilbur".freeze] s.date = "2022-11-09" s.description = "An email validator for Rails 3+. See homepage for details: http://github.com/K-and-R/email_validator".freeze s.email = "karl@kandrsoftware.com".freeze s.extra_rdoc_files = ["CHANGELOG.md".freeze, "LICENSE".freeze, "README.md".freeze] s.files = ["CHANGELOG.md".freeze, "LICENSE".freeze, "README.md".freeze, "lib/email_validator.rb".freeze, "lib/email_validator/rfc.rb".freeze, "lib/email_validator/strict.rb".freeze, "spec/email_validator_spec.rb".freeze, "spec/spec_helper.rb".freeze] s.homepage = "https://github.com/K-and-R/email_validator".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.4.0".freeze) s.rubygems_version = "3.2.5".freeze s.summary = "An email validator for Rails 3+.".freeze s.test_files = ["spec/email_validator_spec.rb".freeze, "spec/spec_helper.rb".freeze] if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_runtime_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) end end