emailhunter 1.0.0 → 2.0.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 +4 -4
- data/Gemfile +2 -0
- data/README.md +276 -62
- data/Rakefile +2 -0
- data/bin/console +1 -0
- data/emailhunter.gemspec +21 -7
- data/lib/email_hunter/account.rb +16 -7
- data/lib/email_hunter/api.rb +103 -11
- data/lib/email_hunter/campaigns.rb +139 -0
- data/lib/email_hunter/combined_enrichment.rb +54 -0
- data/lib/email_hunter/company.rb +61 -0
- data/lib/email_hunter/company_enrichment.rb +61 -0
- data/lib/email_hunter/count.rb +17 -9
- data/lib/email_hunter/discover.rb +80 -0
- data/lib/email_hunter/exist.rb +14 -8
- data/lib/email_hunter/finder.rb +19 -5
- data/lib/email_hunter/lead_enrichment.rb +69 -0
- data/lib/email_hunter/leads.rb +129 -0
- data/lib/email_hunter/people.rb +61 -0
- data/lib/email_hunter/search.rb +24 -10
- data/lib/email_hunter/verify.rb +15 -10
- data/lib/email_hunter/version.rb +1 -1
- data/lib/emailhunter.rb +2 -0
- metadata +20 -9
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'ostruct'
|
|
6
|
+
|
|
7
|
+
module EmailHunter
|
|
8
|
+
class Leads
|
|
9
|
+
API_URL = 'https://api.hunter.io/v2/leads'
|
|
10
|
+
|
|
11
|
+
attr_reader :key, :params, :action, :lead_id, :data
|
|
12
|
+
|
|
13
|
+
def initialize(key, action: :list, lead_id: nil, data: nil, params: {})
|
|
14
|
+
@key = key
|
|
15
|
+
@action = action
|
|
16
|
+
@lead_id = lead_id
|
|
17
|
+
@data = data
|
|
18
|
+
@params = params
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def hunt
|
|
22
|
+
case action
|
|
23
|
+
when :list
|
|
24
|
+
list_leads
|
|
25
|
+
when :create
|
|
26
|
+
create_lead
|
|
27
|
+
when :update
|
|
28
|
+
update_lead
|
|
29
|
+
when :delete
|
|
30
|
+
delete_lead
|
|
31
|
+
else
|
|
32
|
+
raise ArgumentError, "Unknown action: #{action}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def list_leads
|
|
39
|
+
response_data = fetch_leads_data
|
|
40
|
+
return nil if response_data.empty?
|
|
41
|
+
|
|
42
|
+
# Convert nested data structure to OpenStruct
|
|
43
|
+
result = OpenStruct.new(
|
|
44
|
+
data: OpenStruct.new(response_data[:data] || {}),
|
|
45
|
+
meta: OpenStruct.new(response_data[:meta] || {})
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Convert leads array to OpenStruct objects
|
|
49
|
+
result.data.leads = result.data.leads.map { |lead| OpenStruct.new(lead) } if result.data.leads.is_a?(Array)
|
|
50
|
+
|
|
51
|
+
result
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def create_lead
|
|
55
|
+
response_data = post_lead_data
|
|
56
|
+
return nil if response_data.empty?
|
|
57
|
+
|
|
58
|
+
OpenStruct.new(response_data)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def update_lead
|
|
62
|
+
response_data = put_lead_data
|
|
63
|
+
return nil if response_data.empty?
|
|
64
|
+
|
|
65
|
+
OpenStruct.new(response_data)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def delete_lead
|
|
69
|
+
response = delete_lead_data
|
|
70
|
+
response.success?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def fetch_leads_data
|
|
74
|
+
@fetch_leads_data ||= begin
|
|
75
|
+
connection = Faraday.new
|
|
76
|
+
request_params = {
|
|
77
|
+
api_key: key,
|
|
78
|
+
limit: params.fetch(:limit, 20),
|
|
79
|
+
offset: params.fetch(:offset, 0)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Add optional filters
|
|
83
|
+
request_params[:leads_list_id] = params[:leads_list_id] if params[:leads_list_id]
|
|
84
|
+
|
|
85
|
+
response = connection.get(API_URL, request_params)
|
|
86
|
+
|
|
87
|
+
return {} unless response.success?
|
|
88
|
+
|
|
89
|
+
JSON.parse(response.body, symbolize_names: true)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def post_lead_data
|
|
94
|
+
connection = Faraday.new
|
|
95
|
+
request_data = data.merge(api_key: key)
|
|
96
|
+
|
|
97
|
+
response = connection.post(API_URL) do |req|
|
|
98
|
+
req.headers['Content-Type'] = 'application/json'
|
|
99
|
+
req.body = request_data.to_json
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
return {} unless response.success?
|
|
103
|
+
|
|
104
|
+
JSON.parse(response.body, symbolize_names: true)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def put_lead_data
|
|
108
|
+
connection = Faraday.new
|
|
109
|
+
url = "#{API_URL}/#{lead_id}"
|
|
110
|
+
request_data = data.merge(api_key: key)
|
|
111
|
+
|
|
112
|
+
response = connection.put(url) do |req|
|
|
113
|
+
req.headers['Content-Type'] = 'application/json'
|
|
114
|
+
req.body = request_data.to_json
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
return {} unless response.success?
|
|
118
|
+
|
|
119
|
+
JSON.parse(response.body, symbolize_names: true)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def delete_lead_data
|
|
123
|
+
connection = Faraday.new
|
|
124
|
+
url = "#{API_URL}/#{lead_id}"
|
|
125
|
+
|
|
126
|
+
connection.delete(url, api_key: key)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'ostruct'
|
|
6
|
+
|
|
7
|
+
module EmailHunter
|
|
8
|
+
class People
|
|
9
|
+
API_URL = 'https://api.hunter.io/v2/people/find'
|
|
10
|
+
|
|
11
|
+
attr_reader :email, :key
|
|
12
|
+
|
|
13
|
+
def initialize(email, key)
|
|
14
|
+
@email = email
|
|
15
|
+
@key = key
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def hunt
|
|
19
|
+
response_data = fetch_people_data
|
|
20
|
+
return nil if response_data.empty?
|
|
21
|
+
|
|
22
|
+
# Convert nested data structure to a Struct
|
|
23
|
+
data = response_data[:data]
|
|
24
|
+
meta = response_data[:meta]
|
|
25
|
+
|
|
26
|
+
result = OpenStruct.new(
|
|
27
|
+
data: OpenStruct.new(data),
|
|
28
|
+
meta: OpenStruct.new(meta)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Recursively convert nested hashes to OpenStructs for deeper access
|
|
32
|
+
convert_hash_to_struct(result.data, data)
|
|
33
|
+
|
|
34
|
+
result
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def fetch_people_data
|
|
40
|
+
@fetch_people_data ||= begin
|
|
41
|
+
connection = Faraday.new
|
|
42
|
+
response = connection.get(API_URL, email: email, api_key: key)
|
|
43
|
+
|
|
44
|
+
return {} unless response.success?
|
|
45
|
+
|
|
46
|
+
JSON.parse(response.body, symbolize_names: true)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def convert_hash_to_struct(struct, hash)
|
|
51
|
+
hash.each do |key, value|
|
|
52
|
+
if value.is_a?(Hash)
|
|
53
|
+
struct[key] = OpenStruct.new(value)
|
|
54
|
+
convert_hash_to_struct(struct[key], value)
|
|
55
|
+
elsif value.is_a?(Array) && value.first.is_a?(Hash)
|
|
56
|
+
struct[key] = value.map { |item| OpenStruct.new(item) }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/lib/email_hunter/search.rb
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
require 'faraday'
|
|
4
4
|
require 'json'
|
|
5
5
|
|
|
6
|
-
API_SEARCH_URL = 'https://api.hunter.io/v2/domain-search?'
|
|
7
|
-
|
|
8
6
|
module EmailHunter
|
|
9
7
|
class Search
|
|
10
|
-
|
|
8
|
+
API_URL = 'https://api.hunter.io/v2/domain-search'
|
|
9
|
+
|
|
10
|
+
attr_reader :domain, :key, :params
|
|
11
11
|
|
|
12
12
|
def initialize(domain, key, params = {})
|
|
13
13
|
@domain = domain
|
|
@@ -16,24 +16,38 @@ module EmailHunter
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def hunt
|
|
19
|
-
|
|
19
|
+
response_data = fetch_search_data
|
|
20
|
+
return nil if response_data.empty?
|
|
21
|
+
|
|
22
|
+
Struct.new(*response_data.keys).new(*response_data.values)
|
|
20
23
|
end
|
|
21
24
|
|
|
25
|
+
private
|
|
26
|
+
|
|
22
27
|
def limit
|
|
23
|
-
params
|
|
28
|
+
params.fetch(:limit, 10).to_i
|
|
24
29
|
end
|
|
25
30
|
|
|
26
31
|
def offset
|
|
27
|
-
params
|
|
32
|
+
params.fetch(:offset, 0).to_i
|
|
28
33
|
end
|
|
29
34
|
|
|
30
|
-
def
|
|
31
|
-
@
|
|
32
|
-
|
|
35
|
+
def fetch_search_data
|
|
36
|
+
@fetch_search_data ||= begin
|
|
37
|
+
connection = Faraday.new
|
|
38
|
+
request_params = {
|
|
39
|
+
domain: domain,
|
|
40
|
+
api_key: key,
|
|
41
|
+
offset: offset,
|
|
42
|
+
limit: limit
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
request_params[:type] = params[:type] if params[:type]
|
|
46
|
+
response = connection.get(API_URL, request_params)
|
|
33
47
|
|
|
34
48
|
return {} unless response.success?
|
|
35
49
|
|
|
36
|
-
JSON.parse(response.body,
|
|
50
|
+
JSON.parse(response.body, symbolize_names: true)
|
|
37
51
|
end
|
|
38
52
|
end
|
|
39
53
|
end
|
data/lib/email_hunter/verify.rb
CHANGED
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
require 'faraday'
|
|
4
4
|
require 'json'
|
|
5
5
|
|
|
6
|
-
API_VERIFY_URL = 'https://api.hunter.io/v2/email-verifier?'
|
|
7
|
-
|
|
8
6
|
module EmailHunter
|
|
9
7
|
class Verify
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
API_URL = 'https://api.hunter.io/v2/email-verifier'
|
|
9
|
+
|
|
10
|
+
attr_reader :email, :key
|
|
12
11
|
|
|
13
12
|
def initialize(email, key)
|
|
14
13
|
@email = email
|
|
@@ -16,16 +15,22 @@ module EmailHunter
|
|
|
16
15
|
end
|
|
17
16
|
|
|
18
17
|
def hunt
|
|
19
|
-
|
|
18
|
+
response_data = fetch_verify_data
|
|
19
|
+
return nil if response_data.empty?
|
|
20
|
+
|
|
21
|
+
Struct.new(*response_data.keys).new(*response_data.values)
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def fetch_verify_data
|
|
27
|
+
@fetch_verify_data ||= begin
|
|
28
|
+
connection = Faraday.new
|
|
29
|
+
response = connection.get(API_URL, email: email, api_key: key)
|
|
25
30
|
|
|
26
|
-
return
|
|
31
|
+
return {} unless response.success?
|
|
27
32
|
|
|
28
|
-
JSON.parse(response.body,
|
|
33
|
+
JSON.parse(response.body, symbolize_names: true)
|
|
29
34
|
end
|
|
30
35
|
end
|
|
31
36
|
end
|
data/lib/email_hunter/version.rb
CHANGED
data/lib/emailhunter.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: emailhunter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Davide Santangelo
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2025-11-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -108,8 +108,10 @@ dependencies:
|
|
|
108
108
|
- - ">="
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0'
|
|
111
|
-
description:
|
|
112
|
-
|
|
111
|
+
description: |
|
|
112
|
+
EmailHunter is a minimalistic Ruby wrapper for the Hunter.io API.
|
|
113
|
+
It provides a straightforward interface to integrate Hunter.io's
|
|
114
|
+
email discovery capabilities into your sales and marketing workflows.
|
|
113
115
|
email:
|
|
114
116
|
- davide.santangelo@gmail.com
|
|
115
117
|
executables: []
|
|
@@ -130,17 +132,26 @@ files:
|
|
|
130
132
|
- lib/email_hunter.rb
|
|
131
133
|
- lib/email_hunter/account.rb
|
|
132
134
|
- lib/email_hunter/api.rb
|
|
135
|
+
- lib/email_hunter/campaigns.rb
|
|
136
|
+
- lib/email_hunter/combined_enrichment.rb
|
|
137
|
+
- lib/email_hunter/company.rb
|
|
138
|
+
- lib/email_hunter/company_enrichment.rb
|
|
133
139
|
- lib/email_hunter/count.rb
|
|
140
|
+
- lib/email_hunter/discover.rb
|
|
134
141
|
- lib/email_hunter/exist.rb
|
|
135
142
|
- lib/email_hunter/finder.rb
|
|
143
|
+
- lib/email_hunter/lead_enrichment.rb
|
|
144
|
+
- lib/email_hunter/leads.rb
|
|
145
|
+
- lib/email_hunter/people.rb
|
|
136
146
|
- lib/email_hunter/search.rb
|
|
137
147
|
- lib/email_hunter/verify.rb
|
|
138
148
|
- lib/email_hunter/version.rb
|
|
139
149
|
- lib/emailhunter.rb
|
|
140
|
-
homepage:
|
|
150
|
+
homepage: https://github.com/davidesantangelo/emailhunter
|
|
141
151
|
licenses:
|
|
142
152
|
- MIT
|
|
143
|
-
metadata:
|
|
153
|
+
metadata:
|
|
154
|
+
source_code_uri: https://github.com/davidesantangelo/emailhunter
|
|
144
155
|
post_install_message:
|
|
145
156
|
rdoc_options: []
|
|
146
157
|
require_paths:
|
|
@@ -149,15 +160,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
149
160
|
requirements:
|
|
150
161
|
- - ">="
|
|
151
162
|
- !ruby/object:Gem::Version
|
|
152
|
-
version:
|
|
163
|
+
version: 3.0.0
|
|
153
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
165
|
requirements:
|
|
155
166
|
- - ">="
|
|
156
167
|
- !ruby/object:Gem::Version
|
|
157
168
|
version: '0'
|
|
158
169
|
requirements: []
|
|
159
|
-
rubygems_version: 3.
|
|
170
|
+
rubygems_version: 3.3.26
|
|
160
171
|
signing_key:
|
|
161
172
|
specification_version: 4
|
|
162
|
-
summary: A tiny
|
|
173
|
+
summary: A tiny Ruby wrapper around the Hunter.io API
|
|
163
174
|
test_files: []
|