@zerobounce/zero-bounce-sdk 1.2.0 → 1.2.1

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.
package/documentation.md CHANGED
@@ -57,13 +57,19 @@ try {
57
57
 
58
58
  ```javascript
59
59
  const email = "<EMAIL_ADDRESS>"; // The email address you want to validate
60
- const ip_address = "127.0.0.1"; // The IP Address the email signed up from (Optional)
61
60
 
61
+ // Using options object (recommended)
62
62
  try {
63
- const response = await zeroBounce.validateEmail(email, ip_address);
63
+ const response = await zeroBounce.validateEmail(email, {
64
+ ip_address: "127.0.0.1", // The IP Address the email signed up from (Optional)
65
+ timeout: 10, // Validation timeout in seconds, 3-60 (Optional)
66
+ });
64
67
  } catch (error) {
65
68
  console.error(error);
66
69
  }
70
+
71
+ // Legacy syntax (still supported for backwards compatibility)
72
+ // const response = await zeroBounce.validateEmail(email, "127.0.0.1");
67
73
  ```
68
74
 
69
75
  - ####### Get api usage from a start date to an end date
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerobounce/zero-bounce-sdk",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "This SDK contains methods for interacting easily with ZeroBounce API. More information about ZeroBounce you can find in the official documentation.",
5
5
  "main": "dist/zeroBounceSDK.js",
6
6
  "scripts": {
package/src/utils.js CHANGED
@@ -74,3 +74,9 @@ export function parameterIsMissing(parameter, aditionalInfo = "") {
74
74
  `ZeroBounce: ${parameter} parameter is missing. ${aditionalInfo}`
75
75
  );
76
76
  }
77
+
78
+ export function parameterIsInvalid(parameter, aditionalInfo = "") {
79
+ console.error(
80
+ `ZeroBounce: ${parameter} parameter is invalid. ${aditionalInfo}`
81
+ );
82
+ }
@@ -1,4 +1,4 @@
1
- import { createRequest, notInitialized, parameterIsMissing } from "./utils.js";
1
+ import { createRequest, notInitialized, parameterIsMissing, parameterIsInvalid } from "./utils.js";
2
2
 
3
3
  export class ZeroBounceSDK {
4
4
  static ApiURL = Object.freeze({
@@ -40,9 +40,11 @@ export class ZeroBounceSDK {
40
40
 
41
41
  /**
42
42
  * @param email - email to be validated
43
- * @param ip_address
43
+ * @param options - options object or ip_address string for backwards compatibility
44
+ * @param options.ip_address - IP address (optional)
45
+ * @param options.timeout - validation timeout in seconds, 3-60 (optional). If met, the API will return unknown/greylisted.
44
46
  * */
45
- validateEmail(email, ip_address = null) {
47
+ validateEmail(email, options = null) {
46
48
  if (!this._initialized) {
47
49
  notInitialized();
48
50
  return;
@@ -50,11 +52,28 @@ export class ZeroBounceSDK {
50
52
  parameterIsMissing("Email");
51
53
  return;
52
54
  }
55
+
56
+ let ip_address;
57
+ let timeout;
58
+ if (typeof options === "string") {
59
+ ip_address = options;
60
+ } else if (options && typeof options === "object") {
61
+ ip_address = options.ip_address;
62
+ timeout = options.timeout;
63
+ }
64
+
65
+ if (timeout != null && (timeout < 3 || timeout > 60)) {
66
+ parameterIsInvalid("timeout", "Must be between 3 and 60 seconds.");
67
+ return;
68
+ }
69
+
53
70
  const params = {
54
71
  api_key: this._api_key,
55
- email: email,
56
- ip_address,
72
+ email,
57
73
  };
74
+ if (ip_address != null) params.ip_address = ip_address;
75
+ if (timeout != null) params.timeout = timeout;
76
+
58
77
  return createRequest({ requestType: "GET", params, path: "/validate", apiBaseURL: this._api_base_url });
59
78
  }
60
79
 
@@ -199,6 +199,84 @@ describe("ZeroBounceSDK", () => {
199
199
  const response = await zeroBounceSDK.validateEmail(email, ip_address);
200
200
  expect(response).toEqual(expectedResponse);
201
201
  });
202
+
203
+ it("should pass options object to the API", async () => {
204
+ const expectedResponse = {
205
+ "address": "valid@example.com",
206
+ "status": "valid",
207
+ "sub_status": "",
208
+ "free_email": false,
209
+ "did_you_mean": null,
210
+ "account": null,
211
+ "domain": null,
212
+ "domain_age_days": "9692",
213
+ "smtp_provider": "example",
214
+ "mx_found": "true",
215
+ "mx_record": "mx.example.com",
216
+ "firstname": "zero",
217
+ "lastname": "bounce",
218
+ "gender": "male",
219
+ "country": null,
220
+ "region": null,
221
+ "city": null,
222
+ "zipcode": null,
223
+ "processed_at": "2023-04-27 13:47:23.980"
224
+ }
225
+
226
+ const fetchSpy = jest.spyOn(global, "fetch").mockImplementationOnce(() => Promise.resolve({
227
+ json: () => Promise.resolve(expectedResponse),
228
+ text: () => Promise.resolve(JSON.stringify(expectedResponse)),
229
+ }));
230
+
231
+ zeroBounceSDK.init("valid-api-key", ZeroBounceSDK.ApiURL.DEFAULT_API_URL);
232
+ await zeroBounceSDK.validateEmail(email, { ip_address: ip_address, timeout: 10 });
233
+
234
+ expect(fetchSpy).toHaveBeenCalledWith(
235
+ expect.stringContaining("ip_address=127.0.0.1"),
236
+ expect.any(Object)
237
+ );
238
+ expect(fetchSpy).toHaveBeenCalledWith(
239
+ expect.stringContaining("timeout=10"),
240
+ expect.any(Object)
241
+ );
242
+ });
243
+
244
+ it("should pass timeout only via options object", async () => {
245
+ const expectedResponse = {
246
+ "address": "valid@example.com",
247
+ "status": "valid",
248
+ "sub_status": "",
249
+ }
250
+
251
+ const fetchSpy = jest.spyOn(global, "fetch").mockImplementationOnce(() => Promise.resolve({
252
+ json: () => Promise.resolve(expectedResponse),
253
+ text: () => Promise.resolve(JSON.stringify(expectedResponse)),
254
+ }));
255
+
256
+ zeroBounceSDK.init("valid-api-key", ZeroBounceSDK.ApiURL.DEFAULT_API_URL);
257
+ await zeroBounceSDK.validateEmail(email, { timeout: 30 });
258
+
259
+ expect(fetchSpy).toHaveBeenCalledWith(
260
+ expect.stringContaining("timeout=30"),
261
+ expect.any(Object)
262
+ );
263
+ });
264
+
265
+ it("should throw an error if timeout is less than 3", async () => {
266
+ zeroBounceSDK.init("valid-api-key", ZeroBounceSDK.ApiURL.DEFAULT_API_URL);
267
+ await zeroBounceSDK.validateEmail(email, { timeout: 2 });
268
+ expect(console.error).toHaveBeenCalledWith(
269
+ expect.stringContaining("timeout parameter is invalid")
270
+ );
271
+ });
272
+
273
+ it("should throw an error if timeout is greater than 60", async () => {
274
+ zeroBounceSDK.init("valid-api-key", ZeroBounceSDK.ApiURL.DEFAULT_API_URL);
275
+ await zeroBounceSDK.validateEmail(email, { timeout: 61 });
276
+ expect(console.error).toHaveBeenCalledWith(
277
+ expect.stringContaining("timeout parameter is invalid")
278
+ );
279
+ });
202
280
  });
203
281
 
204
282
 
@@ -1 +0,0 @@
1
- !function(e,i){"object"==typeof exports&&"object"==typeof module?module.exports=i():"function"==typeof define&&define.amd?define([],i):"object"==typeof exports?exports.ZeroBounceSDK=i():e.ZeroBounceSDK=i()}(this,(()=>(()=>{"use strict";var e={d:(i,t)=>{for(var a in t)e.o(t,a)&&!e.o(i,a)&&Object.defineProperty(i,a,{enumerable:!0,get:t[a]})},o:(e,i)=>Object.prototype.hasOwnProperty.call(e,i)},i={};e.d(i,{default:()=>s});const t={Accept:"*/*","Accept-Encoding":"gzip, deflate, br",Connection:"keep-alive"};async function a({requestType:e,body:i=null,params:a=null,path:r,batch:n=!1,returnText:s=!1,scoring:l=!1}){const o=`${n?"https://bulkapi.zerobounce.net/v2":"https://api.zerobounce.net/v2"}${r}?${new URLSearchParams(a)}`;try{const a=await fetch(o,{method:e,headers:t,body:i});if(s){const e=await a.text();return e.includes('"success":"False"')?JSON.parse(e):function(e,i){if(!window.navigator.msSaveOrOpenBlob){const t=document.createElement("a");document.body.appendChild(t);const a=window.URL.createObjectURL(e);return t.href=a,t.download=i,t.click(),setTimeout((()=>{window.URL.revokeObjectURL(a),document.body.removeChild(t)}),0),i}window.navigator.msSaveOrOpenBlob(e,i)}(new Blob([e],{type:"application/json"}),`result${l?"-scoring":""}.csv`)}if(403===a.status)throw new Error("[Error]: api_key is invalid");return await a.json()}catch(e){throw new Error(e)}}function r(){console.error("ZeroBounce: Call init function first with a valid api key.")}function n(e,i=""){console.error(`ZeroBounce: ${e} parameter is missing. ${i}`)}const s=class{constructor(){this._initialized=!1,this._api_key=null}init(e){e?(this._api_key=e,this._initialized=!0):n("Api key","Please provide a valid API key.")}getCredits(){if(this._initialized)return a({requestType:"GET",params:{api_key:this._api_key},path:"/getcredits"});r()}validateEmail(e,i=null){if(this._initialized){if(e)return a({requestType:"GET",params:{api_key:this._api_key,email:e,ip_address:i},path:"/validate"});n("Email")}else r()}getApiUsage(e,i){if(this._initialized)if(e){if(i)return a({requestType:"GET",params:{api_key:this._api_key,start_date:e,end_date:i},path:"/getapiusage"});n("End date","Format: YYYY-MM-DD")}else n("Start date","Format: YYYY-MM-DD");else r()}validateBatch(e){if(!this._initialized)return void r();if(!e)return void n("Email list");const i={api_key:this._api_key,email_batch:e};return a({requestType:"POST",path:"/validatebatch",body:JSON.stringify(i),batch:!0})}getEmailActivity(e){if(this._initialized){if(e)return a({requestType:"GET",params:{api_key:this._api_key,email:e},path:"/activity"});n("Email")}else r()}sendFile({file:e,email_address_column:i,first_name_column:t=!1,return_url:s=!1,last_name_column:l=!1,gender_column:o=!1,ip_address_column:d=!1,has_header_row:p=!1,remove_duplicate:u=!1}){if(!this._initialized)return void r();if(!e)return void n("file");if(!i)return void n("email_address_column");const _=new FormData;return s&&_.append("return_url",s),t&&_.append("first_name_column",t),l&&_.append("last_name_column",l),o&&_.append("gender_column",o),d&&_.append("ip_address_column",d),_.append("email_address_column",i),_.append("file",e),_.append("has_header_row",p),_.append("remove_duplicate",u),_.append("api_key",this._api_key),a({requestType:"POST",path:"/sendfile",body:_,batch:!0})}sendScoringFile({file:e,email_address_column:i,return_url:t=!1,has_header_row:s=!1,remove_duplicate:l=!1}){if(!this._initialized)return void r();if(!e)return void n("file: File");if(!i)return void n("email_address_column: number");const o=new FormData;return t&&o.append("return_url",t),o.append("file",e),o.append("email_address_column",i),o.append("has_header_row",s),o.append("api_key",this._api_key),o.append("remove_duplicate",l),a({requestType:"POST",path:"/scoring/sendfile",body:o,batch:!0})}_getStatusUtil(e,i){if(this._initialized){if(e)return a({requestType:"GET",params:{api_key:this._api_key,file_id:e},path:i,batch:!0});n("File id")}else r()}getFileStatus(e){return this._getStatusUtil(e,"/filestatus")}getScoringFileStatus(e){return this._getStatusUtil(e,"/scoring/filestatus")}_getFileUtil(e,i,t=!1){if(this._initialized){if(e)return a({requestType:"GET",params:{api_key:this._api_key,file_id:e},path:i,batch:!0,returnText:!0,scoring:t});n("File id")}else r()}getFile(e){return this._getFileUtil(e,"/getfile")}getScoringFile(e){return this._getFileUtil(e,"/scoring/getfile",!0)}_deleteFileUtil(e,i,t=!1){if(this._initialized){if(e)return a({requestType:"GET",params:{api_key:this._api_key,file_id:e},path:i,batch:!0,scoring:t});n("File id")}else r()}deleteFile(e){return this._deleteFileUtil(e,"/deletefile")}deleteScoringFile(e){return this._deleteFileUtil(e,"/scoring/deletefile",!0)}guessFormat({domain:e,first_name:i=null,middle_name:t=null,last_name:s=null}){if(this._initialized){if(e)return a({requestType:"GET",params:{api_key:this._api_key,domain:e,first_name:i,middle_name:t,last_name:s},path:"/guessformat"});n("domain")}else r()}};return i.default})()));