truemail 1.6.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'truemail/core'
3
+ require_relative 'truemail/core'
4
4
 
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
8
 
9
9
  class << self
10
- def configuration
10
+ def configuration(&block)
11
11
  @configuration ||= begin
12
12
  return unless block_given?
13
- configuration = Truemail::Configuration.new
14
- yield(configuration)
13
+ configuration = Truemail::Configuration.new(&block)
15
14
  raise_unless(configuration.complete?, Truemail::INCOMPLETE_CONFIG)
16
15
  configuration
17
16
  end
@@ -3,12 +3,20 @@
3
3
  module Truemail
4
4
  module Audit
5
5
  class Base < Truemail::Worker
6
+ require 'net/http'
7
+ require 'ipaddr'
8
+ require 'resolv'
9
+
6
10
  private
7
11
 
8
12
  def add_warning(message)
9
13
  result.warnings[self.class.name.split('::').last.downcase.to_sym] = message
10
14
  end
11
15
 
16
+ def current_host_ip
17
+ result.current_host_ip
18
+ end
19
+
12
20
  def configuration
13
21
  result.configuration
14
22
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truemail
4
+ module Audit
5
+ class Dns < Truemail::Audit::Base
6
+ VERIFIER_DOMAIN_NOT_REFER = 'A-record of verifier domain not refers to current host ip address'
7
+
8
+ def run
9
+ return if verifier_domain_refer_to_current_host_ip?
10
+ add_warning(Truemail::Audit::Dns::VERIFIER_DOMAIN_NOT_REFER)
11
+ end
12
+
13
+ private
14
+
15
+ def a_record
16
+ Truemail::Wrapper.call(configuration: configuration) do
17
+ Resolv::DNS.new.getaddress(verifier_domain).to_s
18
+ end
19
+ end
20
+
21
+ def verifier_domain_refer_to_current_host_ip?
22
+ a_record.eql?(current_host_ip)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truemail
4
+ module Audit
5
+ class Ip < Truemail::Audit::Base
6
+ GET_MY_IP_URL = 'https://api.ipify.org'
7
+ IPIFY_ERROR = 'impossible to detect current host address via third party service'
8
+
9
+ def run
10
+ return add_warning(Truemail::Audit::Ip::IPIFY_ERROR) unless detect_current_host_ip
11
+ Truemail::Audit::Dns.check(result)
12
+ Truemail::Audit::Ptr.check(result)
13
+ end
14
+
15
+ private
16
+
17
+ def detect_ip_via_ipify
18
+ Net::HTTP.get(URI(Truemail::Audit::Ip::GET_MY_IP_URL))
19
+ end
20
+
21
+ def detect_current_host_ip
22
+ result.current_host_ip = Truemail::Wrapper.call(configuration: configuration) do
23
+ detect_ip_via_ipify
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -3,37 +3,19 @@
3
3
  module Truemail
4
4
  module Audit
5
5
  class Ptr < Truemail::Audit::Base
6
- require 'ipaddr'
7
- require 'resolv'
8
-
9
- GET_MY_IP_URL = 'https://api.ipify.org'
10
- IPIFY_ERROR = 'impossible to detect current host address via third party service'
11
- PTR_NOT_FOUND = 'ptr record for current host address was not found'
12
- PTR_NOT_REFER = 'ptr record does not reference to current verifier domain'
13
- VERIFIER_DOMAIN_NOT_REFER = 'a record of verifier domain not refers to current host address'
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'
14
8
 
15
9
  def run
16
- return if !current_host_address && add_warning(Truemail::Audit::Ptr::IPIFY_ERROR)
17
- return if ptr_records.empty? && add_warning(Truemail::Audit::Ptr::PTR_NOT_FOUND)
18
- return if ptr_not_refer_to_verifier_domain? && add_warning(Truemail::Audit::Ptr::PTR_NOT_REFER)
19
- return if verifier_domain_refer_to_current_host_address?
20
- add_warning(Truemail::Audit::Ptr::VERIFIER_DOMAIN_NOT_REFER)
10
+ return add_warning(Truemail::Audit::Ptr::PTR_NOT_FOUND) if ptr_records.empty?
11
+ return if ptr_refer_to_verifier_domain?
12
+ add_warning(Truemail::Audit::Ptr::PTR_NOT_REFER)
21
13
  end
22
14
 
23
15
  private
24
16
 
25
- def detect_ip_via_ipify
26
- Net::HTTP.get(URI(Truemail::Audit::Ptr::GET_MY_IP_URL))
27
- end
28
-
29
- def current_host_address
30
- @current_host_address ||= Truemail::Wrapper.call(configuration: configuration) do
31
- IPAddr.new(detect_ip_via_ipify)
32
- end
33
- end
34
-
35
17
  def current_host_reverse_lookup
36
- current_host_address.reverse
18
+ IPAddr.new(current_host_ip).reverse
37
19
  end
38
20
 
39
21
  def ptr_records
@@ -44,18 +26,8 @@ module Truemail
44
26
  end || []
45
27
  end
46
28
 
47
- def ptr_not_refer_to_verifier_domain?
48
- !ptr_records.include?(verifier_domain)
49
- end
50
-
51
- def a_record
52
- Truemail::Wrapper.call(configuration: configuration) do
53
- Resolv::DNS.new.getaddress(verifier_domain).to_s
54
- end
55
- end
56
-
57
- def verifier_domain_refer_to_current_host_address?
58
- a_record.eql?(current_host_address.to_s)
29
+ def ptr_refer_to_verifier_domain?
30
+ ptr_records.include?(verifier_domain)
59
31
  end
60
32
  end
61
33
  end
@@ -1,22 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Truemail
4
- class Auditor
5
- Result = Struct.new(:warnings, :configuration, keyword_init: true) do
4
+ class Auditor < Truemail::Executor
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
16
14
 
