class KawaiiEmailAddress::Validator

Constants

BACKSLASH
DOMAIN_LITERAL_RE
DOUBLE_QUOTE
LocalPartChars
LocalPartQuotedStringChars
PERIOD

Attributes

period_restriction_violate_domains[RW]
domain_part[R]
local_part[R]

Public Class Methods

new(address) click to toggle source
# File lib/kawaii_email_address/validator.rb, line 22
def initialize(address)
  @domain_part, @local_part = address.reverse.split('@', 2).map(&:reverse)
end

Public Instance Methods

both_part_present?() click to toggle source
# File lib/kawaii_email_address/validator.rb, line 34
def both_part_present?
  local_part && domain_part
end
to_s() click to toggle source
# File lib/kawaii_email_address/validator.rb, line 30
def to_s
  [local_part, domain_part].join('@')
end
valid?() click to toggle source
# File lib/kawaii_email_address/validator.rb, line 26
def valid?
  both_part_present? && valid_local_part? && valid_domain_part?
end
valid_domain_part?() click to toggle source
# File lib/kawaii_email_address/validator.rb, line 84
def valid_domain_part?
  if match = DOMAIN_LITERAL_RE.match(domain_part)
    valid_domain_literal?(match[:ip_addr])
  else
    valid_fqdn_domain_part?
  end
end
valid_local_part?() click to toggle source
# File lib/kawaii_email_address/validator.rb, line 38
def valid_local_part?
  return false if local_part.empty?
  return false if invalid_period_position?

  in_quoted_pair    = false
  in_quoted_string  = false

  is_valid = local_part.chars.each.with_index.all? do |char, i|
    # accept anything if it's got a backslash before it
    if in_quoted_pair
      in_quoted_pair = false
      next true
    end

    case char
    when BACKSLASH # backslash signifies the start of a quoted pair
      # must be in quoted string per http://www.rfc-editor.org/errata_search.php?rfc=3696
      if (i < local_part.length - 1) && in_quoted_string
        in_quoted_pair = true
        next true
      end

    when DOUBLE_QUOTE # double quote delimits quoted strings
      if i == 0
        in_quoted_string = true
        next true
      elsif (i == local_part.length - 1) && in_quoted_string
        in_quoted_string = false
        next true
      end

    when PERIOD
      period_restriction_violate_domain? ||
      in_quoted_string ||
      local_part[i + 1] != PERIOD

    else
      LocalPartChars.include?(char) || \
      (in_quoted_string && LocalPartQuotedStringChars.include?(char))

    end
  end

  is_valid && !in_quoted_string
end

Private Instance Methods

invalid_period_position?() click to toggle source
# File lib/kawaii_email_address/validator.rb, line 120
def invalid_period_position?
  return false if period_restriction_violate_domain?

  local_part.start_with?(PERIOD) || local_part.end_with?(PERIOD)
end
period_restriction_violate_domain?() click to toggle source
# File lib/kawaii_email_address/validator.rb, line 116
def period_restriction_violate_domain?
  self.class.period_restriction_violate_domains.include?(domain_part)
end
valid_domain_literal?(domain) click to toggle source
# File lib/kawaii_email_address/validator.rb, line 94
def valid_domain_literal?(domain)
  begin
    IPAddr.new(domain)
  rescue ArgumentError
    false
  end
end
valid_fqdn_domain_part?() click to toggle source
# File lib/kawaii_email_address/validator.rb, line 102
def valid_fqdn_domain_part?
  parts = domain_part.downcase.split('.', -1)

  return false if parts.length <= 1

  return false if parts.any? do |part|
    part.nil? || part.empty? || part !~ /\A[[:alnum:]\-]+\z/ || part.start_with?('-') || part.end_with?('-')
  end

  return false if parts.last.length < 2 || parts.last !~ /[a-z\-]/

  return true
end