zerobounce-sdk 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.env.sample +3 -0
- data/.gitignore +59 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +21 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +121 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +391 -0
- data/Rakefile +26 -0
- data/bin/bundle +105 -0
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/data/zerobounce-ai-scoring.csv +31 -0
- data/data/zerobounce-batch-validation.csv +31 -0
- data/files/scoring.csv +1 -0
- data/files/validation.csv +1 -0
- data/files/zerobounce-ai-scoring.csv +31 -0
- data/files/zerobounce-batch-validation.csv +31 -0
- data/lib/zerobounce/base_request.rb +55 -0
- data/lib/zerobounce/configuration.rb +36 -0
- data/lib/zerobounce/error.rb +84 -0
- data/lib/zerobounce/mock_request.rb +63 -0
- data/lib/zerobounce/request.rb +63 -0
- data/lib/zerobounce/version.rb +6 -0
- data/lib/zerobounce.rb +370 -0
- data/output.err +737 -0
- data/output.log +250 -0
- data/zerobounce.gemspec +44 -0
- metadata +278 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
email,first,last,gender,ip
|
2
|
+
disposable@example.com,First,Last,male,127.0.0.1
|
3
|
+
invalid@example.com,First,Last,male,127.0.0.1
|
4
|
+
valid@example.com,First,Last,male,127.0.0.1
|
5
|
+
toxic@example.com,First,Last,male,127.0.0.1
|
6
|
+
donotmail@example.com,First,Last,male,127.0.0.1
|
7
|
+
spamtrap@example.com,First,Last,male,127.0.0.1
|
8
|
+
abuse@example.com,First,Last,male,127.0.0.1
|
9
|
+
unknown@example.com,First,Last,male,127.0.0.1
|
10
|
+
catch_all@example.com,First,Last,male,127.0.0.1
|
11
|
+
antispam_system@example.com,First,Last,male,127.0.0.1
|
12
|
+
does_not_accept_mail@example.com,First,Last,male,127.0.0.1
|
13
|
+
exception_occurred@example.com,First,Last,male,127.0.0.1
|
14
|
+
failed_smtp_connection@example.com,First,Last,male,127.0.0.1
|
15
|
+
failed_syntax_check@example.com,First,Last,male,127.0.0.1
|
16
|
+
forcible_disconnect@example.com,First,Last,male,127.0.0.1
|
17
|
+
global_suppression@example.com,First,Last,male,127.0.0.1
|
18
|
+
greylisted@example.com,First,Last,male,127.0.0.1
|
19
|
+
leading_period_removed@example.com,First,Last,male,127.0.0.1
|
20
|
+
mail_server_did_not_respond@example.com,First,Last,male,127.0.0.1
|
21
|
+
mail_server_temporary_error@example.com,First,Last,male,127.0.0.1
|
22
|
+
mailbox_quota_exceeded@example.com,First,Last,male,127.0.0.1
|
23
|
+
mailbox_not_found@example.com,First,Last,male,127.0.0.1
|
24
|
+
no_dns_entries@example.com,First,Last,male,127.0.0.1
|
25
|
+
possible_trap@example.com,First,Last,male,127.0.0.1
|
26
|
+
possible_typo@example.com,First,Last,male,127.0.0.1
|
27
|
+
role_based@example.com,First,Last,male,127.0.0.1
|
28
|
+
timeout_exceeded@example.com,First,Last,male,127.0.0.1
|
29
|
+
unroutable_ip_address@example.com,First,Last,male,127.0.0.1
|
30
|
+
free_email@example.com,First,Last,male,127.0.0.1
|
31
|
+
role_based_catch_all@example.com,First,Last,male,127.0.0.1
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# https://github.com/rest-client/rest-client
|
6
|
+
require 'rest-client'
|
7
|
+
|
8
|
+
|
9
|
+
module Zerobounce
|
10
|
+
|
11
|
+
# Sends the HTTP request.
|
12
|
+
class BaseRequest
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def self._get(root, path, params, content_type='application/json')
|
17
|
+
|
18
|
+
# puts path
|
19
|
+
# puts Zerobounce.config.apikey
|
20
|
+
|
21
|
+
raise ("API key must be assigned") if not Zerobounce.config.apikey
|
22
|
+
|
23
|
+
params[:api_key] = Zerobounce.config.apikey
|
24
|
+
url = "#{root}/#{path}"
|
25
|
+
|
26
|
+
response = RestClient.get(url, {params: params})
|
27
|
+
return response
|
28
|
+
end
|
29
|
+
|
30
|
+
def self._post(root, path, params, content_type='application/json', filepath=nil)
|
31
|
+
|
32
|
+
raise ("API key must be assigned") if not Zerobounce.config.apikey
|
33
|
+
|
34
|
+
params[:api_key] = Zerobounce.config.apikey
|
35
|
+
url = "#{root}/#{path}"
|
36
|
+
response = nil
|
37
|
+
|
38
|
+
if filepath or content_type == 'multipart/form-data'
|
39
|
+
params[:file] = File.new(filepath, 'rb')
|
40
|
+
params[:multipart] = true
|
41
|
+
response = RestClient.post(url, params)
|
42
|
+
|
43
|
+
elsif content_type == 'application/json'
|
44
|
+
response = RestClient.post(url, params.to_json, \
|
45
|
+
content_type: :json, accept: :json)
|
46
|
+
else
|
47
|
+
# this shouldn't happen
|
48
|
+
raise Error.new('Unknown content type specified in request.'\
|
49
|
+
' Must be either multipart/form-data or application/json.')
|
50
|
+
end
|
51
|
+
return response
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rest-client'
|
4
|
+
|
5
|
+
module Zerobounce
|
6
|
+
# Configuration object for Zerobounce.
|
7
|
+
#
|
8
|
+
# @author Aaron Frase
|
9
|
+
#
|
10
|
+
# @attr [String] host
|
11
|
+
# The Zerobounce API host.
|
12
|
+
#
|
13
|
+
# @attr [Hash] headers
|
14
|
+
# Headers to use in all requests.
|
15
|
+
#
|
16
|
+
# @attr [String] apikey
|
17
|
+
# A Zerobounce API key.
|
18
|
+
#
|
19
|
+
# @attr [Array<Symbol>] valid_statues
|
20
|
+
# The statuses that are considered valid by {Response#valid?}.
|
21
|
+
class Configuration
|
22
|
+
attr_accessor :host
|
23
|
+
attr_accessor :headers
|
24
|
+
attr_accessor :apikey
|
25
|
+
attr_accessor :valid_statuses
|
26
|
+
attr_accessor :mock
|
27
|
+
|
28
|
+
def initialize(mock=false)
|
29
|
+
self.host = 'https://api.zerobounce.net'
|
30
|
+
self.apikey = ENV['ZEROBOUNCE_API_KEY']
|
31
|
+
self.valid_statuses = %i[valid catch_all]
|
32
|
+
self.headers = { user_agent: "ZerobounceRubyGem/#{Zerobounce::VERSION}" }
|
33
|
+
self.mock = mock
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# todo:
|
6
|
+
|
7
|
+
module Zerobounce
|
8
|
+
# The base Zerobounce error.
|
9
|
+
#
|
10
|
+
# @author Aaron Frase
|
11
|
+
class Error < StandardError
|
12
|
+
attr_reader :env
|
13
|
+
|
14
|
+
def initialize(env={})
|
15
|
+
@env = env
|
16
|
+
super(env[:body])
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# Parse the response for errors.
|
21
|
+
#
|
22
|
+
# @param [Hash] env
|
23
|
+
# @return [Error, nil]
|
24
|
+
def from_response(env)
|
25
|
+
case env[:status]
|
26
|
+
when 500
|
27
|
+
parse500(env)
|
28
|
+
when 200
|
29
|
+
parse200(env)
|
30
|
+
else
|
31
|
+
UnknownError.new(env)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# @param [Hash] env
|
38
|
+
# @return [Error]
|
39
|
+
def parse500(env)
|
40
|
+
if env[:body].to_s.start_with?('Missing parameter')
|
41
|
+
MissingParameter.new(env)
|
42
|
+
else
|
43
|
+
InternalServerError.new(env)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param [Hash] env
|
48
|
+
# @return [Error, nil]
|
49
|
+
def parse200(env)
|
50
|
+
# The body hasn't been parsed yet and to avoid potentially parsing the body twice
|
51
|
+
# we just use String#start_with?
|
52
|
+
ApiError.new(env) if env[:body].to_s.start_with?('{"error":')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Server returned a 500 error.
|
58
|
+
#
|
59
|
+
# @author Aaron Frase
|
60
|
+
class InternalServerError < Error
|
61
|
+
end
|
62
|
+
|
63
|
+
# A parameter was missing, usually the apikey.
|
64
|
+
#
|
65
|
+
# @author Aaron Frase
|
66
|
+
class MissingParameter < Error
|
67
|
+
end
|
68
|
+
|
69
|
+
# When the status code isn't in the defined codes to parse.
|
70
|
+
#
|
71
|
+
# @author Aaron Frase
|
72
|
+
class UnknownError < Error
|
73
|
+
end
|
74
|
+
|
75
|
+
# General API error, the response code was 200 but an error still occurred.
|
76
|
+
#
|
77
|
+
# @author Aaron Frase
|
78
|
+
class ApiError < Error
|
79
|
+
# @see #message
|
80
|
+
def message
|
81
|
+
JSON.parse(@env[:body])['error']
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'zerobounce/base_request'
|
4
|
+
|
5
|
+
module Zerobounce
|
6
|
+
|
7
|
+
# Sends the HTTP request.
|
8
|
+
class MockRequest < BaseRequest
|
9
|
+
|
10
|
+
def self.get(path, params, content_type='application/json')
|
11
|
+
response = self._get(Zerobounce::API_ROOT_URL, path, params, content_type)
|
12
|
+
if response.headers[:content_type] == 'application/json'
|
13
|
+
response_body = response.body
|
14
|
+
response_body_json = JSON.parse(response_body)
|
15
|
+
|
16
|
+
raise (response_body_json['error']) if response_body_json.key?('error')
|
17
|
+
raise (response_body_json['errors'][0]['error']) \
|
18
|
+
if response_body_json.key?('errors') and \
|
19
|
+
response_body_json['errors'].length > 0
|
20
|
+
|
21
|
+
return response_body_json
|
22
|
+
else
|
23
|
+
return response
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.bulk_get(path, params, content_type='application/json')
|
28
|
+
response = self._get(Zerobounce::BULK_API_ROOT_URL, path, params, content_type)
|
29
|
+
if response.headers[:content_type] == 'application/json'
|
30
|
+
response_body = response.body
|
31
|
+
response_body_json = JSON.parse(response_body)
|
32
|
+
|
33
|
+
raise (response_body_json['error']) if response_body_json.key?('error')
|
34
|
+
raise (response_body_json['errors'][0]['error']) \
|
35
|
+
if response_body_json.key?('errors') and \
|
36
|
+
response_body_json['errors'].length > 0
|
37
|
+
|
38
|
+
return response_body_json
|
39
|
+
else
|
40
|
+
return response.body
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.bulk_post(path, params, content_type='application/json', filepath=nil)
|
45
|
+
response = self._post(Zerobounce::BULK_API_ROOT_URL, path, params, \
|
46
|
+
content_type, filepath)
|
47
|
+
if response.headers[:content_type] == 'application/json'
|
48
|
+
response_body = response.body
|
49
|
+
response_body_json = JSON.parse(response_body)
|
50
|
+
|
51
|
+
raise (response_body_json['error']) if response_body_json.key?('error')
|
52
|
+
raise (response_body_json['errors'][0]['error']) \
|
53
|
+
if response_body_json.key?('errors') and \
|
54
|
+
response_body_json['errors'].length > 0
|
55
|
+
|
56
|
+
return response_body_json
|
57
|
+
end
|
58
|
+
return response.body
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'zerobounce/base_request'
|
4
|
+
|
5
|
+
module Zerobounce
|
6
|
+
|
7
|
+
# Sends the HTTP request.
|
8
|
+
class Request < BaseRequest
|
9
|
+
|
10
|
+
def self.get(path, params, content_type='application/json')
|
11
|
+
response = self._get(Zerobounce::API_ROOT_URL, path, params, content_type)
|
12
|
+
if response.headers[:content_type] == 'application/json'
|
13
|
+
response_body = response.body
|
14
|
+
response_body_json = JSON.parse(response_body)
|
15
|
+
|
16
|
+
raise (response_body_json['error']) if response_body_json.key?('error')
|
17
|
+
raise (response_body_json['errors'][0]['error']) \
|
18
|
+
if response_body_json.key?('errors') and \
|
19
|
+
response_body_json['errors'].length > 0
|
20
|
+
|
21
|
+
return response_body_json
|
22
|
+
else
|
23
|
+
return response
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.bulk_get(path, params, content_type='application/json')
|
28
|
+
response = self._get(Zerobounce::BULK_API_ROOT_URL, path, params, content_type)
|
29
|
+
if response.headers[:content_type] == 'application/json'
|
30
|
+
response_body = response.body
|
31
|
+
response_body_json = JSON.parse(response_body)
|
32
|
+
|
33
|
+
raise (response_body_json['error']) if response_body_json.key?('error')
|
34
|
+
raise (response_body_json['errors'][0]['error']) \
|
35
|
+
if response_body_json.key?('errors') and \
|
36
|
+
response_body_json['errors'].length > 0
|
37
|
+
|
38
|
+
return response_body_json
|
39
|
+
else
|
40
|
+
return response.body
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.bulk_post(path, params, content_type='application/json', filepath=nil)
|
45
|
+
response = self._post(Zerobounce::BULK_API_ROOT_URL, path, params, \
|
46
|
+
content_type, filepath)
|
47
|
+
if response.headers[:content_type] == 'application/json'
|
48
|
+
response_body = response.body
|
49
|
+
response_body_json = JSON.parse(response_body)
|
50
|
+
|
51
|
+
raise (response_body_json['error']) if response_body_json.key?('error')
|
52
|
+
raise (response_body_json['errors'][0]['error']) \
|
53
|
+
if response_body_json.key?('errors') and \
|
54
|
+
response_body_json['errors'].length > 0
|
55
|
+
|
56
|
+
return response_body_json
|
57
|
+
end
|
58
|
+
return response.body
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|