Module: Philiprehberger::EmailValidator

Defined in:
lib/philiprehberger/email_validator.rb,
lib/philiprehberger/email_validator/result.rb,
lib/philiprehberger/email_validator/syntax.rb,
lib/philiprehberger/email_validator/version.rb,
lib/philiprehberger/email_validator/mx_check.rb,
lib/philiprehberger/email_validator/disposable.rb,
lib/philiprehberger/email_validator/normalizer.rb,
lib/philiprehberger/email_validator/configuration.rb,
lib/philiprehberger/email_validator/typo_suggester.rb,
lib/philiprehberger/email_validator/domain_info_extractor.rb

Defined Under Namespace

Modules: Disposable, DomainInfoExtractor, MxCheck, Normalizer, Syntax, TypoSuggester Classes: Configuration, Error, Result

Constant Summary collapse

ROLE_BASED_LOCALS =

Role-based local parts that typically represent groups, not individuals.

Set.new(%w[
  abuse admin billing contact dev devnull ftp help hostmaster
  info mail mailer-daemon marketing noc noreply no-reply
  office postmaster press registrar remove root sales security
  spam subscribe support sysadmin tech undisclosed-recipients
  unsubscribe usenet uucp webmaster www
]).freeze
VERSION =
'0.4.0'

Class Method Summary collapse

Class Method Details

.batch_validate(emails, **opts) ⇒ Hash{String => Result}

Validate multiple emails and return a hash mapping each email to its Result.

Parameters:

  • emails (Array<String>)

    the email addresses to validate

  • opts (Hash)

    options passed to validate (check_mx:, allow_disposable:)

Returns:

  • (Hash{String => Result})

    hash of email => Result pairs



78
79
80
81
82
# File 'lib/philiprehberger/email_validator.rb', line 78

def batch_validate(emails, **opts)
  emails.to_h do |email|
    [email, validate(email, **opts)]
  end
end

.canonical_equal?(a, b) ⇒ Boolean

Compare two email addresses after normalization.

Returns false rather than raising if either input is invalid.

Parameters:

  • a (String)

    first email address

  • b (String)

    second email address

Returns:

  • (Boolean)

    true if both normalize to the same address



159
160
161
162
163
# File 'lib/philiprehberger/email_validator.rb', line 159

def canonical_equal?(a, b)
  Normalizer.normalize(a) == Normalizer.normalize(b)
rescue Error, StandardError
  false
end

.configurationConfiguration

The current configuration instance.

Returns:



139
140
141
# File 'lib/philiprehberger/email_validator.rb', line 139

def configuration
  @configuration ||= Configuration.new
end

.configure {|Configuration| ... } ⇒ void

This method returns an undefined value.

Configure the email validator.

Yields:



125
126
127
# File 'lib/philiprehberger/email_validator.rb', line 125

def configure
  yield configuration
end

.disposable?(email) ⇒ Boolean

Check if an email address uses a known disposable domain.

Parameters:

  • email (String)

    the email address to check

Returns:

  • (Boolean)

    true if the domain is disposable



104
105
106
# File 'lib/philiprehberger/email_validator.rb', line 104

def disposable?(email)
  disposable_domain?(email)
end

.domain_info(email, check_mx: false) ⇒ Hash

Extract domain information from an email address.

Parameters:

  • email (String)

    the email address to analyze

  • check_mx (Boolean) (defaults to: false)

    whether to look up MX records (default: false)

Returns:

  • (Hash)

    { domain:, tld:, mx_records: }

Raises:

  • (Error)

    if format is invalid



179
180
181
# File 'lib/philiprehberger/email_validator.rb', line 179

def domain_info(email, check_mx: false)
  DomainInfoExtractor.extract(email, check_mx: check_mx)
end

.mx_valid?(domain) ⇒ Boolean

Check if a domain has valid MX records.

Parameters:

  • domain (String)

    the domain to check

