Class: ValidateEmail

Inherits:
Object
  • Object
show all
Defined in:
lib/valid_email/validate_email.rb

Constant Summary collapse

SPECIAL_CHARS =
%w(( ) , : ; < > @ [ ])
SPECIAL_ESCAPED_CHARS =
%w(\  \\ ")
LOCAL_MAX_LEN =
64
DOMAIN_REGEX =
/\A^([[:alpha:]]{1}|([[:alnum:]][a-zA-Z0-9-]{0,61}[[:alnum:]]))(\.([[:alnum:]][a-zA-Z0-9-]{0,61}[[:alnum:]]))+\z/

Class Method Summary collapse

Class Method Details

.ban_disposable_email?(value) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
122
123
124
# File 'lib/valid_email/validate_email.rb', line 119

def ban_disposable_email?(value)
  m = Mail::Address.new(value)
  m.domain && !BanDisposableEmailValidator.config.include?(m.domain)
rescue Mail::Field::ParseError
  false
end

.domain_valid?(value) ⇒ Boolean

Returns:

  • (Boolean)


109
110
111
112
113
114
115
116
117
# File 'lib/valid_email/validate_email.rb', line 109

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

.mx_valid?(value, fallback = false) ⇒ Boolean

Returns:

  • (Boolean)


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/valid_email/validate_email.rb', line 89

def mx_valid?(value, fallback=false)
  m = Mail::Address.new(value)
  return false unless m.domain

  mx = []
  Resolv::DNS.open do |dns|
    dns.timeouts = MxValidator.config[:timeouts] unless MxValidator.config[:timeouts].empty?
    mx.concat dns.getresources(m.domain, Resolv::DNS::Resource::IN::MX)
    mx.concat dns.getresources(m.domain, Resolv::DNS::Resource::IN::A) if fallback
  end

  return mx.any?
rescue Mail::Field::ParseError
  false
end

.mx_valid_with_fallback?(value) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/valid_email/validate_email.rb', line 105

def mx_valid_with_fallback?(value)
  mx_valid?(value, true)
end

.valid?(value, user_options = {}) ⇒ Boolean

Returns:

  • (Boolean)


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/valid_email/validate_email.rb', line 10

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.any?(&: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

.valid_dot_atom?(dot_atom) ⇒ Boolean

Returns:

  • (Boolean)


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/valid_email/validate_email.rb', line 64

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

.valid_local?(local) ⇒ Boolean

Returns:

  • (Boolean)


57
58
59
60
61
62
# File 'lib/valid_email/validate_email.rb', line 57

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