class EmailValidator

EmailValidator class

Public Class Methods

default_options() click to toggle source
# File lib/email_validator.rb, line 22
def default_options
  @@default_options
end
invalid?(value, options = {}) click to toggle source
# File lib/email_validator.rb, line 33
def invalid?(value, options = {})
  !valid?(value, options)
end
regexp(options = {}) click to toggle source

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
# File lib/email_validator.rb, line 40
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
valid?(value, options = {}) click to toggle source
# File lib/email_validator.rb, line 26
def valid?(value, options = {})
  options = parse_options(options)
  return true if value.nil? && options[:allow_nil] == true
  return false if value.nil?
  !!(value =~ regexp(options))
end

Protected Class Methods

address_literal() click to toggle source
# File lib/email_validator.rb, line 91
def address_literal
  "\\[(?:#{ipv4}|#{ipv6})\\]"
end
alnum() click to toggle source
# File lib/email_validator.rb, line 74
def alnum
  '[[:alnum:]]'
end
alnumhy() click to toggle source
# File lib/email_validator.rb, line 78
def alnumhy
  "(?:#{alnum}|-)"
end
alpha() click to toggle source
# File lib/email_validator.rb, line 70
def alpha
  '[[:alpha:]]'
end
atom_char() click to toggle source
# File lib/email_validator.rb, line 130
def atom_char
  # The `atext` spec
  # We are looking at this without whitespace; no whitespace support here
  "[-#{alpha}#{alnum}+_!\"'#$%^&*{}/=?`|~]"
end
domain_label_pattern() click to toggle source

splitting this up into separate regex pattern for performance; let's not try the “contains” pattern unless we have to

# File lib/email_validator.rb, line 103
def domain_label_pattern
  "#{host_label_pattern}\\.#{tld_label_pattern}"
end
domain_part_is_correct_length() click to toggle source
# File lib/email_validator.rb, line 122
def domain_part_is_correct_length
  '(?=.{1,255}$)'
end
domain_part_pattern(options) click to toggle source
# File lib/email_validator.rb, line 141
def domain_part_pattern(options)
  return options[:domain].sub(/\./, '\.') if options[:domain].present?
  return fqdn_pattern if options[:require_fqdn]
  "#{domain_part_is_correct_length}(?:#{address_literal}|(?:#{host_label_pattern}\\.)*#{tld_label_pattern})"
end
fqdn_pattern() click to toggle source
# File lib/email_validator.rb, line 147
def fqdn_pattern
  "(?=.{1,255}$)(?:#{host_label_pattern}\\.)*#{domain_label_pattern}"
end
host_label_pattern() click to toggle source
# File lib/email_validator.rb, line 95
def host_label_pattern
  "#{label_is_correct_length}" \
  "#{label_contains_no_more_than_one_consecutive_hyphen}" \
  "#{alnum}(?:#{alnumhy}{,61}#{alnum})?"
end
ipv4() click to toggle source
# File lib/email_validator.rb, line 82
def ipv4
  '\d{1,3}(?:\.\d{1,3}){3}'
end
ipv6() click to toggle source
# File lib/email_validator.rb, line 86
def ipv6
  # only supporting full IPv6 addresses right now
  'IPv6:[[:xdigit:]]{1,4}(?::[[:xdigit:]]{1,4}){7}'
end
label_contains_no_more_than_one_consecutive_hyphen() click to toggle source
# File lib/email_validator.rb, line 126
def label_contains_no_more_than_one_consecutive_hyphen
  '(?!.*?--.*$)'
end
label_is_correct_length() click to toggle source
# File lib/email_validator.rb, line 118
def label_is_correct_length
  '(?=[^.]{1,63}(?:\.|$))'
end
local_part_pattern() click to toggle source
# File lib/email_validator.rb, line 136
def local_part_pattern
  # the `dot-atom-text` spec, but with a 64 character limit
  "#{atom_char}(?:\\.?#{atom_char}){,63}"
end
loose_regexp(options = {}) click to toggle source
# File lib/email_validator.rb, line 57
def loose_regexp(options = {})
  return /\A[^\s]+@[^\s]+\z/ if options[:domain].nil?
  /\A[^\s]+@#{domain_part_pattern(options)}\z/
end
rfc_regexp(options = {}) click to toggle source
# File lib/email_validator.rb, line 66
def rfc_regexp(options = {})
  /\A(?>#{local_part_pattern})(?:@#{domain_part_pattern(options)})?\z/i
end
strict_regexp(options = {}) click to toggle source
# File lib/email_validator.rb, line 62
def strict_regexp(options = {})
  /\A(?>#{local_part_pattern})@#{domain_part_pattern(options)}\z/i
end
tld_label_pattern() click to toggle source

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
# File lib/email_validator.rb, line 114
def tld_label_pattern
  "#{alpha}{1,64}"
end

Private Class Methods

parse_options(options) click to toggle source
# File lib/email_validator.rb, line 153
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

Public Instance Methods

validate_each(record, attribute, value) click to toggle source
# File lib/email_validator.rb, line 160
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