zerobounce-sdk 2.1.8 → 2.2.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/CHANGELOG.md +146 -19
- data/README.md +472 -410
- data/lib/zerobounce/api_urls.rb +9 -0
- data/lib/zerobounce/base_request.rb +208 -8
- data/lib/zerobounce/client.rb +22 -0
- data/lib/zerobounce/configuration.rb +24 -3
- data/lib/zerobounce/error.rb +18 -0
- data/lib/zerobounce/get_file_helper.rb +3 -7
- data/lib/zerobounce/mock_request.rb +31 -12
- data/lib/zerobounce/priority3.rb +331 -0
- data/lib/zerobounce/request.rb +77 -38
- data/lib/zerobounce/response_error.rb +117 -0
- data/lib/zerobounce/validate_sub_status.rb +1 -0
- data/lib/zerobounce/version.rb +1 -1
- data/lib/zerobounce/warmup.rb +467 -0
- data/lib/zerobounce.rb +101 -14
- metadata +8 -33
- data/.dockerignore +0 -17
- data/.env.example +0 -3
- data/.github/auto_assign.yml +0 -5
- data/.github/dependabot.yml +0 -35
- data/.github/workflows/auto_assign_ci.yaml +0 -21
- data/.github/workflows/codeql.yml +0 -105
- data/.github/workflows/publish.yml +0 -131
- data/.github/workflows/sdk_ci.yml +0 -29
- data/.gitignore +0 -70
- data/.rspec +0 -2
- data/.ruby-version +0 -1
- data/CODE_OF_CONDUCT.md +0 -69
- data/CONTRIBUTING.md +0 -112
- data/Dockerfile +0 -17
- data/Gemfile +0 -13
- data/Gemfile.lock +0 -135
- data/Rakefile +0 -26
- data/SECURITY.md +0 -21
- data/bin/bundle +0 -105
- data/bin/console +0 -7
- data/bin/setup +0 -6
- data/data/zerobounce-ai-scoring.csv +0 -31
- data/data/zerobounce-batch-validation.csv +0 -31
- data/documentation.md +0 -530
- data/files/scoring.csv +0 -1
- data/files/validation.csv +0 -1
- data/files/zerobounce-ai-scoring.csv +0 -31
- data/files/zerobounce-batch-validation.csv +0 -31
- data/zerobounce.gemspec +0 -49
data/README.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
# Zerobounce
|
|
3
3
|
Ruby client for Zerobounce.net API. Developed based on [this version](https://github.com/afrase/zerobounce) by Aaron Frase.
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
## Security
|
|
7
|
+
|
|
8
|
+
- Keep API keys on a trusted server. Do not embed them in mobile apps or browser JavaScript that untrusted users can inspect.
|
|
9
|
+
- Custom API base URLs (when supported) must use `https://`. Do not pass end-user-controlled hosts into those settings.
|
|
10
|
+
- Request URLs include `api_key` as a query parameter (ZeroBounce API contract). Do not log full request URLs or enable payload debug logging in production.
|
|
11
|
+
|
|
5
12
|
## Usage
|
|
6
13
|
Add this line to your application's Gemfile:
|
|
7
14
|
```ruby
|
|
@@ -34,6 +41,9 @@ Zerobounce.configure do |config|
|
|
|
34
41
|
# Optional: Set custom API URLs
|
|
35
42
|
config.api_root_url = 'https://api.zerobounce.net/v2'
|
|
36
43
|
config.bulk_api_root_url = 'https://bulkapi.zerobounce.net/v2'
|
|
44
|
+
# Optional: the root the S3 and SFTP/FTP jobs use (the bulk host without
|
|
45
|
+
# /v2). Left unset it is derived from bulk_api_root_url.
|
|
46
|
+
config.bulk_root_url = 'https://bulkapi.zerobounce.net'
|
|
37
47
|
end
|
|
38
48
|
```
|
|
39
49
|
|
|
@@ -69,15 +79,24 @@ Zerobounce.config.api_root_url = 'https://api.zerobounce.net/v2'
|
|
|
69
79
|
Zerobounce.config.bulk_api_root_url = 'https://bulkapi.zerobounce.net/v2'
|
|
70
80
|
```
|
|
71
81
|
|
|
72
|
-
#### Method 3: Using
|
|
73
|
-
|
|
82
|
+
#### Method 3: Using a `.env` file
|
|
83
|
+
The gem reads the `ZEROBOUNCE_*` environment variables, but it does not load a `.env` file itself (it did up to 2.1.8). To keep the settings in one, add the [dotenv](https://github.com/bkeepers/dotenv) gem to your Gemfile and load it before the gem is first configured:
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
require 'dotenv/load'
|
|
87
|
+
require 'zerobounce'
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The `.env` file:
|
|
74
91
|
```bash
|
|
75
92
|
ZEROBOUNCE_API_KEY=your_api_key_here
|
|
76
93
|
ZEROBOUNCE_API_URL=https://api.zerobounce.net/v2
|
|
77
94
|
ZEROBOUNCE_BULK_API_URL=https://bulkapi.zerobounce.net/v2
|
|
95
|
+
# Optional. Only needed to point the S3 and SFTP/FTP jobs somewhere of their own.
|
|
96
|
+
ZEROBOUNCE_BULK_ROOT_URL=https://bulkapi.zerobounce.net
|
|
78
97
|
```
|
|
79
98
|
|
|
80
|
-
|
|
99
|
+
With the variables loaded, no further configuration is needed in your code.
|
|
81
100
|
|
|
82
101
|
#### Method 4: System environment variables
|
|
83
102
|
Set environment variables in your system:
|
|
@@ -85,6 +104,8 @@ Set environment variables in your system:
|
|
|
85
104
|
export ZEROBOUNCE_API_KEY=your_api_key_here
|
|
86
105
|
export ZEROBOUNCE_API_URL=https://api.zerobounce.net/v2
|
|
87
106
|
export ZEROBOUNCE_BULK_API_URL=https://bulkapi.zerobounce.net/v2
|
|
107
|
+
# Optional. Only needed to point the S3 and SFTP/FTP jobs somewhere of their own.
|
|
108
|
+
export ZEROBOUNCE_BULK_ROOT_URL=https://bulkapi.zerobounce.net
|
|
88
109
|
```
|
|
89
110
|
|
|
90
111
|
|
|
@@ -94,6 +115,9 @@ export ZEROBOUNCE_BULK_API_URL=https://bulkapi.zerobounce.net/v2
|
|
|
94
115
|
If you don't specify `api_root_url` or `bulk_api_root_url`, the gem will use the following defaults:
|
|
95
116
|
- **Main API**: `https://api.zerobounce.net/v2`
|
|
96
117
|
- **Bulk API**: `https://bulkapi.zerobounce.net/v2`
|
|
118
|
+
- **S3 and SFTP/FTP jobs**: `https://bulkapi.zerobounce.net` — the bulk host *without* `/v2`
|
|
119
|
+
|
|
120
|
+
`bulk_root_url` (`ZEROBOUNCE_BULK_ROOT_URL`) is the one base URL that is derived rather than defaulted: left unset, it is `bulk_api_root_url` with the trailing `/v2` stripped, so pointing `bulk_api_root_url` at a mock server moves the S3 and SFTP/FTP endpoints with it. Set it to send those jobs somewhere on their own.
|
|
97
121
|
|
|
98
122
|
These defaults are defined in the `Zerobounce::ApiUrls` class constants:
|
|
99
123
|
- `Zerobounce::ApiUrls::DEFAULT_URL` - Main API URL (Global)
|
|
@@ -142,62 +166,62 @@ end
|
|
|
142
166
|
#### Environment Variable Priority
|
|
143
167
|
The configuration follows this priority order (highest to lowest):
|
|
144
168
|
1. Explicitly set in code (`config.api_root_url = '...'`)
|
|
145
|
-
2. Environment variables (`ZEROBOUNCE_API_URL`, `ZEROBOUNCE_BULK_API_URL`)
|
|
146
|
-
3. Default constants (`ApiUrls::DEFAULT_URL`, `ApiUrls::BULK_DEFAULT_URL`)
|
|
169
|
+
2. Environment variables (`ZEROBOUNCE_API_URL`, `ZEROBOUNCE_BULK_API_URL`, `ZEROBOUNCE_BULK_ROOT_URL`)
|
|
170
|
+
3. Default constants (`ApiUrls::DEFAULT_URL`, `ApiUrls::BULK_DEFAULT_URL`); `bulk_root_url` falls back to `bulk_api_root_url` without `/v2`
|
|
147
171
|
|
|
148
172
|
Credits
|
|
149
173
|
```ruby
|
|
150
174
|
Zerobounce.credits
|
|
151
|
-
=> 79
|
|
175
|
+
# => 79 (-1 for an invalid key)
|
|
152
176
|
```
|
|
153
177
|
|
|
154
178
|
Activity
|
|
155
179
|
```ruby
|
|
156
180
|
Zerobounce.activity('ss@gmail.com')
|
|
157
|
-
=> {"found"=>true, "active_in_days"=>"180"}
|
|
181
|
+
# => {"found"=>true, "active_in_days"=>"180"}
|
|
158
182
|
```
|
|
159
183
|
|
|
160
184
|
Usage statistics
|
|
161
185
|
```ruby
|
|
162
186
|
Zerobounce.api_usage(Date.today, Date.today)
|
|
163
|
-
=>
|
|
164
|
-
{"total"=>0,
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
187
|
+
# =>
|
|
188
|
+
# {"total"=>0,
|
|
189
|
+
# "status_valid"=>0,
|
|
190
|
+
# "status_invalid"=>0,
|
|
191
|
+
# "status_catch_all"=>0,
|
|
192
|
+
# "status_do_not_mail"=>0,
|
|
193
|
+
# "status_spamtrap"=>0,
|
|
194
|
+
# "status_unknown"=>0,
|
|
195
|
+
# "sub_status_toxic"=>0,
|
|
196
|
+
# "sub_status_disposable"=>0,
|
|
197
|
+
# "sub_status_role_based"=>0,
|
|
198
|
+
# "sub_status_possible_trap"=>0,
|
|
199
|
+
# "sub_status_global_suppression"=>0,
|
|
200
|
+
# "sub_status_timeout_exceeded"=>0,
|
|
201
|
+
# "sub_status_mail_server_temporary_error"=>0,
|
|
202
|
+
# "sub_status_mail_server_did_not_respond"=>0,
|
|
203
|
+
# "sub_status_greylisted"=>0,
|
|
204
|
+
# "sub_status_antispam_system"=>0,
|
|
205
|
+
# "sub_status_does_not_accept_mail"=>0,
|
|
206
|
+
# "sub_status_exception_occurred"=>0,
|
|
207
|
+
# "sub_status_failed_syntax_check"=>0,
|
|
208
|
+
# "sub_status_mailbox_not_found"=>0,
|
|
209
|
+
# "sub_status_unroutable_ip_address"=>0,
|
|
210
|
+
# "sub_status_possible_typo"=>0,
|
|
211
|
+
# "sub_status_no_dns_entries"=>0,
|
|
212
|
+
# "sub_status_role_based_catch_all"=>0,
|
|
213
|
+
# "sub_status_mailbox_quota_exceeded"=>0,
|
|
214
|
+
# "sub_status_forcible_disconnect"=>0,
|
|
215
|
+
# "sub_status_failed_smtp_connection"=>0,
|
|
216
|
+
# "sub_status_accept_all"=>0,
|
|
217
|
+
# "sub_status_mx_forward"=>0,
|
|
218
|
+
# "sub_status_alternate"=>0,
|
|
219
|
+
# "sub_status_allowed"=>0,
|
|
220
|
+
# "sub_status_blocked"=>0,
|
|
221
|
+
# "sub_status_gold"=>0,
|
|
222
|
+
# "sub_status_role_based_accept_all"=>0,
|
|
223
|
+
# "start_date"=>"4/28/2023",
|
|
224
|
+
# "end_date"=>"4/28/2023"}
|
|
201
225
|
```
|
|
202
226
|
|
|
203
227
|
### Email Validation
|
|
@@ -206,159 +230,164 @@ Validate single eMail
|
|
|
206
230
|
```ruby
|
|
207
231
|
Zerobounce.validate('valid@example.com')
|
|
208
232
|
# Zerobounce.validate('valid@example.com', '192.168.0.1') # optional IP address
|
|
209
|
-
=>
|
|
210
|
-
{"address"=>"valid@example.com",
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
233
|
+
# =>
|
|
234
|
+
# {"address"=>"valid@example.com",
|
|
235
|
+
# "status"=>"valid",
|
|
236
|
+
# "sub_status"=>"",
|
|
237
|
+
# "free_email"=>false,
|
|
238
|
+
# "did_you_mean"=>nil,
|
|
239
|
+
# "account"=>nil,
|
|
240
|
+
# "domain"=>nil,
|
|
241
|
+
# "domain_age_days"=>"9692",
|
|
242
|
+
# "smtp_provider"=>"example",
|
|
243
|
+
# "mx_found"=>"true",
|
|
244
|
+
# "mx_record"=>"mx.example.com",
|
|
245
|
+
# "firstname"=>"zero",
|
|
246
|
+
# "lastname"=>"bounce",
|
|
247
|
+
# "gender"=>"male",
|
|
248
|
+
# "country"=>nil,
|
|
249
|
+
# "region"=>nil,
|
|
250
|
+
# "city"=>nil,
|
|
251
|
+
# "zipcode"=>nil,
|
|
252
|
+
# "processed_at"=>"2023-04-28 15:18:45.631"}
|
|
229
253
|
```
|
|
230
254
|
|
|
231
255
|
Validate batch
|
|
256
|
+
|
|
257
|
+
`validate_batch` returns the whole response: a Hash with `email_batch` (one result per address) and `errors`. Up to 2.1.8 it returned only the `email_batch` Array and raised on any error; now a problem with one address is listed in `errors` and does not raise. An account-level error (reported for the address `all`, such as an invalid key or no credits left) still raises.
|
|
258
|
+
|
|
232
259
|
```ruby
|
|
233
|
-
emails
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
"
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
# ip_addresses
|
|
243
|
-
=>
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
[
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
"
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
"
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
"
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
"
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
"
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
260
|
+
emails = ["disposable@example.com",
|
|
261
|
+
"invalid@example.com",
|
|
262
|
+
"valid@example.com",
|
|
263
|
+
"toxic@example.com",
|
|
264
|
+
"donotmail@example.com",
|
|
265
|
+
"spamtrap@example.com"]
|
|
266
|
+
ip_addresses = ["192.168.0.1"] * emails.length
|
|
267
|
+
|
|
268
|
+
result = Zerobounce.validate_batch(emails)
|
|
269
|
+
# result = Zerobounce.validate_batch(emails, ip_addresses) # optional ip_addresses parameter
|
|
270
|
+
# => {"email_batch"=>[...], "errors"=>[]}
|
|
271
|
+
|
|
272
|
+
result['errors']
|
|
273
|
+
# => [] e.g. [{"email_address"=>"bad@", "error"=>"Invalid email address"}]
|
|
274
|
+
|
|
275
|
+
result['email_batch']
|
|
276
|
+
# =>
|
|
277
|
+
# [{"address"=>"disposable@example.com",
|
|
278
|
+
# "status"=>"do_not_mail",
|
|
279
|
+
# "sub_status"=>"disposable",
|
|
280
|
+
# "free_email"=>false,
|
|
281
|
+
# "did_you_mean"=>nil,
|
|
282
|
+
# "account"=>nil,
|
|
283
|
+
# "domain"=>nil,
|
|
284
|
+
# "domain_age_days"=>"9692",
|
|
285
|
+
# "smtp_provider"=>"example",
|
|
286
|
+
# "mx_found"=>"true",
|
|
287
|
+
# "mx_record"=>"mx.example.com",
|
|
288
|
+
# "firstname"=>"zero",
|
|
289
|
+
# "lastname"=>"bounce",
|
|
290
|
+
# "gender"=>"male",
|
|
291
|
+
# "country"=>nil,
|
|
292
|
+
# "region"=>nil,
|
|
293
|
+
# "city"=>nil,
|
|
294
|
+
# "zipcode"=>nil,
|
|
295
|
+
# "processed_at"=>"2023-04-28 15:21:44.340"},
|
|
296
|
+
# {"address"=>"invalid@example.com",
|
|
297
|
+
# "status"=>"invalid",
|
|
298
|
+
# "sub_status"=>"mailbox_not_found",
|
|
299
|
+
# "free_email"=>false,
|
|
300
|
+
# "did_you_mean"=>nil,
|
|
301
|
+
# "account"=>nil,
|
|
302
|
+
# "domain"=>nil,
|
|
303
|
+
# "domain_age_days"=>"9692",
|
|
304
|
+
# "smtp_provider"=>"example",
|
|
305
|
+
# "mx_found"=>"true",
|
|
306
|
+
# "mx_record"=>"mx.example.com",
|
|
307
|
+
# "firstname"=>"zero",
|
|
308
|
+
# "lastname"=>"bounce",
|
|
309
|
+
# "gender"=>"male",
|
|
310
|
+
# "country"=>nil,
|
|
311
|
+
# "region"=>nil,
|
|
312
|
+
# "city"=>nil,
|
|
313
|
+
# "zipcode"=>nil,
|
|
314
|
+
# "processed_at"=>"2023-04-28 15:21:44.340"},
|
|
315
|
+
# {"address"=>"valid@example.com",
|
|
316
|
+
# "status"=>"valid",
|
|
317
|
+
# "sub_status"=>"",
|
|
318
|
+
# "free_email"=>false,
|
|
319
|
+
# "did_you_mean"=>nil,
|
|
320
|
+
# "account"=>nil,
|
|
321
|
+
# "domain"=>nil,
|
|
322
|
+
# "domain_age_days"=>"9692",
|
|
323
|
+
# "smtp_provider"=>"example",
|
|
324
|
+
# "mx_found"=>"true",
|
|
325
|
+
# "mx_record"=>"mx.example.com",
|
|
326
|
+
# "firstname"=>"zero",
|
|
327
|
+
# "lastname"=>"bounce",
|
|
328
|
+
# "gender"=>"male",
|
|
329
|
+
# "country"=>nil,
|
|
330
|
+
# "region"=>nil,
|
|
331
|
+
# "city"=>nil,
|
|
332
|
+
# "zipcode"=>nil,
|
|
333
|
+
# "processed_at"=>"2023-04-28 15:21:44.340"},
|
|
334
|
+
# {"address"=>"toxic@example.com",
|
|
335
|
+
# "status"=>"do_not_mail",
|
|
336
|
+
# "sub_status"=>"toxic",
|
|
337
|
+
# "free_email"=>false,
|
|
338
|
+
# "did_you_mean"=>nil,
|
|
339
|
+
# "account"=>nil,
|
|
340
|
+
# "domain"=>nil,
|
|
341
|
+
# "domain_age_days"=>"9692",
|
|
342
|
+
# "smtp_provider"=>"example",
|
|
343
|
+
# "mx_found"=>"true",
|
|
344
|
+
# "mx_record"=>"mx.example.com",
|
|
345
|
+
# "firstname"=>"zero",
|
|
346
|
+
# "lastname"=>"bounce",
|
|
347
|
+
# "gender"=>"male",
|
|
348
|
+
# "country"=>nil,
|
|
349
|
+
# "region"=>nil,
|
|
350
|
+
# "city"=>nil,
|
|
351
|
+
# "zipcode"=>nil,
|
|
352
|
+
# "processed_at"=>"2023-04-28 15:21:44.340"},
|
|
353
|
+
# {"address"=>"donotmail@example.com",
|
|
354
|
+
# "status"=>"do_not_mail",
|
|
355
|
+
# "sub_status"=>"role_based",
|
|
356
|
+
# "free_email"=>false,
|
|
357
|
+
# "did_you_mean"=>nil,
|
|
358
|
+
# "account"=>nil,
|
|
359
|
+
# "domain"=>nil,
|
|
360
|
+
# "domain_age_days"=>"9692",
|
|
361
|
+
# "smtp_provider"=>"example",
|
|
362
|
+
# "mx_found"=>"true",
|
|
363
|
+
# "mx_record"=>"mx.example.com",
|
|
364
|
+
# "firstname"=>"zero",
|
|
365
|
+
# "lastname"=>"bounce",
|
|
366
|
+
# "gender"=>"male",
|
|
367
|
+
# "country"=>nil,
|
|
368
|
+
# "region"=>nil,
|
|
369
|
+
# "city"=>nil,
|
|
370
|
+
# "zipcode"=>nil,
|
|
371
|
+
# "processed_at"=>"2023-04-28 15:21:44.340"},
|
|
372
|
+
# {"address"=>"spamtrap@example.com",
|
|
373
|
+
# "status"=>"spamtrap",
|
|
374
|
+
# "sub_status"=>"",
|
|
375
|
+
# "free_email"=>false,
|
|
376
|
+
# "did_you_mean"=>nil,
|
|
377
|
+
# "account"=>nil,
|
|
378
|
+
# "domain"=>nil,
|
|
379
|
+
# "domain_age_days"=>"9692",
|
|
380
|
+
# "smtp_provider"=>"example",
|
|
381
|
+
# "mx_found"=>"true",
|
|
382
|
+
# "mx_record"=>"mx.example.com",
|
|
383
|
+
# "firstname"=>"zero",
|
|
384
|
+
# "lastname"=>"bounce",
|
|
385
|
+
# "gender"=>"male",
|
|
386
|
+
# "country"=>nil,
|
|
387
|
+
# "region"=>nil,
|
|
388
|
+
# "city"=>nil,
|
|
389
|
+
# "zipcode"=>nil,
|
|
390
|
+
# "processed_at"=>"2023-04-28 15:21:44.340"}]
|
|
362
391
|
```
|
|
363
392
|
|
|
364
393
|
#### Batch File Validation
|
|
@@ -366,24 +395,24 @@ Zerobounce.validate_batch(emails)
|
|
|
366
395
|
Send file
|
|
367
396
|
```ruby
|
|
368
397
|
# sample file can be found in the files folder of this repository
|
|
369
|
-
|
|
370
|
-
=> "/home/zb/wrappers/ruby-test/files/validation.csv"
|
|
371
|
-
|
|
372
|
-
=>
|
|
373
|
-
{"success"=>true,
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
398
|
+
validate_file_path = File.join(Dir.pwd, 'files', 'validation.csv')
|
|
399
|
+
# => "/home/zb/wrappers/ruby-test/files/validation.csv"
|
|
400
|
+
Zerobounce.validate_file_send(validate_file_path)
|
|
401
|
+
# =>
|
|
402
|
+
# {"success"=>true,
|
|
403
|
+
# "message"=>"File Accepted",
|
|
404
|
+
# "file_name"=>"validation.csv",
|
|
405
|
+
# "file_id"=>"75d854a6-565c-49f9-b4c8-b3344480ec4c"}
|
|
406
|
+
# file_id will be required for next steps
|
|
407
|
+
# optional named parameters:
|
|
408
|
+
# email_address_column: 1,
|
|
409
|
+
# first_name_column: 2,
|
|
410
|
+
# last_name_column: 3,
|
|
411
|
+
# gender_column: 4,
|
|
412
|
+
# has_header_row: true,
|
|
413
|
+
# return_url: nil, # results callback url
|
|
414
|
+
# allow_phase_2: true # optional; validation bulk sendfile only (omit or nil to skip)
|
|
415
|
+
Zerobounce.validate_file_send(validate_file_path, email_address_column: 1, gender_column: 4)
|
|
387
416
|
```
|
|
388
417
|
|
|
389
418
|
Bulk validation uses `https://bulkapi.zerobounce.net/v2`. See [v2 send file](https://www.zerobounce.net/docs/email-validation-api-quickstart/v2-send-file), [v2 file status](https://www.zerobounce.net/docs/email-validation-api-quickstart/v2-file-status), and [v2 get file](https://www.zerobounce.net/docs/email-validation-api-quickstart/v2-get-file).
|
|
@@ -391,26 +420,24 @@ Bulk validation uses `https://bulkapi.zerobounce.net/v2`. See [v2 send file](htt
|
|
|
391
420
|
Check file
|
|
392
421
|
```ruby
|
|
393
422
|
file_id = "75d854a6-565c-49f9-b4c8-b3344480ec4c"
|
|
394
|
-
=> "75d854a6-565c-49f9-b4c8-b3344480ec4c"
|
|
395
423
|
Zerobounce.validate_file_check(file_id)
|
|
396
|
-
=>
|
|
397
|
-
{"success"=>true,
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
424
|
+
# =>
|
|
425
|
+
# {"success"=>true,
|
|
426
|
+
# "file_id"=>"75d854a6-565c-49f9-b4c8-b3344480ec4c",
|
|
427
|
+
# "file_name"=>"validation.csv",
|
|
428
|
+
# "upload_date"=>"2023-04-28T15:25:41Z",
|
|
429
|
+
# "file_status"=>"Greylisted",
|
|
430
|
+
# "complete_percentage"=>"0%",
|
|
431
|
+
# "file_phase_2_status"=>"N/A", # when present (validation bulk v2)
|
|
432
|
+
# "error_reason"=>nil,
|
|
433
|
+
# "return_url"=>nil}
|
|
406
434
|
```
|
|
407
435
|
|
|
408
436
|
Get file
|
|
409
437
|
```ruby
|
|
410
438
|
file_id = "75d854a6-565c-49f9-b4c8-b3344480ec4c"
|
|
411
|
-
=> "75d854a6-565c-49f9-b4c8-b3344480ec4c"
|
|
412
439
|
Zerobounce.validate_file_get(file_id)
|
|
413
|
-
=> "\"email\",\"first\",\"last\",\"gender\",\"ip\",\"ZB Status\",\"ZB Sub Status\",\"ZB Account\",\"ZB Domain\",\"ZB First Name\",\"ZB Last Name\",\"ZB Gender\",\"ZB Free Email\",\"ZB MX Found\",\"ZB MX Record\",\"ZB SMTP Provider\",\"ZB Did You Mean\"\n\"disposable@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"disposable\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"invalid@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"mailbox_not_found\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"valid@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"valid\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"toxic@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"toxic\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"donotmail@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"role_based\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"spamtrap@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"spamtrap\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"abuse@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"abuse\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"unknown@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"mail_server_temporary_error\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"catch_all@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"catch-all\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"antispam_system@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"antispam_system\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"does_not_accept_mail@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"does_not_accept_mail\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"exception_occurred@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"exception_occurred\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"failed_smtp_connection@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"failed_smtp_connection\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"failed_syntax_check@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"failed_syntax_check\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"forcible_disconnect@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"forcible_disconnect\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"global_suppression@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"global_suppression\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"greylisted@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"greylisted\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"leading_period_removed@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"valid\",\"leading_period_removed\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"mail_server_did_not_respond@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"mail_server_did_not_respond\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"mail_server_temporary_error@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"mail_server_temporary_error\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"mailbox_quota_exceeded@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"mailbox_quota_exceeded\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"mailbox_not_found@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"mailbox_not_found\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"no_dns_entries@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"no_dns_entries\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"possible_trap@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"possible_trap\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"possible_typo@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"possible_typo\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"role_based@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"role_based\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"timeout_exceeded@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"timeout_exceeded\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"unroutable_ip_address@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"unroutable_ip_address\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"free_email@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"valid\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"True\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"role_based_catch_all@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"role_based_catch_all\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n"
|
|
440
|
+
# => "\"email\",\"first\",\"last\",\"gender\",\"ip\",\"ZB Status\",\"ZB Sub Status\",\"ZB Account\",\"ZB Domain\",\"ZB First Name\",\"ZB Last Name\",\"ZB Gender\",\"ZB Free Email\",\"ZB MX Found\",\"ZB MX Record\",\"ZB SMTP Provider\",\"ZB Did You Mean\"\n\"disposable@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"disposable\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"invalid@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"mailbox_not_found\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"valid@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"valid\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"toxic@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"toxic\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"donotmail@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"role_based\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"spamtrap@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"spamtrap\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"abuse@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"abuse\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"unknown@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"mail_server_temporary_error\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"catch_all@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"catch-all\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"antispam_system@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"antispam_system\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"does_not_accept_mail@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"does_not_accept_mail\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"exception_occurred@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"exception_occurred\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"failed_smtp_connection@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"failed_smtp_connection\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"failed_syntax_check@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"failed_syntax_check\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"forcible_disconnect@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"forcible_disconnect\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"global_suppression@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"global_suppression\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"greylisted@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"greylisted\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"leading_period_removed@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"valid\",\"leading_period_removed\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"mail_server_did_not_respond@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"mail_server_did_not_respond\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"mail_server_temporary_error@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"mail_server_temporary_error\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"mailbox_quota_exceeded@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"mailbox_quota_exceeded\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"mailbox_not_found@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"mailbox_not_found\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"no_dns_entries@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"no_dns_entries\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"possible_trap@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"possible_trap\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"possible_typo@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"possible_typo\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"role_based@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"role_based\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"timeout_exceeded@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"unknown\",\"timeout_exceeded\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"unroutable_ip_address@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"invalid\",\"unroutable_ip_address\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"free_email@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"valid\",\"\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"True\",\"true\",\"mx.example.com\",\"example\",\"\"\n\"role_based_catch_all@example.com\",\"First\",\"Last\",\"male\",\"127.0.0.1\",\"do_not_mail\",\"role_based_catch_all\",\"\",\"\",\"zero\",\"bounce\",\"male\",\"False\",\"true\",\"mx.example.com\",\"example\",\"\"\n"
|
|
414
441
|
```
|
|
415
442
|
|
|
416
443
|
Optional [v2 get file](https://www.zerobounce.net/docs/email-validation-api-quickstart/v2-get-file) query parameters use `Zerobounce::GetFileOptions` and `Zerobounce::DownloadType` (`PHASE_1`, `PHASE_2`, `COMBINED`). Set `activity_data` for validation `validate_file_get` only; it is not sent for `scoring_file_get`.
|
|
@@ -423,18 +450,17 @@ opts = Zerobounce::GetFileOptions.new(
|
|
|
423
450
|
csv = Zerobounce.validate_file_get(file_id, opts)
|
|
424
451
|
```
|
|
425
452
|
|
|
426
|
-
Non-success HTTP responses
|
|
453
|
+
Non-success HTTP responses and JSON error bodies (including HTTP 200 responses with `"success": false`) raise with the API message; see [Errors](#errors). To inspect a raw body string, use `Zerobounce.get_file_json_indicates_error?(body)`.
|
|
427
454
|
|
|
428
455
|
Delete file
|
|
429
456
|
```ruby
|
|
430
457
|
file_id = "75d854a6-565c-49f9-b4c8-b3344480ec4c"
|
|
431
|
-
=> "75d854a6-565c-49f9-b4c8-b3344480ec4c"
|
|
432
458
|
Zerobounce.validate_file_delete(file_id)
|
|
433
|
-
=>
|
|
434
|
-
{"success"=>true,
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
459
|
+
# =>
|
|
460
|
+
# {"success"=>true,
|
|
461
|
+
# "message"=>"File Deleted",
|
|
462
|
+
# "file_name"=>"validation.csv",
|
|
463
|
+
# "file_id"=>"75d854a6-565c-49f9-b4c8-b3344480ec4c"}
|
|
438
464
|
```
|
|
439
465
|
|
|
440
466
|
### AI Scoring
|
|
@@ -442,52 +468,61 @@ Zerobounce.validate_file_delete(file_id)
|
|
|
442
468
|
Send file
|
|
443
469
|
```ruby
|
|
444
470
|
scoring_file_path = File.join(Dir.pwd, 'files', 'scoring.csv')
|
|
445
|
-
=> "/home/odin/zb/wrappers/ruby-test/files/scoring.csv"
|
|
471
|
+
# => "/home/odin/zb/wrappers/ruby-test/files/scoring.csv"
|
|
446
472
|
Zerobounce.scoring_file_send(scoring_file_path)
|
|
447
|
-
=>
|
|
448
|
-
{"success"=>true,
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
473
|
+
# =>
|
|
474
|
+
# {"success"=>true,
|
|
475
|
+
# "message"=>"File Accepted",
|
|
476
|
+
# "file_name"=>"scoring.csv",
|
|
477
|
+
# "file_id"=>"89fb7262-b845-4fa1-aa25-e486347ec64e"}
|
|
452
478
|
# file_id will be required for the next steps
|
|
453
479
|
# optional named parameters
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
480
|
+
# email_address_column: 1,
|
|
481
|
+
# has_header_row: true,
|
|
482
|
+
# return_url: nil # results callback url
|
|
483
|
+
Zerobounce.scoring_file_send(scoring_file_path, email_address_column: 1)
|
|
458
484
|
```
|
|
459
485
|
|
|
460
486
|
File check
|
|
461
487
|
```ruby
|
|
462
488
|
file_id = "89fb7262-b845-4fa1-aa25-e486347ec64e"
|
|
463
|
-
=> "89fb7262-b845-4fa1-aa25-e486347ec64e"
|
|
464
489
|
Zerobounce.scoring_file_check(file_id)
|
|
465
|
-
=>
|
|
466
|
-
{"success"=>true,
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
490
|
+
# =>
|
|
491
|
+
# {"success"=>true,
|
|
492
|
+
# "file_id"=>"89fb7262-b845-4fa1-aa25-e486347ec64e",
|
|
493
|
+
# "file_name"=>"scoring.csv",
|
|
494
|
+
# "upload_date"=>"2023-04-28T16:57:18Z",
|
|
495
|
+
# "file_status"=>"Complete",
|
|
496
|
+
# "complete_percentage"=>"100% Complete.",
|
|
497
|
+
# "return_url"=>nil}
|
|
473
498
|
```
|
|
474
499
|
|
|
475
500
|
Get file
|
|
476
501
|
```ruby
|
|
477
502
|
file_id = "89fb7262-b845-4fa1-aa25-e486347ec64e"
|
|
478
|
-
=> "89fb7262-b845-4fa1-aa25-e486347ec64e"
|
|
479
503
|
Zerobounce.scoring_file_get(file_id)
|
|
480
|
-
=> "\"email\",\"ZeroBounceQualityScore\"\r\n\"disposable@example.com\",\"0\"\r\n\"invalid@example.com\",\"10\"\r\n\"valid@example.com\",\"10\"\r\n\"toxic@example.com\",\"2\"\r\n\"donotmail@example.com\",\"0\"\r\n\"spamtrap@example.com\",\"0\"\r\n\"abuse@example.com\",\"10\"\r\n\"unknown@example.com\",\"10\"\r\n\"catch_all@example.com\",\"10\"\r\n\"antispam_system@example.com\",\"0\"\r\n\"does_not_accept_mail@example.com\",\"0\"\r\n\"exception_occurred@example.com\",\"0\"\r\n\"failed_smtp_connection@example.com\",\"0\"\r\n\"failed_syntax_check@example.com\",\"0\"\r\n\"forcible_disconnect@example.com\",\"0\"\r\n\"global_suppression@example.com\",\"0\"\r\n\"greylisted@example.com\",\"0\"\r\n\"leading_period_removed@example.com\",\"0\"\r\n\"mail_server_did_not_respond@example.com\",\"0\"\r\n\"mail_server_temporary_error@example.com\",\"0\"\r\n\"mailbox_quota_exceeded@example.com\",\"0\"\r\n\"mailbox_not_found@example.com\",\"0\"\r\n\"no_dns_entries@example.com\",\"0\"\r\n\"possible_trap@example.com\",\"0\"\r\n\"possible_typo@example.com\",\"0\"\r\n\"role_based@example.com\",\"0\"\r\n\"timeout_exceeded@example.com\",\"0\"\r\n\"unroutable_ip_address@example.com\",\"0\"\r\n\"free_email@example.com\",\"0\"\r\n\"role_based_catch_all@example.com\",\"0\""
|
|
504
|
+
# => "\"email\",\"ZeroBounceQualityScore\"\r\n\"disposable@example.com\",\"0\"\r\n\"invalid@example.com\",\"10\"\r\n\"valid@example.com\",\"10\"\r\n\"toxic@example.com\",\"2\"\r\n\"donotmail@example.com\",\"0\"\r\n\"spamtrap@example.com\",\"0\"\r\n\"abuse@example.com\",\"10\"\r\n\"unknown@example.com\",\"10\"\r\n\"catch_all@example.com\",\"10\"\r\n\"antispam_system@example.com\",\"0\"\r\n\"does_not_accept_mail@example.com\",\"0\"\r\n\"exception_occurred@example.com\",\"0\"\r\n\"failed_smtp_connection@example.com\",\"0\"\r\n\"failed_syntax_check@example.com\",\"0\"\r\n\"forcible_disconnect@example.com\",\"0\"\r\n\"global_suppression@example.com\",\"0\"\r\n\"greylisted@example.com\",\"0\"\r\n\"leading_period_removed@example.com\",\"0\"\r\n\"mail_server_did_not_respond@example.com\",\"0\"\r\n\"mail_server_temporary_error@example.com\",\"0\"\r\n\"mailbox_quota_exceeded@example.com\",\"0\"\r\n\"mailbox_not_found@example.com\",\"0\"\r\n\"no_dns_entries@example.com\",\"0\"\r\n\"possible_trap@example.com\",\"0\"\r\n\"possible_typo@example.com\",\"0\"\r\n\"role_based@example.com\",\"0\"\r\n\"timeout_exceeded@example.com\",\"0\"\r\n\"unroutable_ip_address@example.com\",\"0\"\r\n\"free_email@example.com\",\"0\"\r\n\"role_based_catch_all@example.com\",\"0\""
|
|
481
505
|
# Optional second argument: GetFileOptions with download_type only (activity_data is not sent for scoring getfile)
|
|
482
|
-
|
|
506
|
+
Zerobounce.scoring_file_get(file_id, Zerobounce::GetFileOptions.new(download_type: Zerobounce::DownloadType::PHASE_2))
|
|
483
507
|
```
|
|
484
508
|
|
|
485
509
|
Delete file
|
|
486
510
|
```ruby
|
|
487
511
|
file_id = "89fb7262-b845-4fa1-aa25-e486347ec64e"
|
|
488
|
-
=> "89fb7262-b845-4fa1-aa25-e486347ec64e"
|
|
489
512
|
Zerobounce.scoring_file_delete(file_id)
|
|
490
|
-
|
|
513
|
+
# =>
|
|
514
|
+
# {"success"=>true,
|
|
515
|
+
# "message"=>"File Deleted",
|
|
516
|
+
# "file_name"=>"scoring.csv",
|
|
517
|
+
# "file_id"=>"89fb7262-b845-4fa1-aa25-e486347ec64e"}
|
|
518
|
+
|
|
519
|
+
# The API answers an unknown file id - and, for a while, a file that was only
|
|
520
|
+
# just uploaded - with {"success": false} on an HTTP 200. That raises:
|
|
521
|
+
begin
|
|
522
|
+
Zerobounce.scoring_file_delete("00000000-0000-0000-0000-000000000000")
|
|
523
|
+
rescue RuntimeError => e
|
|
524
|
+
e.message # => "File cannot be found."
|
|
525
|
+
end
|
|
491
526
|
```
|
|
492
527
|
|
|
493
528
|
|
|
@@ -542,176 +577,189 @@ When `has_header_row: false` is provided to `scoring_file_send()` method, column
|
|
|
542
577
|
|
|
543
578
|
### Email Finder
|
|
544
579
|
|
|
545
|
-
|
|
580
|
+
Use `find_email` to find one person's address and `find_domain` to get a domain's address formats; both take either `domain:` or `company_name:`.
|
|
581
|
+
|
|
582
|
+
Guess Format (deprecated)
|
|
583
|
+
|
|
584
|
+
`guessformat(domain, first_name: '', middle_name: '', last_name: '')` takes the domain as its only positional argument and has no `company_name:` option. It is deprecated, prints a deprecation warning on every call, and will be removed; use `find_domain` (formats) or `find_email` (one address) below.
|
|
546
585
|
```ruby
|
|
547
|
-
#
|
|
548
|
-
Zerobounce.guessformat(domain: "zerobounce.net")
|
|
549
|
-
=>
|
|
550
|
-
{"email"=>"",
|
|
551
|
-
"domain"=>"zerobounce.net",
|
|
552
|
-
"format"=>"first.last",
|
|
553
|
-
"status"=>"",
|
|
554
|
-
"sub_status"=>"",
|
|
555
|
-
"confidence"=>"high",
|
|
556
|
-
"did_you_mean"=>"",
|
|
557
|
-
"failure_reason"=>"",
|
|
558
|
-
"other_domain_formats"=>
|
|
559
|
-
[{"format"=>"first", "confidence"=>"high"},
|
|
560
|
-
{"format"=>"last.first", "confidence"=>"high"},
|
|
561
|
-
{"format"=>"lfirst", "confidence"=>"high"},
|
|
562
|
-
{"format"=>"lastfirst", "confidence"=>"high"},
|
|
563
|
-
{"format"=>"firstl", "confidence"=>"high"},
|
|
564
|
-
{"format"=>"last", "confidence"=>"medium"},
|
|
565
|
-
{"format"=>"first.middle.last", "confidence"=>"medium"},
|
|
566
|
-
{"format"=>"first-last", "confidence"=>"medium"},
|
|
567
|
-
{"format"=>"l.first", "confidence"=>"medium"},
|
|
568
|
-
{"format"=>"f.last", "confidence"=>"medium"},
|
|
569
|
-
{"format"=>"f-last", "confidence"=>"medium"},
|
|
570
|
-
{"format"=>"first.l", "confidence"=>"medium"},
|
|
571
|
-
{"format"=>"first-l", "confidence"=>"medium"},
|
|
572
|
-
{"format"=>"firstlast", "confidence"=>"medium"},
|
|
573
|
-
{"format"=>"first_l", "confidence"=>"medium"},
|
|
574
|
-
{"format"=>"f_last", "confidence"=>"medium"},
|
|
575
|
-
{"format"=>"last.f", "confidence"=>"medium"},
|
|
576
|
-
{"format"=>"last-f", "confidence"=>"medium"},
|
|
577
|
-
{"format"=>"last-first", "confidence"=>"medium"},
|
|
578
|
-
{"format"=>"first_last", "confidence"=>"medium"},
|
|
579
|
-
{"format"=>"last_f", "confidence"=>"medium"},
|
|
580
|
-
{"format"=>"last_first", "confidence"=>"medium"},
|
|
581
|
-
{"format"=>"flast", "confidence"=>"medium"},
|
|
582
|
-
{"format"=>"lastf", "confidence"=>"medium"},
|
|
583
|
-
{"format"=>"l-first", "confidence"=>"low"},
|
|
584
|
-
{"format"=>"l_first", "confidence"=>"low"}]}
|
|
585
|
-
|
|
586
|
-
# With names for better accuracy (new syntax)
|
|
587
|
-
Zerobounce.guessformat(domain: "zerobounce.net", first_name: "John", middle_name: 'Deere', last_name: "Doe")
|
|
588
|
-
|
|
589
|
-
# Backwards compatible syntax (still supported)
|
|
586
|
+
# Deprecated - prefer Zerobounce.find_domain(domain: "zerobounce.net")
|
|
590
587
|
Zerobounce.guessformat("zerobounce.net")
|
|
591
|
-
|
|
592
|
-
```
|
|
588
|
+
# => {"email"=>"", "domain"=>"zerobounce.net", "format"=>"first.last", "confidence"=>"high", "other_domain_formats"=>[...], ...}
|
|
593
589
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
# New keyword argument syntax (recommended)
|
|
597
|
-
Zerobounce.guessformat(company_name: "Zero Bounce")
|
|
598
|
-
=>
|
|
599
|
-
{"email"=>"",
|
|
600
|
-
"company_name"=>"Zero Bounce",
|
|
601
|
-
"format"=>"first.last",
|
|
602
|
-
"status"=>"",
|
|
603
|
-
"sub_status"=>"",
|
|
604
|
-
"confidence"=>"high",
|
|
605
|
-
"did_you_mean"=>"",
|
|
606
|
-
"failure_reason"=>"",
|
|
607
|
-
"other_domain_formats"=>[...]}
|
|
608
|
-
|
|
609
|
-
# With names for better accuracy (new syntax)
|
|
610
|
-
Zerobounce.guessformat(first_name: "John", last_name: "Doe", company_name: "Zero Bounce")
|
|
590
|
+
# Deprecated - prefer Zerobounce.find_email("John", domain: "zerobounce.net", middle_name: "Deere", last_name: "Doe")
|
|
591
|
+
Zerobounce.guessformat("zerobounce.net", first_name: "John", middle_name: 'Deere', last_name: "Doe")
|
|
611
592
|
```
|
|
612
593
|
|
|
613
594
|
Find Email Address
|
|
614
595
|
```ruby
|
|
615
596
|
# Find email by domain
|
|
616
597
|
Zerobounce.find_email("John", domain: "zerobounce.net")
|
|
617
|
-
=>
|
|
618
|
-
{
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
}
|
|
598
|
+
# =>
|
|
599
|
+
# {
|
|
600
|
+
# "email"=>"john@zerobounce.net",
|
|
601
|
+
# "email_confidence"=>"medium",
|
|
602
|
+
# "domain"=>"zerobounce.net",
|
|
603
|
+
# "company_name"=>"ZeroBounce",
|
|
604
|
+
# "did_you_mean"=>"",
|
|
605
|
+
# "failure_reason"=>""
|
|
606
|
+
# }
|
|
626
607
|
|
|
627
608
|
# Find email by company name
|
|
628
609
|
Zerobounce.find_email("John", company_name: "Zero Bounce")
|
|
629
|
-
=>
|
|
630
|
-
{
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
}
|
|
610
|
+
# =>
|
|
611
|
+
# {
|
|
612
|
+
# "email"=>"john@zerobounce.net",
|
|
613
|
+
# "email_confidence"=>"medium",
|
|
614
|
+
# "domain"=>"zerobounce.net",
|
|
615
|
+
# "company_name"=>"ZeroBounce",
|
|
616
|
+
# "did_you_mean"=>"",
|
|
617
|
+
# "failure_reason"=>""
|
|
618
|
+
# }
|
|
638
619
|
|
|
639
620
|
# With additional name information for better accuracy
|
|
640
621
|
Zerobounce.find_email("John", domain: "zerobounce.net", middle_name: "Deere", last_name: "Doe")
|
|
622
|
+
|
|
623
|
+
# The first name is optional. Without one the call answers with the domain's
|
|
624
|
+
# address format rather than one person's address.
|
|
625
|
+
Zerobounce.find_email(domain: "zerobounce.net")
|
|
641
626
|
```
|
|
642
627
|
|
|
643
628
|
Find Domain Information
|
|
644
629
|
```ruby
|
|
645
630
|
# Find domain format by domain
|
|
646
631
|
Zerobounce.find_domain(domain: "zerobounce.net")
|
|
647
|
-
=>
|
|
648
|
-
{
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
}
|
|
632
|
+
# =>
|
|
633
|
+
# {
|
|
634
|
+
# "domain"=>"zerobounce.net",
|
|
635
|
+
# "company_name"=>"Hertza, LLC",
|
|
636
|
+
# "format"=>"first.last",
|
|
637
|
+
# "confidence"=>"high",
|
|
638
|
+
# "did_you_mean"=>"",
|
|
639
|
+
# "failure_reason"=>"",
|
|
640
|
+
# "other_domain_formats"=>[
|
|
641
|
+
# {"format"=>"first", "confidence"=>"high"},
|
|
642
|
+
# {"format"=>"last.first", "confidence"=>"high"},
|
|
643
|
+
# {"format"=>"lastfirst", "confidence"=>"high"},
|
|
644
|
+
# {"format"=>"firstl", "confidence"=>"high"},
|
|
645
|
+
# {"format"=>"lfirst", "confidence"=>"high"},
|
|
646
|
+
# {"format"=>"firstlast", "confidence"=>"high"},
|
|
647
|
+
# {"format"=>"last_middle_f", "confidence"=>"high"},
|
|
648
|
+
# {"format"=>"last", "confidence"=>"high"},
|
|
649
|
+
# {"format"=>"f.last", "confidence"=>"medium"},
|
|
650
|
+
# {"format"=>"last-f", "confidence"=>"medium"},
|
|
651
|
+
# {"format"=>"l.first", "confidence"=>"medium"},
|
|
652
|
+
# {"format"=>"last_f", "confidence"=>"medium"},
|
|
653
|
+
# {"format"=>"first.middle.last", "confidence"=>"medium"},
|
|
654
|
+
# {"format"=>"first-last", "confidence"=>"medium"},
|
|
655
|
+
# {"format"=>"last.f", "confidence"=>"medium"},
|
|
656
|
+
# {"format"=>"last_first", "confidence"=>"medium"},
|
|
657
|
+
# {"format"=>"f-last", "confidence"=>"medium"},
|
|
658
|
+
# {"format"=>"first.l", "confidence"=>"medium"},
|
|
659
|
+
# {"format"=>"first-l", "confidence"=>"medium"},
|
|
660
|
+
# {"format"=>"first_l", "confidence"=>"medium"},
|
|
661
|
+
# {"format"=>"first_last", "confidence"=>"medium"},
|
|
662
|
+
# {"format"=>"f_last", "confidence"=>"medium"},
|
|
663
|
+
# {"format"=>"last-first", "confidence"=>"medium"},
|
|
664
|
+
# {"format"=>"flast", "confidence"=>"medium"},
|
|
665
|
+
# {"format"=>"lastf", "confidence"=>"medium"},
|
|
666
|
+
# {"format"=>"l_first", "confidence"=>"medium"},
|
|
667
|
+
# {"format"=>"l-first", "confidence"=>"medium"},
|
|
668
|
+
# {"format"=>"first-middle-last", "confidence"=>"low"},
|
|
669
|
+
# {"format"=>"firstmlast", "confidence"=>"low"},
|
|
670
|
+
# {"format"=>"last.middle.first", "confidence"=>"low"},
|
|
671
|
+
# {"format"=>"last_middle_first", "confidence"=>"low"},
|
|
672
|
+
# {"format"=>"first_middle_last", "confidence"=>"low"},
|
|
673
|
+
# {"format"=>"last-middle-first", "confidence"=>"low"},
|
|
674
|
+
# {"format"=>"first-m-last", "confidence"=>"low"},
|
|
675
|
+
# {"format"=>"firstmiddlelast", "confidence"=>"low"},
|
|
676
|
+
# {"format"=>"last.m.first", "confidence"=>"low"},
|
|
677
|
+
# {"format"=>"lastmfirst", "confidence"=>"low"},
|
|
678
|
+
# {"format"=>"lastmiddlefirst", "confidence"=>"low"},
|
|
679
|
+
# {"format"=>"last_m_first", "confidence"=>"low"},
|
|
680
|
+
# {"format"=>"first.m.last", "confidence"=>"low"},
|
|
681
|
+
# {"format"=>"first_m_last", "confidence"=>"low"},
|
|
682
|
+
# {"format"=>"last-m-first", "confidence"=>"low"}
|
|
683
|
+
# ]
|
|
684
|
+
# }
|
|
700
685
|
|
|
701
686
|
# Find domain format by company name
|
|
702
687
|
Zerobounce.find_domain(company_name: "Zero Bounce")
|
|
703
|
-
=>
|
|
704
|
-
{
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
}
|
|
688
|
+
# =>
|
|
689
|
+
# {
|
|
690
|
+
# "domain"=>"zerobounce.net",
|
|
691
|
+
# "company_name"=>"Zero Bounce",
|
|
692
|
+
# "format"=>"first.last",
|
|
693
|
+
# "confidence"=>"high",
|
|
694
|
+
# "did_you_mean"=>"",
|
|
695
|
+
# "failure_reason"=>"",
|
|
696
|
+
# "other_domain_formats"=>[...]
|
|
697
|
+
# }
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
## Errors
|
|
701
|
+
|
|
702
|
+
- An HTTP error status raises the `RestClient` exception for that status, as it did up to 2.1.8: `RestClient::NotFound`, `RestClient::Forbidden` and so on, all subclasses of `RestClient::ExceptionWithResponse` and of `RuntimeError`. `#http_code` gives the status. The message is the API's own short error text (up to 2.1.8 it was RestClient's, such as `404 Not Found`); an HTML error page is reduced to its title.
|
|
703
|
+
- An error reported with an HTTP 200 - an `error` field, `{"success": false}`, or an account-level `validate_batch` failure - raises `RuntimeError` with the API's message.
|
|
704
|
+
- Invalid arguments, and a base URL that is not `https://`, raise `ArgumentError` before any request is sent.
|
|
705
|
+
- Redirects are not followed; a 3xx raises its `RestClient` exception (for example `RestClient::Found`).
|
|
706
|
+
- The Warmup client raises `Zerobounce::ApiResponseError`, whose `#status_code` gives the HTTP status.
|
|
707
|
+
|
|
708
|
+
The API key is removed from every error message.
|
|
709
|
+
|
|
710
|
+
```ruby
|
|
711
|
+
begin
|
|
712
|
+
Zerobounce.validate_file_check("00000000-0000-0000-0000-000000000000")
|
|
713
|
+
rescue RestClient::ExceptionWithResponse => e
|
|
714
|
+
e.http_code # => 404, for example
|
|
715
|
+
e.message # => the API's error text
|
|
716
|
+
rescue RuntimeError => e
|
|
717
|
+
e.message # => e.g. "File cannot be found."
|
|
718
|
+
end
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
## Warmup API
|
|
722
|
+
|
|
723
|
+
The Warmup API is a separate product. It has its own host, its own team-scoped key, and its own client; your validation key will not work with it.
|
|
724
|
+
|
|
725
|
+
```ruby
|
|
726
|
+
warmup = Zerobounce::Warmup.new('<YOUR_WARMUP_API_KEY>')
|
|
727
|
+
|
|
728
|
+
warmup.list_sending_accounts
|
|
729
|
+
warmup.progress_today
|
|
730
|
+
warmup.download_seeds # CSV text, columns seed,provider
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
Add a from-address you run yourself, with one of the five standard engagement rules (0 Default, 1 Slow Pace, 2 Repair, 3 Boost, 4 Protect):
|
|
734
|
+
|
|
735
|
+
```ruby
|
|
736
|
+
warmup.add_sending_account('sender@example.com', 'self_managed', engagement_rule_id: 0)
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
Or have ZeroBounce provision the mailbox. A 200 means the request was accepted; provisioning happens afterwards.
|
|
740
|
+
|
|
741
|
+
```ruby
|
|
742
|
+
warmup.add_sending_account(
|
|
743
|
+
'sender@example.com', 'zb_managed',
|
|
744
|
+
email_content: { types_of_emails: %w[newsletter marketing] },
|
|
745
|
+
managed_sending: { timezone_offset: -5, warmup_start_date: Date.new(2026, 3, 4) }
|
|
746
|
+
)
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
A custom engagement rule can be changed only once every seven days; inside that window the API answers 429.
|
|
750
|
+
|
|
751
|
+
```ruby
|
|
752
|
+
warmup.create_custom_engagement('sender@example.com', 20, 20, 35) # reply, important, click %
|
|
713
753
|
```
|
|
714
754
|
|
|
755
|
+
`check_domain_dmarc` takes an **email address**, not a domain — the live API rejects a bare domain even though the docs describe one:
|
|
756
|
+
|
|
757
|
+
```ruby
|
|
758
|
+
warmup.check_domain_dmarc('sender@example.com')
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
Every documented empty success (204, or an empty 200) comes back as `nil`, and a payload that is not a JSON object — `/seeds` is an array, `/seed-count` a bare number — comes back as the parsed value itself. Failures raise `Zerobounce::ApiResponseError`, whose `#status_code` gives the HTTP status. Nothing is stored by `test_smtp_configuration`, and the credentials you pass it are masked out of any error it raises.
|
|
762
|
+
|
|
715
763
|
## Development
|
|
716
764
|
|
|
717
765
|
### Local setup
|
|
@@ -747,14 +795,7 @@ docker run --rm zb-ruby-sdk
|
|
|
747
795
|
bundle exec rspec
|
|
748
796
|
```
|
|
749
797
|
|
|
750
|
-
|
|
751
|
-
```bash
|
|
752
|
-
running tests
|
|
753
|
-
.....................................................
|
|
754
|
-
|
|
755
|
-
Finished in 6.81 seconds (files took 0.40587 seconds to load)
|
|
756
|
-
53 examples, 0 failures
|
|
757
|
-
```
|
|
798
|
+
It should end with `0 failures`. The suite is offline: recorded cassettes and WebMock stubs, no network.
|
|
758
799
|
|
|
759
800
|
### Test parameters
|
|
760
801
|
The tests use the following environment parameter:
|
|
@@ -767,9 +808,30 @@ To set your key:
|
|
|
767
808
|
export ZEROBOUNCE_API_KEY=your_api_key_here
|
|
768
809
|
```
|
|
769
810
|
|
|
770
|
-
A
|
|
811
|
+
A `.env.example` file is provided; it holds a placeholder (`your_api_key_here`), not a key. The spec helper loads a `.env` file if there is one.
|
|
812
|
+
|
|
813
|
+
Tests use webmock and vcr for mocking HTTP requests. The cassettes in `spec/cassettes` were recorded against the live API; the key in them has been replaced with a placeholder, and requests are matched ignoring `api_key`, so any value of `ZEROBOUNCE_API_KEY` works (CI uses `invalid_key_for_tests`). To re-record a cassette, delete it and run the spec with a real key; check that the new cassette holds no key before committing it.
|
|
814
|
+
|
|
815
|
+
### Live API suite
|
|
816
|
+
|
|
817
|
+
`rspec` never touches the network: the live suite lives outside `spec/`, so CI does not even load it. It needs real keys, which come from the environment and are never written anywhere:
|
|
818
|
+
|
|
819
|
+
```bash
|
|
820
|
+
export ZEROBOUNCE_API_KEY=... # validation API
|
|
821
|
+
export ZEROBOUNCE_WARMUP_API_KEY=... # Warmup API
|
|
822
|
+
ruby -Ilib live/live_api.rb
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
By default it only makes free calls: sandbox addresses, reads, and requests that are expected to fail but still prove the API accepts the payload. Nothing in the free tier submits a job, and it checks that the credit balance did not move. Two flags opt in to more:
|
|
826
|
+
|
|
827
|
+
| Flag | What it adds |
|
|
828
|
+
| --- | --- |
|
|
829
|
+
| `ZEROBOUNCE_LIVE_SPEND=1` | billable calls (scoring, activity, email finder), a bulk round trip that deletes its own job, and a complete S3 job payload (a real job if the account has an S3 integration) |
|
|
830
|
+
| `ZEROBOUNCE_LIVE_CHANGES=1` | reversible account changes — a test filter and a self-managed Warmup sending account — each undone in cleanup even when a check fails |
|
|
831
|
+
|
|
832
|
+
It never creates an Inbox Placement test, sets the Inbox Placement webhook, or starts ZB-managed Warmup onboarding, because the API cannot undo any of those.
|
|
771
833
|
|
|
772
|
-
|
|
834
|
+
Run it by hand before every release: the offline suite proves the SDK sends what we think it sends, and only the live suite proves the API accepts it.
|
|
773
835
|
|
|
774
836
|
## Publish
|
|
775
837
|
|