truemail 1.8.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,6 +5,7 @@ require_relative 'truemail/core'
5
5
  module Truemail
6
6
  INCOMPLETE_CONFIG = 'verifier_email is required parameter'
7
7
  NOT_CONFIGURED = 'use Truemail.configure before or pass custom configuration'
8
+ INVALID_TYPE = 'email should be a String'
8
9
 
9
10
  class << self
10
11
  def configuration(&block)
@@ -25,10 +26,12 @@ module Truemail
25
26
  end
26
27
 
27
28
  def validate(email, custom_configuration: nil, **options)
29
+ check_argument_type(email)
28
30
  Truemail::Validator.new(email, configuration: determine_configuration(custom_configuration), **options).run
29
31
  end
30
32
 
31
33
  def valid?(email, **options)
34
+ check_argument_type(email)
32
35
  validate(email, **options).result.valid?
33
36
  end
34
37
 
@@ -38,8 +41,12 @@ module Truemail
38
41
 
39
42
  private
40
43
 
41
- def raise_unless(condition, message)
42
- raise Truemail::ConfigurationError, message unless condition
44
+ def raise_unless(condition, message, error_class = Truemail::ConfigurationError)
45
+ raise error_class, message unless condition
46
+ end
47
+
48
+ def check_argument_type(argument)
49
+ raise_unless(argument.is_a?(String), Truemail::INVALID_TYPE, Truemail::TypeError)
43
50
  end
44
51
 
45
52
  def determine_configuration(custom_configuration)
@@ -3,7 +3,7 @@
3
3
  module Truemail
4
4
  module Audit
5
5
  class Dns < Truemail::Audit::Base
6
- VERIFIER_DOMAIN_NOT_REFER = 'a record of verifier domain not refers to current host ip address'
6
+ VERIFIER_DOMAIN_NOT_REFER = 'A-record of verifier domain not refers to current host ip address'
7
7
 
8
8
  def run
9
9
  return if verifier_domain_refer_to_current_host_ip?
@@ -3,8 +3,8 @@
3
3
  module Truemail
4
4
  module Audit
5
5
  class Ptr < Truemail::Audit::Base
6
- PTR_NOT_FOUND = 'ptr record for current host ip address was not found'
7
- PTR_NOT_REFER = 'ptr record does not reference to current verifier domain'
6
+ PTR_NOT_FOUND = 'PTR-record for current host ip address was not found'
7
+ PTR_NOT_REFER = 'PTR-record does not reference to current verifier domain'
8
8
 
9
9
  def run
10
10
  return add_warning(Truemail::Audit::Ptr::PTR_NOT_FOUND) if ptr_records.empty?
@@ -1,15 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Truemail
4
- class Auditor
4
+ class Auditor < Truemail::Executor
5
5
  Result = Struct.new(:current_host_ip, :warnings, :configuration, keyword_init: true) do
6
6
  def initialize(warnings: {}, **args)
7
7
  super
8
8
  end
9
9
  end
10
10
 
11
- attr_reader :result
12
-
13
11
  def initialize(configuration:)
14
12
  @result = Truemail::Auditor::Result.new(configuration: configuration)
15
13
  end
@@ -18,5 +16,9 @@ module Truemail
18
16
  Truemail::Audit::Ip.check(result)
19
17
  self
20
18
  end
19
+
20
+ def as_json
21
+ Truemail::Log::Serializer::AuditorJson.call(self)
22
+ end
21
23
  end
22
24
  end
@@ -6,6 +6,7 @@ module Truemail
6
6
  DEFAULT_RESPONSE_TIMEOUT = 2
7
7
  DEFAULT_CONNECTION_ATTEMPTS = 2
8
8
  DEFAULT_VALIDATION_TYPE = :smtp
9
+ DEFAULT_LOGGER_OPTIONS = { tracking_event: :error, stdout: false, log_absolute_path: nil }.freeze
9
10
 
10
11
  attr_reader :email_pattern,
11
12
  :smtp_error_body_pattern,