Returns:

  • (Boolean)

    true if MX or A records exist



96
97
98
# File 'lib/philiprehberger/email_validator.rb', line 96

def mx_valid?(domain)
  MxCheck.valid?(domain)
end

.normalize(email) ⇒ String

Normalize an email address.

Parameters:

  • email (String)

    the email address to normalize

Returns:

  • (String)

    the normalized email address

Raises:

  • (Error)

    if format is invalid



148
149
150
# File 'lib/philiprehberger/email_validator.rb', line 148

def normalize(email)
  Normalizer.normalize(email)
end

.reset_configuration!void

This method returns an undefined value.

Reset configuration to defaults.



132
133
134
# File 'lib/philiprehberger/email_validator.rb', line 132

def reset_configuration!
  @configuration = Configuration.new
end

.role_based?(email) ⇒ Boolean

Detect role-based email addresses (info@, admin@, support@, etc.).

Parameters:

  • email (String)

    the email address to check

Returns:

  • (Boolean)

    true if the local part is role-based



112
113
114
115
116
117
118
119
# File 'lib/philiprehberger/email_validator.rb', line 112

def role_based?(email)
  return false unless email.is_a?(String)

  local = extract_local(email)
  return false if local.nil?

  ROLE_BASED_LOCALS.include?(local.downcase)
end

.suggest(email) ⇒ Hash?

Suggest a corrected email if the domain appears to be a typo.

Parameters:

  • email (String)

    the email address to check

Returns:

  • (Hash, nil)

    { original:, suggested: } or nil if no suggestion



169
170
171
# File 'lib/philiprehberger/email_validator.rb', line 169

def suggest(email)
  TypoSuggester.suggest(email)
end

.valid?(email) ⇒ Boolean

Quick syntax check for an email address.

Parameters:

  • email (String)

    the email address to validate

Returns:

  • (Boolean)

    true if syntax is valid



33
34
35
# File 'lib/philiprehberger/email_validator.rb', line 33

def valid?(email)
  Syntax.valid?(email)
end

.valid_all?(emails) ⇒ Boolean

Check if all emails in an array are valid.

Parameters:

  • emails (Array<String>)

    the email addresses to check

Returns:

  • (Boolean)

    true only if all emails are valid



88
89
90
# File 'lib/philiprehberger/email_validator.rb', line 88

def valid_all?(emails)
  emails.all? { |email| valid?(email) }
end

.validate(email, check_mx: false, allow_disposable: true) ⇒ Result

Full validation returning a Result object.

Parameters:

  • email (String)

    the email address to validate

  • check_mx (Boolean) (defaults to: false)

    whether to verify MX records (default: false)

  • allow_disposable (Boolean) (defaults to: true)

    whether to allow disposable domains (default: true)

Returns:

  • (Result)

    validation result with errors and warnings



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/philiprehberger/email_validator.rb', line 43

def validate(email, check_mx: false, allow_disposable: true)
  errors = []
  warnings = []

  syntax_errors = Syntax.validate(email)
  errors.concat(syntax_errors)

  if syntax_errors.empty?
    errors << 'disposable email domains are not allowed' if !allow_disposable && disposable_domain?(email)

    warnings << 'address appears to be role-based' if role_based?(email)

    if check_mx
      domain = extract_domain(email)
      errors << "domain '#{domain}' has no MX or A records" unless MxCheck.valid?(domain)
    end
  end

  Result.new(errors: errors, warnings: warnings)
end

.validate_all(emails, **opts) ⇒ Array<Result>

Validate an array of email addresses.

Parameters:

  • emails (Array<String>)

    the email addresses to validate

  • opts (Hash)

    options passed to validate (check_mx:, allow_disposable:)

Returns:

  • (Array<Result>)

    array of Result objects



69
70
71
# File 'lib/philiprehberger/email_validator.rb', line 69

def validate_all(emails, **opts)
  emails.map { |email| validate(email, **opts) }
end