17
15
  def run
18
- Truemail::Audit::Ptr.check(result)
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
@@ -20,9 +20,7 @@ module Truemail
20
20
  :blacklisted_domains,
21
21
  :logger
22
22
 
23
- attr_accessor :whitelist_validation, :smtp_safe_check
24
-
25
- alias retry_count connection_attempts
23
+ attr_accessor :whitelist_validation, :not_rfc_mx_lookup_flow, :smtp_safe_check
26
24
 
27
25
  def initialize(&block)
28
26
  instance_initializer.each do |instace_variable, value|
@@ -101,6 +99,7 @@ module Truemail
101
99
  whitelisted_domains: [],
102
100
  whitelist_validation: false,
103
101
  blacklisted_domains: [],
102
+ not_rfc_mx_lookup_flow: false,
104
103
  smtp_safe_check: false
105
104
  }
106
105
  end
@@ -110,7 +109,7 @@ module Truemail
110
109
  end
111
110
 
112
111
  def validate_arguments(argument, method)
113
- constant = Truemail::RegexConstant.const_get("regex_#{method[/\A.+_(.+)\=\z/, 1]}_pattern".upcase)
112
+ constant = Truemail::RegexConstant.const_get("regex_#{method[/\A.+_(.+)=\z/, 1]}_pattern".upcase)
114
113
  raise_unless(argument, method, constant.match?(argument.to_s))
115
114
  end
116
115
 
@@ -1,19 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Truemail
4
- require 'truemail/version'
5
- require 'truemail/configuration'
6
- require 'truemail/worker'
7
- require 'truemail/wrapper'
8
- require 'truemail/auditor'
9
- require 'truemail/validator'
10
- require 'truemail/logger'
4
+ require_relative '../truemail/version'
5
+ require_relative '../truemail/configuration'
6
+ require_relative '../truemail/worker'
7
+ require_relative '../truemail/executor'
8
+ require_relative '../truemail/wrapper'
9
+ require_relative '../truemail/auditor'
10
+ require_relative '../truemail/validator'
11
+ require_relative '../truemail/logger'
11
12
 
12
13
  ConfigurationError = Class.new(StandardError)
13
14
 
14
15
  ArgumentError = Class.new(StandardError) do
15
- def initialize(current_param, class_name)
16
- super("#{current_param} is not a valid #{class_name}")
16
+ def initialize(arg_value, arg_name)
17
+ super("#{arg_value} is not a valid #{arg_name}")
17
18
  end
18
19
  end
19
20
 
@@ -29,32 +30,36 @@ module Truemail
29
30
  end
30
31
 
31
32
  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
33
+ REGEX_DOMAIN = /[\p{L}0-9]+([\-.]{1}[\p{L}0-9]+)*\.\p{L}{2,63}/i.freeze
34
+ REGEX_EMAIL_PATTERN = /(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|.|+]*)@(#{REGEX_DOMAIN})\z)/.freeze
34
35
  REGEX_DOMAIN_PATTERN = /(?=\A.{4,255}\z)(\A#{REGEX_DOMAIN}\z)/.freeze
35
36
  REGEX_DOMAIN_FROM_EMAIL = /\A.+@(.+)\z/.freeze
36
37
  REGEX_SMTP_ERROR_BODY_PATTERN = /(?=.*550)(?=.*(user|account|customer|mailbox)).*/i.freeze
37
38
  end
38
39
 
39
40
  module Audit
40
- require 'truemail/audit/base'
41
- require 'truemail/audit/ptr'
41
+ require_relative '../truemail/audit/base'
42
+ require_relative '../truemail/audit/ip'
43
+ require_relative '../truemail/audit/dns'
44
+ require_relative '../truemail/audit/ptr'
42
45
  end
43
46
 
44
47
  module Validate
45
- require 'truemail/validate/base'
46
- require 'truemail/validate/domain_list_match'
47
- require 'truemail/validate/regex'
48
- require 'truemail/validate/mx'
49
- require 'truemail/validate/smtp'
50
- require 'truemail/validate/smtp/response'
51
- require 'truemail/validate/smtp/request'
48
+ require_relative '../truemail/validate/base'
49
+ require_relative '../truemail/validate/domain_list_match'
50
+ require_relative '../truemail/validate/regex'
51
+ require_relative '../truemail/validate/mx'
52
+ require_relative '../truemail/validate/smtp'
53
+ require_relative '../truemail/validate/smtp/response'
54
+ require_relative '../truemail/validate/smtp/request'
52
55
  end
53
56
 
54
57
  module Log
55
- require 'truemail/log/event'
56
- require 'truemail/log/serializer/base'
57
- require 'truemail/log/serializer/text'
58
- require 'truemail/log/serializer/json'
58
+ require_relative '../truemail/log/event'
59
+ require_relative '../truemail/log/serializer/base'
60
+ require_relative '../truemail/log/serializer/auditor_json'
61
+ require_relative '../truemail/log/serializer/validator_base'
62
+ require_relative '../truemail/log/serializer/validator_text'
63
+ require_relative '../truemail/log/serializer/validator_json'
59
64
  end
60
65
  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,27 +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
- 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,
71
60
  email_pattern: email_pattern,
72
61
  smtp_error_body_pattern: smtp_error_body_pattern
73
62
  }
74
63
  end
75
-
76
- def result
77
- @result ||=
78
- {
79
- date: Time.now,
80
- email: validation_result.email,
81
- validation_type: validation_type,
82
- success: validation_result.success,
83
- errors: errors,
84
- smtp_debug: smtp_debug,
85
- configuration: configuration
86
- }
87
- end
88
64
  end
89
65
  end
90
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