@@ -71,7 +72,8 @@ module Truemail
71
72
  end
72
73
  end
73
74
 
74
- def logger=(tracking_event: :error, stdout: false, log_absolute_path: nil)
75
+ def logger=(options)
76
+ tracking_event, stdout, log_absolute_path = logger_options(options)
75
77
  valid_event = Truemail::Log::Event::TRACKING_EVENTS.key?(tracking_event)
76
78
  stdout_only = stdout && log_absolute_path.nil?
77
79
  file_only = log_absolute_path.is_a?(String)
@@ -109,7 +111,7 @@ module Truemail
109
111
  end
110
112
 
111
113
  def validate_arguments(argument, method)
112
- constant = Truemail::RegexConstant.const_get("regex_#{method[/\A.+_(.+)\=\z/, 1]}_pattern".upcase)
114
+ constant = Truemail::RegexConstant.const_get("regex_#{method[/\A.+_(.+)=\z/, 1]}_pattern".upcase)
113
115
  raise_unless(argument, method, constant.match?(argument.to_s))
114
116
  end
115
117
 
@@ -140,5 +142,9 @@ module Truemail
140
142
  check_validation_type(validation_type)
141
143
  end
142
144
  end
145
+
146
+ def logger_options(current_options)
147
+ Truemail::Configuration::DEFAULT_LOGGER_OPTIONS.merge(current_options).values
148
+ end
143
149
  end
144
150
  end
@@ -4,12 +4,14 @@ module Truemail
4
4
  require_relative '../truemail/version'
5
5
  require_relative '../truemail/configuration'
6
6
  require_relative '../truemail/worker'
7
+ require_relative '../truemail/executor'
7
8
  require_relative '../truemail/wrapper'
8
9
  require_relative '../truemail/auditor'
9
10
  require_relative '../truemail/validator'
10
11
  require_relative '../truemail/logger'
11
12
 
12
13
  ConfigurationError = Class.new(StandardError)
14
+ TypeError = Class.new(StandardError)
13
15
 
14
16
  ArgumentError = Class.new(StandardError) do
15
17
  def initialize(arg_value, arg_name)
@@ -29,8 +31,8 @@ module Truemail
29
31
  end
30
32
 
31
33
  module RegexConstant
