Skip to content

Conversation

@ducduyn31
Copy link

Context

The ZeroBounce API supports a timeout parameter for email validation that was not exposed in this SDK. According to the https://www.zerobounce.net/docs/email-validation-api-quickstart/v2-validate-emails, the timeout parameter allows controlling the validation duration (3-60 seconds). If the timeout is met, the API returns unknown/greylisted status instead of waiting indefinitely.

Summay of Changes

  • Added optional timeout parameter to validateEmail for controlling validation duration (3-60 seconds)
  • If timeout is met, the API returns unknown/greylisted status
  • Backwards compatible: supports both legacy and new syntax
 // New object syntax (recommended)
  await zeroBounce.validateEmail(email, {
    ip_address: "127.0.0.1",
    timeout: 10,
  });

  // Just timeout
  await zeroBounce.validateEmail(email, { timeout: 10 });

  // Legacy syntax still works
  await zeroBounce.validateEmail(email, "127.0.0.1");

Tests

Unit tests pass:
image

I also added an integration tests with the emails we provided in Readme, but only run locally

Here is the test implementation
import { ZeroBounceSDK } from "../src/zero-bounce.js";
import "whatwg-fetch";

const API_KEY = process.env.ZEROBOUNCE_API_KEY;

const describeIfApiKey = API_KEY ? describe : describe.skip;

describeIfApiKey("ZeroBounceSDK Integration Tests", () => {
  let zeroBounceSDK;

  beforeEach(() => {
    zeroBounceSDK = new ZeroBounceSDK();
    zeroBounceSDK.init(API_KEY);
  });

  describe("validateEmail", () => {
    it("should validate a valid test email", async () => {
      const response = await zeroBounceSDK.validateEmail("valid@example.com");

      expect(response.address).toBe("valid@example.com");
      expect(response.status).toBe("valid");
    });

    it("should validate an invalid test email", async () => {
      const response = await zeroBounceSDK.validateEmail("invalid@example.com");

      expect(response.address).toBe("invalid@example.com");
      expect(response.status).toBe("invalid");
    });

    it("should validate with ip_address using legacy syntax", async () => {
      const response = await zeroBounceSDK.validateEmail("valid@example.com", "99.110.204.1");

      expect(response.address).toBe("valid@example.com");
      expect(response.status).toBe("valid");
    });

    it("should validate with options object", async () => {
      const response = await zeroBounceSDK.validateEmail("valid@example.com", {
        ip_address: "99.110.204.1",
      });

      expect(response.address).toBe("valid@example.com");
      expect(response.status).toBe("valid");
    });

    it("should validate with timeout option", async () => {
      const response = await zeroBounceSDK.validateEmail("valid@example.com", {
        timeout: 10,
      });

      expect(response.address).toBe("valid@example.com");
      expect(response.status).toBe("valid");
    });

    it("should validate with both ip_address and timeout options", async () => {
      const response = await zeroBounceSDK.validateEmail("valid@example.com", {
        ip_address: "99.110.204.1",
        timeout: 10,
      });

      expect(response.address).toBe("valid@example.com");
      expect(response.status).toBe("valid");
    });

    it("should return greylisted for greylisted test email", async () => {
      const response = await zeroBounceSDK.validateEmail("greylisted@example.com");

      expect(response.address).toBe("greylisted@example.com");
      expect(response.sub_status).toBe("greylisted");
    });

    it("should return timeout_exceeded for timeout test email", async () => {
      const response = await zeroBounceSDK.validateEmail("timeout_exceeded@example.com");

      expect(response.address).toBe("timeout_exceeded@example.com");
      expect(response.sub_status).toBe("timeout_exceeded");
    });
  });

  describe("getCredits", () => {
    it("should return credits", async () => {
      const response = await zeroBounceSDK.getCredits();

      expect(response).toHaveProperty("Credits");
    });
  });
});

Test Result:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant