<commit_before>require "valid_email2"
require "resolv"
require "mail"

module ValidEmail2
  class Address
    attr_accessor :address

    ALLOWED_DOMAIN_CHARACTERS_REGEX = /\A[a-z0-9\-.]+\z/i

    def initialize(address)
      @parse_error = false
      @raw_address = address

      begin
        @address = Mail::Address.new(address)
      rescue Mail::Field::ParseError
        @parse_error = true
      end

      @parse_error ||= address_contain_emoticons? @raw_address
    end

    def valid?
      return false if @parse_error

      if address.domain && address.address == @raw_address
        domain = address.domain

        domain.match(ALLOWED_DOMAIN_CHARACTERS_REGEX) &&
          # Domain needs to have at least one dot
          domain.match(/\./) &&
          # Domain may not have two consecutive dots
          !domain.match(/\.{2,}/) &&
          # Domain may not start with a dot
          !domain.match(/^\./)
      else
        false
      end
    end

    def disposable?
      valid? && domain_is_in?(ValidEmail2.disposable_emails)
    end

    def blacklisted?
      valid? && domain_is_in?(ValidEmail2.blacklist)
    end

    def valid_mx?
      return false unless valid?

      Resolv::DNS.open do |dns|
        return dns.getresources(address.domain, Resolv::DNS::Resource::IN::MX).size > 0 ||
               dns.getresources(address.domain, Resolv::DNS::Resource::IN::A).size > 0
      end
    end

    private

    def domain_is_in?(domain_list)
      address_domain = address.domain.downcase
      domain_list.any? { |domain|
        address_domain.end_with?(domain) && address_domain =~ /\A(?:.+\.)*?#{domain}\z/
      }
    end

    def address_contain_emoticons? email_str
      (email_str.each_char.select { |char| char.bytesize > 1 }.join).empty? ? false : true
    end
  end
end
<commit_msg>Short circuit on nil value in address_contain_emoticons? Fixed #102<commit_after>require "valid_email2"
require "resolv"
require "mail"

module ValidEmail2
  class Address
    attr_accessor :address

    ALLOWED_DOMAIN_CHARACTERS_REGEX = /\A[a-z0-9\-.]+\z/i

    def initialize(address)
      @parse_error = false
      @raw_address = address

      begin
        @address = Mail::Address.new(address)
      rescue Mail::Field::ParseError
        @parse_error = true
      end

      @parse_error ||= address_contain_emoticons? @raw_address
    end

    def valid?
      return false if @parse_error

      if address.domain && address.address == @raw_address
        domain = address.domain

        domain.match(ALLOWED_DOMAIN_CHARACTERS_REGEX) &&
          # Domain needs to have at least one dot
          domain.match(/\./) &&
          # Domain may not have two consecutive dots
          !domain.match(/\.{2,}/) &&
          # Domain may not start with a dot
          !domain.match(/^\./)
      else
        false
      end
    end

    def disposable?
      valid? && domain_is_in?(ValidEmail2.disposable_emails)
    end

    def blacklisted?
      valid? && domain_is_in?(ValidEmail2.blacklist)
    end

    def valid_mx?
      return false unless valid?

      Resolv::DNS.open do |dns|
        return dns.getresources(address.domain, Resolv::DNS::Resource::IN::MX).size > 0 ||
               dns.getresources(address.domain, Resolv::DNS::Resource::IN::A).size > 0
      end
    end

    private

    def domain_is_in?(domain_list)
      address_domain = address.domain.downcase
      domain_list.any? { |domain|
        address_domain.end_with?(domain) && address_domain =~ /\A(?:.+\.)*?#{domain}\z/
      }
    end

    def address_contain_emoticons? email_str
      return false if email_str.nil?

      (email_str.each_char.select { |char| char.bytesize > 1 }.join).empty? ? false : true
    end
  end
end

{'fraction_non_alphanumeric': 0.11093333333333333, 'fraction_numerical': 0.0061333333333333335, 'mean_word_length': 2.400725294650952, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3072840', 'n_tokens_mistral': 1229, 'n_tokens_neox': 1192, 'n_words': 264}