32
- REGEX_DOMAIN = /[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}/i.freeze
33
- REGEX_EMAIL_PATTERN = /(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@(#{REGEX_DOMAIN})\z)/.freeze
34
+ REGEX_DOMAIN = /[\p{L}0-9]+([\-.]{1}[\p{L}0-9]+)*\.\p{L}{2,63}/i.freeze
35
+ REGEX_EMAIL_PATTERN = /(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|.|+]*)@(#{REGEX_DOMAIN})\z)/.freeze
34
36
  REGEX_DOMAIN_PATTERN = /(?=\A.{4,255}\z)(\A#{REGEX_DOMAIN}\z)/.freeze
35
37
  REGEX_DOMAIN_FROM_EMAIL = /\A.+@(.+)\z/.freeze
36
38
  REGEX_SMTP_ERROR_BODY_PATTERN = /(?=.*550)(?=.*(user|account|customer|mailbox)).*/i.freeze
@@ -56,7 +58,9 @@ module Truemail
56
58
  module Log
57
59
  require_relative '../truemail/log/event'
58
60
  require_relative '../truemail/log/serializer/base'
59
- require_relative '../truemail/log/serializer/text'
60
- require_relative '../truemail/log/serializer/json'
61
+ require_relative '../truemail/log/serializer/auditor_json'
62
+ require_relative '../truemail/log/serializer/validator_base'
63
+ require_relative '../truemail/log/serializer/validator_text'
64
+ require_relative '../truemail/log/serializer/validator_json'
61
65
  end
62
66
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truemail
4
+ class Executor
5
+ attr_reader :result
6
+
7
+ def run; end
8
+
9
+ def as_json; end
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truemail
4
+ module Log
5
+ module Serializer
6
+ class AuditorJson < Truemail::Log::Serializer::Base
7
+ def serialize
8
+ result.to_json
9
+ end
10
+
11
+ private
12
+
13
+ def result
14
+ @result ||=
15
+ {
16
+ date: Time.now,
17
+ current_host_ip: executor_result.current_host_ip,
18
+ warnings: warnings(executor_result.warnings),
19
+ configuration: configuration
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -4,47 +4,35 @@ module Truemail
4
4
  module Log
5
5
  module Serializer
6
6
  class Base
7
+ require 'json'
8
+
7
9
  DEFAULT_GEM_VALUE = 'default gem value'
8
10
 
9
- def self.call(validator_instance)
10
- new(validator_instance).serialize
11
+ def self.call(executor_instance)
12
+ new(executor_instance).serialize
11
13
  end
12
14
 
13
- def initialize(validator_instance)
14
- @validation_type = validator_instance.validation_type
15
- @validation_result = validator_instance.result
16
- @validation_configuration = validation_result.configuration
15
+ def initialize(executor_instance)
16
+ @executor_result = executor_instance.result
17
+ @executor_configuration = executor_result.configuration
17
18
  end
18
19
 
19
20
  def serialize; end
20
21
 
21
22
  private
22
23
 
23
- attr_reader :validation_type, :validation_result, :validation_configuration
24
+ attr_reader :executor_result, :executor_configuration
24
25
 
25
- def errors
26
- validation_errors = validation_result.errors
27
- return if validation_errors.empty?
28
- validation_errors
26
+ def errors(executor_result_target)
27
+ return if executor_result_target.empty?
28
+ executor_result_target
29
29
  end
30
30
 
31
- def smtp_debug
32
- validation_smtp_debug = validation_result.smtp_debug
33
- return unless validation_smtp_debug
34
- validation_smtp_debug.map do |smtp_request|
35
- smtp_response = smtp_request.response
36
- {
37
- mail_host: smtp_request.host,
38
- port_opened: smtp_response.port_opened,
39
- connection: smtp_response.connection,
40
- errors: smtp_response.errors
41
- }
42
- end
43
- end
31
+ alias warnings errors
44
32
 
45
33
  %i[validation_type_by_domain whitelisted_domains blacklisted_domains].each do |method|
46
34
  define_method(method) do
47
- value = validation_configuration.public_send(method)
35
+ value = executor_configuration.public_send(method)
48
36
  return if value.empty?
49
37
  value
50
38
  end
@@ -52,7 +40,7 @@ module Truemail
52
40
 
53
41
  %i[email_pattern smtp_error_body_pattern].each do |method|
54
42
  define_method(method) do
55
- value = validation_configuration.public_send(method)
43
+ value = executor_configuration.public_send(method)
56
44
  default_pattern = Truemail::RegexConstant.const_get(
57
45
  (method.eql?(:email_pattern) ? :regex_email_pattern : :regex_smtp_error_body_pattern).upcase
58
46
  )
@@ -64,28 +52,15 @@ module Truemail
64
52
  def configuration
65
53
  {
66
54
  validation_type_by_domain: validation_type_by_domain,
67
- whitelist_validation: validation_configuration.whitelist_validation,
55
+ whitelist_validation: executor_configuration.whitelist_validation,
68
56
  whitelisted_domains: whitelisted_domains,
69
57
  blacklisted_domains: blacklisted_domains,
70
- not_rfc_mx_lookup_flow: validation_configuration.not_rfc_mx_lookup_flow,
71
- smtp_safe_check: validation_configuration.smtp_safe_check,
58
+ not_rfc_mx_lookup_flow: executor_configuration.not_rfc_mx_lookup_flow,
59
+ smtp_safe_check: executor_configuration.smtp_safe_check,
72
60
  email_pattern: email_pattern,
73
61
  smtp_error_body_pattern: smtp_error_body_pattern
74
62
  }
75
63
  end
76
-
77
- def result
78
- @result ||=
79
- {
80
- date: Time.now,
81
- email: validation_result.email,
82
- validation_type: validation_type,
83
- success: validation_result.success,
84
- errors: errors,
85
- smtp_debug: smtp_debug,
86
- configuration: configuration
87
- }
88
- end
89
64
  end
90
65
  end
91
66
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truemail
4
+ module Log
5
+ module Serializer
6
+ class ValidatorBase < Truemail::Log::Serializer::Base
7
+ def initialize(executor_instance)
8
+ @validation_type = executor_instance.validation_type
9
+ super
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :validation_type
15
+
16
+ def smtp_debug
17
+ validation_smtp_debug = executor_result.smtp_debug
18
+ return unless validation_smtp_debug
19
+ validation_smtp_debug.map do |smtp_request|
20
+ smtp_response = smtp_request.response
21
+ {
22
+ mail_host: smtp_request.host,
23
+ port_opened: smtp_response.port_opened,
24
+ connection: smtp_response.connection,
25
+ errors: smtp_response.errors
26
+ }
27
+ end
28
+ end
29
+
30
+ def result
31
+ @result ||=
32
+ {
33
+ date: Time.now,
34
+ email: executor_result.email,
35
+ validation_type: validation_type,
36
+ success: executor_result.success,
37
+ errors: errors(executor_result.errors),
38
+ smtp_debug: smtp_debug,
39
+ configuration: configuration
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -3,7 +3,7 @@
3
3
  module Truemail
4
4
  module Log
5
5
  module Serializer
6
- class Json < Truemail::Log::Serializer::Base
6
+ class ValidatorJson < Truemail::Log::Serializer::ValidatorBase
7
7
  def serialize
8
8
  result.to_json
9
9
  end
@@ -3,7 +3,7 @@
3
3
  module Truemail
4
4
  module Log
5
5
  module Serializer
6
- class Text < Truemail::Log::Serializer::Base
6
+ class ValidatorText < Truemail::Log::Serializer::ValidatorBase
7
7
  ATTEMPT = 'ATTEMPT #'
8
8
 
9
9
  def serialize
@@ -30,7 +30,7 @@ module Truemail
30
30
 
31
31
  def collection_printer(collection)
32
32
  collection.inject([]) { |array, hash| array << printer(hash) }.map.with_index do |item, index|
33
- "\n#{Truemail::Log::Serializer::Text::ATTEMPT}#{index + 1}:\n#{item}\n"
33
+ "\n#{Truemail::Log::Serializer::ValidatorText::ATTEMPT}#{index + 1}:\n#{item}\n"
34
34
  end
35
35
  end
36
36
 
@@ -15,7 +15,7 @@ module Truemail
15
15
  def push(validator_instance)
16
16
  current_event = Truemail::Log::Event.new(event, validator_instance)
17
17
  return unless current_event.valid?
18
- create_logs(current_event.log_level, Truemail::Log::Serializer::Text.call(validator_instance))
18
+ create_logs(current_event.log_level, Truemail::Log::Serializer::ValidatorText.call(validator_instance))
19
19
  end
20
20
 
21
21
  private
@@ -31,8 +31,8 @@ module Truemail
31
31
  end
32
32
 
33
33
  def run
34
- session.start do |smtp_request|
35
- response.connection = true
34
+ session.start(configuration.verifier_domain) do |smtp_request|
35
+ response.connection = response.helo = true
36
36
  smtp_handshakes(smtp_request, response)
37
37
  end
38
38
  rescue => error
@@ -83,7 +83,6 @@ module Truemail
83
83
 
84
84
  def session_data
85
85
  {
86
- helo: configuration.verifier_domain,
87
86
  mailfrom: configuration.verifier_email,
88
87
  rcptto: email
89
88
  }
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Truemail
4
- class Validator
4
+ class Validator < Truemail::Executor
5
5
  RESULT_ATTRS = %i[success email domain mail_servers errors smtp_debug configuration].freeze
6
6
  VALIDATION_TYPES = %i[regex mx smtp].freeze
7
7
 
@@ -16,9 +16,9 @@ module Truemail
16
16
  alias_method :valid?, :success
17
17
  end
18
18
 
19
- attr_reader :validation_type, :result
19
+ attr_reader :validation_type
20
20
 
21
- def initialize(email, with: nil, configuration:)
21
+ def initialize(email, configuration:, with: nil)
22
22
  with ||= configuration.default_validation_type
23
23
  raise Truemail::ArgumentError.new(with, :argument) unless Truemail::Validator::VALIDATION_TYPES.include?(with)
24
24
  @result = Truemail::Validator::Result.new(email: email, configuration: configuration)
@@ -33,7 +33,7 @@ module Truemail
33
33
  end
34
34
 
35
35
  def as_json
36
- Truemail::Log::Serializer::Json.call(self)
36
+ Truemail::Log::Serializer::ValidatorJson.call(self)
37
37
  end
38
38
 
39
39
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Truemail
4
- VERSION = '1.8.0'
4
+ VERSION = '2.0.1'
5
5
  end
@@ -13,9 +13,17 @@ Gem::Specification.new do |spec|
13
13
  spec.summary = %(truemail)
14
14
  spec.description = %(Configurable framework agnostic plain Ruby email validator. Verify email via Regex, DNS and SMTP.)
15
15
 
16
- spec.homepage = 'https://github.com/rubygarage/truemail'
16
+ spec.homepage = 'https://github.com/truemail-rb/truemail'
17
17
  spec.license = 'MIT'
18
18
 
19
+ spec.metadata = {
20
+ 'homepage_uri' => 'https://truemail-rb.org',
21
+ 'changelog_uri' => 'https://github.com/truemail-rb/truemail/blob/master/CHANGELOG.md',
22
+ 'source_code_uri' => 'https://github.com/truemail-rb/truemail',
23
+ 'documentation_uri' => 'https://truemail-rb.org/truemail-gem',
24
+ 'bug_tracker_uri' => 'https://github.com/truemail-rb/truemail/issues'
25
+ }
26
+
19
27
  spec.required_ruby_version = '>= 2.5.0'
20
28
 
21
29
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
@@ -26,18 +34,18 @@ Gem::Specification.new do |spec|
26
34
  spec.add_runtime_dependency 'simpleidn', '~> 0.1.1'
27
35
 
28
36
  spec.add_development_dependency 'bundler', '~> 1.16'
29
- spec.add_development_dependency 'bundler-audit', '~> 0.6.1'
37
+ spec.add_development_dependency 'bundler-audit', '~> 0.7.0.1'
30
38
  spec.add_development_dependency 'fasterer', '~> 0.8.3'
31
- spec.add_development_dependency 'ffaker', '~> 2.14'
39
+ spec.add_development_dependency 'ffaker', '~> 2.17'
32
40
  spec.add_development_dependency 'json_matchers', '~> 0.11.1'
33
- spec.add_development_dependency 'overcommit', '~> 0.53.0'
41
+ spec.add_development_dependency 'overcommit', '~> 0.57.0'
34
42
  spec.add_development_dependency 'pry-byebug', '~> 3.9'
35
43
  spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.1'
36
- spec.add_development_dependency 'reek', '~> 6.0'
44
+ spec.add_development_dependency 'reek', '~> 6.0', '>= 6.0.2'
37
45
  spec.add_development_dependency 'rspec', '~> 3.9'
38
- spec.add_development_dependency 'rubocop', '~> 0.79.0'
39
- spec.add_development_dependency 'rubocop-performance', '~> 1.5', '>= 1.5.2'
40
- spec.add_development_dependency 'rubocop-rspec', '~> 1.39'
46
+ spec.add_development_dependency 'rubocop', '~> 0.93.1'
47
+ spec.add_development_dependency 'rubocop-performance', '~> 1.8', '>= 1.8.1'
48
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.43', '>= 1.43.2'
41
49
  spec.add_development_dependency 'simplecov', '~> 0.17.1'
42
- spec.add_development_dependency 'truemail-rspec', '~> 0.1.2'
50
+ spec.add_development_dependency 'truemail-rspec', '~> 0.2.1'
43
51
  end