@adtrackify/at-service-common 3.18.15 → 3.18.16

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.
Files changed (29) hide show
  1. package/dist/cjs/__tests__/services/email-verification/contact-email-verification-service.spec.js +89 -0
  2. package/dist/cjs/__tests__/services/email-verification/contact-email-verification-service.spec.js.map +1 -0
  3. package/dist/cjs/services/email-verification/contact-email-verification-service.d.ts +7 -0
  4. package/dist/cjs/services/email-verification/contact-email-verification-service.js +67 -0
  5. package/dist/cjs/services/email-verification/contact-email-verification-service.js.map +1 -0
  6. package/dist/cjs/services/email-verification/index.d.ts +1 -1
  7. package/dist/cjs/services/email-verification/index.js +1 -1
  8. package/dist/cjs/services/email-verification/index.js.map +1 -1
  9. package/dist/esm/__tests__/services/email-verification/contact-email-verification-service.spec.js +87 -0
  10. package/dist/esm/__tests__/services/email-verification/contact-email-verification-service.spec.js.map +1 -0
  11. package/dist/esm/services/email-verification/contact-email-verification-service.d.ts +7 -0
  12. package/dist/esm/services/email-verification/contact-email-verification-service.js +63 -0
  13. package/dist/esm/services/email-verification/contact-email-verification-service.js.map +1 -0
  14. package/dist/esm/services/email-verification/index.d.ts +1 -1
  15. package/dist/esm/services/email-verification/index.js +1 -1
  16. package/dist/esm/services/email-verification/index.js.map +1 -1
  17. package/package.json +1 -1
  18. package/dist/cjs/__tests__/services/email-verification/contact-email-verifier.spec.js +0 -77
  19. package/dist/cjs/__tests__/services/email-verification/contact-email-verifier.spec.js.map +0 -1
  20. package/dist/cjs/services/email-verification/contact-email-verifier.d.ts +0 -4
  21. package/dist/cjs/services/email-verification/contact-email-verifier.js +0 -61
  22. package/dist/cjs/services/email-verification/contact-email-verifier.js.map +0 -1
  23. package/dist/esm/__tests__/services/email-verification/contact-email-verifier.spec.js +0 -75
  24. package/dist/esm/__tests__/services/email-verification/contact-email-verifier.spec.js.map +0 -1
  25. package/dist/esm/services/email-verification/contact-email-verifier.d.ts +0 -4
  26. package/dist/esm/services/email-verification/contact-email-verifier.js +0 -56
  27. package/dist/esm/services/email-verification/contact-email-verifier.js.map +0 -1
  28. /package/dist/cjs/__tests__/services/email-verification/{contact-email-verifier.spec.d.ts → contact-email-verification-service.spec.d.ts} +0 -0
  29. /package/dist/esm/__tests__/services/email-verification/{contact-email-verifier.spec.d.ts → contact-email-verification-service.spec.d.ts} +0 -0
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const at_tracking_event_types_1 = require("@adtrackify/at-tracking-event-types");
4
+ jest.mock('../../../services/email-verification/email-verification-service', () => ({
5
+ EmailVerificationService: jest.fn().mockImplementation(() => ({ getEmailVerificationWithCaching: jest.fn() })),
6
+ }));
7
+ const emails_1 = require("../../../libs/emails");
8
+ const contact_email_verification_service_1 = require("../../../services/email-verification/contact-email-verification-service");
9
+ const email_verification_service_1 = require("../../../services/email-verification/email-verification-service");
10
+ const createTestContact = (emailAddress, id = 'c1') => ({
11
+ id,
12
+ source: at_tracking_event_types_1.CONTACT_ACQUISITION_SOURCE.BDEX,
13
+ sourceId: at_tracking_event_types_1.CONTACT_SOURCE_ID.BDEX,
14
+ firstName: 'John',
15
+ lastName: 'Doe',
16
+ emailAddress,
17
+ emailStatus: at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE,
18
+ pixelId: 'px',
19
+ identityId: 'id',
20
+ sessionId: 'sess',
21
+ createdAt: '1',
22
+ updatedAt: '1',
23
+ });
24
+ describe('isBlacklistedEmail', () => {
25
+ it('flags blacklisted domains and passes clean ones', () => {
26
+ expect((0, emails_1.isBlacklistedEmail)('a@consolidated.net')).toBe(true);
27
+ expect((0, emails_1.isBlacklistedEmail)('a@mailinator.com')).toBe(true);
28
+ expect((0, emails_1.isBlacklistedEmail)('a@example.com')).toBe(false);
29
+ });
30
+ });
31
+ describe('ContactEmailVerificationService', () => {
32
+ let service;
33
+ let getVerification;
34
+ beforeEach(() => {
35
+ jest.clearAllMocks();
36
+ service = new contact_email_verification_service_1.ContactEmailVerificationService('cache-arn', 'emailable-key');
37
+ getVerification = email_verification_service_1.EmailVerificationService.mock.results.at(-1)?.value.getEmailVerificationWithCaching;
38
+ });
39
+ it('constructs an EmailVerificationService with the given cache arn + emailable key', () => {
40
+ expect(email_verification_service_1.EmailVerificationService).toHaveBeenCalledWith('cache-arn', 'emailable-key');
41
+ });
42
+ describe('verifyContactEmail', () => {
43
+ it('returns null for an invalid email and never calls the verification service', async () => {
44
+ const result = await service.verifyContactEmail(createTestContact('not-an-email'), 'not-an-email');
45
+ expect(result).toBeNull();
46
+ expect(getVerification).not.toHaveBeenCalled();
47
+ });
48
+ it('returns null for a blacklisted email and never calls the verification service', async () => {
49
+ const result = await service.verifyContactEmail(createTestContact('a@consolidated.net'), 'a@consolidated.net');
50
+ expect(result).toBeNull();
51
+ expect(getVerification).not.toHaveBeenCalled();
52
+ });
53
+ it('short-circuits a risky Yahoo email to RISKY without calling the verification service', async () => {
54
+ const result = await service.verifyContactEmail(createTestContact('a@yahoo.com'), 'a@yahoo.com');
55
+ expect(result?.state).toBe(at_tracking_event_types_1.EMAIL_STATUS.RISKY);
56
+ expect(getVerification).not.toHaveBeenCalled();
57
+ });
58
+ it('verifies a Yahoo email when forceVerify is true', async () => {
59
+ getVerification.mockResolvedValueOnce({ emailVerification: { state: at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE, email: 'a@yahoo.com' } });
60
+ const result = await service.verifyContactEmail(createTestContact('a@yahoo.com'), 'a@yahoo.com', true);
61
+ expect(getVerification).toHaveBeenCalledWith('a@yahoo.com');
62
+ expect(result?.state).toBe(at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE);
63
+ });
64
+ it('returns the verification result for a clean email', async () => {
65
+ getVerification.mockResolvedValueOnce({ emailVerification: { state: at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE, email: 'good@example.com' } });
66
+ const result = await service.verifyContactEmail(createTestContact('good@example.com'), 'good@example.com');
67
+ expect(getVerification).toHaveBeenCalledWith('good@example.com');
68
+ expect(result?.state).toBe(at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE);
69
+ });
70
+ it('returns null when the verification service yields nothing', async () => {
71
+ getVerification.mockResolvedValueOnce(undefined);
72
+ const result = await service.verifyContactEmail(createTestContact('good@example.com'), 'good@example.com');
73
+ expect(result).toBeNull();
74
+ });
75
+ });
76
+ describe('verifyContactsEmail', () => {
77
+ it('keeps verified contacts, drops failures + no-email, and does not mutate the input', async () => {
78
+ getVerification.mockImplementation(async (email) => email === 'good@example.com' ? { emailVerification: { state: at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE, email } } : undefined);
79
+ const good = createTestContact('good@example.com', 'good');
80
+ const contacts = [good, createTestContact('not-an-email', 'bad'), createTestContact(undefined, 'noemail')];
81
+ const result = await service.verifyContactsEmail(contacts);
82
+ expect(result).toHaveLength(1);
83
+ expect(result?.[0].id).toBe('good');
84
+ expect(result?.[0].emailVerification?.state).toBe(at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE);
85
+ expect(good.emailVerification).toBeUndefined();
86
+ });
87
+ });
88
+ });
89
+ //# sourceMappingURL=contact-email-verification-service.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-email-verification-service.spec.js","sourceRoot":"","sources":["../../../../../src/__tests__/services/email-verification/contact-email-verification-service.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { EmailableVerifyEmailResponse, ThirdPartyContact } from '@adtrackify/at-tracking-event-types';
2
+ export declare class ContactEmailVerificationService {
3
+ private emailVerificationService;
4
+ constructor(cacheLambdaFunctionArn: string, emailableApiKey: string);
5
+ verifyContactEmail: (contact: ThirdPartyContact, email: string, forceVerify?: boolean) => Promise<EmailableVerifyEmailResponse | null>;
6
+ verifyContactsEmail: (contacts: ThirdPartyContact[]) => Promise<ThirdPartyContact[] | null>;
7
+ }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContactEmailVerificationService = void 0;
4
+ const at_tracking_event_types_1 = require("@adtrackify/at-tracking-event-types");
5
+ const helpers_1 = require("../../helpers");
6
+ const emails_js_1 = require("../../libs/emails.js");
7
+ const email_verification_service_js_1 = require("./email-verification-service.js");
8
+ class ContactEmailVerificationService {
9
+ emailVerificationService;
10
+ constructor(cacheLambdaFunctionArn, emailableApiKey) {
11
+ this.emailVerificationService = new email_verification_service_js_1.EmailVerificationService(cacheLambdaFunctionArn, emailableApiKey);
12
+ }
13
+ verifyContactEmail = async (contact, email, forceVerify = false) => {
14
+ try {
15
+ if (!(0, emails_js_1.validateEmail)(email)) {
16
+ helpers_1.Logger.error('Contact email verification: invalid email', { contact, email });
17
+ return null;
18
+ }
19
+ if ((0, emails_js_1.isBlacklistedEmail)(email)) {
20
+ helpers_1.Logger.error('Contact email verification: blacklisted email', { contact, email });
21
+ return null;
22
+ }
23
+ if ((0, emails_js_1.isDisposableEmail)(email)) {
24
+ helpers_1.Logger.error('Contact email verification: disposable email', { contact, email });
25
+ return null;
26
+ }
27
+ if ((0, emails_js_1.isYahooEmail)(email) && !forceVerify) {
28
+ helpers_1.Logger.info('Contact email verification: risky Yahoo email — skipping Emailable', { contact, email });
29
+ return { state: at_tracking_event_types_1.EMAIL_STATUS.RISKY, email, reason: 'Yahoo email - riskier than other emails' };
30
+ }
31
+ const response = await this.emailVerificationService.getEmailVerificationWithCaching(email);
32
+ if (!response?.emailVerification) {
33
+ helpers_1.Logger.error('Contact email verification: no response from verification service', { contact, email, response });
34
+ return null;
35
+ }
36
+ helpers_1.Logger.info('Contact email verification: result', { contact, email, emailVerification: response.emailVerification });
37
+ return response.emailVerification;
38
+ }
39
+ catch (error) {
40
+ helpers_1.Logger.error('Contact email verification: failed to verify contact email', { error, email });
41
+ return null;
42
+ }
43
+ };
44
+ verifyContactsEmail = async (contacts) => {
45
+ try {
46
+ const verifiedContacts = [];
47
+ for (const contact of contacts) {
48
+ const email = contact.emailAddress;
49
+ if (!email) {
50
+ helpers_1.Logger.warn('Contact email verification: no email on contact — skipping', { contact });
51
+ continue;
52
+ }
53
+ const emailVerification = await this.verifyContactEmail(contact, email);
54
+ if (emailVerification) {
55
+ verifiedContacts.push({ ...contact, emailVerification });
56
+ }
57
+ }
58
+ return verifiedContacts;
59
+ }
60
+ catch (error) {
61
+ helpers_1.Logger.error('Contact email verification: failed to verify contact emails', { error });
62
+ return null;
63
+ }
64
+ };
65
+ }
66
+ exports.ContactEmailVerificationService = ContactEmailVerificationService;
67
+ //# sourceMappingURL=contact-email-verification-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-email-verification-service.js","sourceRoot":"","sources":["../../../../src/services/email-verification/contact-email-verification-service.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
1
  export * from './email-verification-service.js';
2
- export * from './contact-email-verifier.js';
2
+ export * from './contact-email-verification-service.js';
@@ -15,5 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./email-verification-service.js"), exports);
18
- __exportStar(require("./contact-email-verifier.js"), exports);
18
+ __exportStar(require("./contact-email-verification-service.js"), exports);
19
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/services/email-verification/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kEAAgD;AAChD,8DAA4C"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/services/email-verification/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kEAAgD;AAChD,0EAAwD"}
@@ -0,0 +1,87 @@
1
+ import { CONTACT_ACQUISITION_SOURCE, CONTACT_SOURCE_ID, EMAIL_STATUS } from '@adtrackify/at-tracking-event-types';
2
+ jest.mock('../../../services/email-verification/email-verification-service', () => ({
3
+ EmailVerificationService: jest.fn().mockImplementation(() => ({ getEmailVerificationWithCaching: jest.fn() })),
4
+ }));
5
+ import { isBlacklistedEmail } from '../../../libs/emails';
6
+ import { ContactEmailVerificationService } from '../../../services/email-verification/contact-email-verification-service';
7
+ import { EmailVerificationService } from '../../../services/email-verification/email-verification-service';
8
+ const createTestContact = (emailAddress, id = 'c1') => ({
9
+ id,
10
+ source: CONTACT_ACQUISITION_SOURCE.BDEX,
11
+ sourceId: CONTACT_SOURCE_ID.BDEX,
12
+ firstName: 'John',
13
+ lastName: 'Doe',
14
+ emailAddress,
15
+ emailStatus: EMAIL_STATUS.DELIVERABLE,
16
+ pixelId: 'px',
17
+ identityId: 'id',
18
+ sessionId: 'sess',
19
+ createdAt: '1',
20
+ updatedAt: '1',
21
+ });
22
+ describe('isBlacklistedEmail', () => {
23
+ it('flags blacklisted domains and passes clean ones', () => {
24
+ expect(isBlacklistedEmail('a@consolidated.net')).toBe(true);
25
+ expect(isBlacklistedEmail('a@mailinator.com')).toBe(true);
26
+ expect(isBlacklistedEmail('a@example.com')).toBe(false);
27
+ });
28
+ });
29
+ describe('ContactEmailVerificationService', () => {
30
+ let service;
31
+ let getVerification;
32
+ beforeEach(() => {
33
+ jest.clearAllMocks();
34
+ service = new ContactEmailVerificationService('cache-arn', 'emailable-key');
35
+ getVerification = EmailVerificationService.mock.results.at(-1)?.value.getEmailVerificationWithCaching;
36
+ });
37
+ it('constructs an EmailVerificationService with the given cache arn + emailable key', () => {
38
+ expect(EmailVerificationService).toHaveBeenCalledWith('cache-arn', 'emailable-key');
39
+ });
40
+ describe('verifyContactEmail', () => {
41
+ it('returns null for an invalid email and never calls the verification service', async () => {
42
+ const result = await service.verifyContactEmail(createTestContact('not-an-email'), 'not-an-email');
43
+ expect(result).toBeNull();
44
+ expect(getVerification).not.toHaveBeenCalled();
45
+ });
46
+ it('returns null for a blacklisted email and never calls the verification service', async () => {
47
+ const result = await service.verifyContactEmail(createTestContact('a@consolidated.net'), 'a@consolidated.net');
48
+ expect(result).toBeNull();
49
+ expect(getVerification).not.toHaveBeenCalled();
50
+ });
51
+ it('short-circuits a risky Yahoo email to RISKY without calling the verification service', async () => {
52
+ const result = await service.verifyContactEmail(createTestContact('a@yahoo.com'), 'a@yahoo.com');
53
+ expect(result?.state).toBe(EMAIL_STATUS.RISKY);
54
+ expect(getVerification).not.toHaveBeenCalled();
55
+ });
56
+ it('verifies a Yahoo email when forceVerify is true', async () => {
57
+ getVerification.mockResolvedValueOnce({ emailVerification: { state: EMAIL_STATUS.DELIVERABLE, email: 'a@yahoo.com' } });
58
+ const result = await service.verifyContactEmail(createTestContact('a@yahoo.com'), 'a@yahoo.com', true);
59
+ expect(getVerification).toHaveBeenCalledWith('a@yahoo.com');
60
+ expect(result?.state).toBe(EMAIL_STATUS.DELIVERABLE);
61
+ });
62
+ it('returns the verification result for a clean email', async () => {
63
+ getVerification.mockResolvedValueOnce({ emailVerification: { state: EMAIL_STATUS.DELIVERABLE, email: 'good@example.com' } });
64
+ const result = await service.verifyContactEmail(createTestContact('good@example.com'), 'good@example.com');
65
+ expect(getVerification).toHaveBeenCalledWith('good@example.com');
66
+ expect(result?.state).toBe(EMAIL_STATUS.DELIVERABLE);
67
+ });
68
+ it('returns null when the verification service yields nothing', async () => {
69
+ getVerification.mockResolvedValueOnce(undefined);
70
+ const result = await service.verifyContactEmail(createTestContact('good@example.com'), 'good@example.com');
71
+ expect(result).toBeNull();
72
+ });
73
+ });
74
+ describe('verifyContactsEmail', () => {
75
+ it('keeps verified contacts, drops failures + no-email, and does not mutate the input', async () => {
76
+ getVerification.mockImplementation(async (email) => email === 'good@example.com' ? { emailVerification: { state: EMAIL_STATUS.DELIVERABLE, email } } : undefined);
77
+ const good = createTestContact('good@example.com', 'good');
78
+ const contacts = [good, createTestContact('not-an-email', 'bad'), createTestContact(undefined, 'noemail')];
79
+ const result = await service.verifyContactsEmail(contacts);
80
+ expect(result).toHaveLength(1);
81
+ expect(result?.[0].id).toBe('good');
82
+ expect(result?.[0].emailVerification?.state).toBe(EMAIL_STATUS.DELIVERABLE);
83
+ expect(good.emailVerification).toBeUndefined();
84
+ });
85
+ });
86
+ });
87
+ //# sourceMappingURL=contact-email-verification-service.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-email-verification-service.spec.js","sourceRoot":"","sources":["../../../../../src/__tests__/services/email-verification/contact-email-verification-service.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { EmailableVerifyEmailResponse, ThirdPartyContact } from '@adtrackify/at-tracking-event-types';
2
+ export declare class ContactEmailVerificationService {
3
+ private emailVerificationService;
4
+ constructor(cacheLambdaFunctionArn: string, emailableApiKey: string);
5
+ verifyContactEmail: (contact: ThirdPartyContact, email: string, forceVerify?: boolean) => Promise<EmailableVerifyEmailResponse | null>;
6
+ verifyContactsEmail: (contacts: ThirdPartyContact[]) => Promise<ThirdPartyContact[] | null>;
7
+ }
@@ -0,0 +1,63 @@
1
+ import { EMAIL_STATUS } from '@adtrackify/at-tracking-event-types';
2
+ import { Logger } from '../../helpers';
3
+ import { isBlacklistedEmail, isDisposableEmail, isYahooEmail, validateEmail } from '../../libs/emails.js';
4
+ import { EmailVerificationService } from './email-verification-service.js';
5
+ export class ContactEmailVerificationService {
6
+ emailVerificationService;
7
+ constructor(cacheLambdaFunctionArn, emailableApiKey) {
8
+ this.emailVerificationService = new EmailVerificationService(cacheLambdaFunctionArn, emailableApiKey);
9
+ }
10
+ verifyContactEmail = async (contact, email, forceVerify = false) => {
11
+ try {
12
+ if (!validateEmail(email)) {
13
+ Logger.error('Contact email verification: invalid email', { contact, email });
14
+ return null;
15
+ }
16
+ if (isBlacklistedEmail(email)) {
17
+ Logger.error('Contact email verification: blacklisted email', { contact, email });
18
+ return null;
19
+ }
20
+ if (isDisposableEmail(email)) {
21
+ Logger.error('Contact email verification: disposable email', { contact, email });
22
+ return null;
23
+ }
24
+ if (isYahooEmail(email) && !forceVerify) {
25
+ Logger.info('Contact email verification: risky Yahoo email — skipping Emailable', { contact, email });
26
+ return { state: EMAIL_STATUS.RISKY, email, reason: 'Yahoo email - riskier than other emails' };
27
+ }
28
+ const response = await this.emailVerificationService.getEmailVerificationWithCaching(email);
29
+ if (!response?.emailVerification) {
30
+ Logger.error('Contact email verification: no response from verification service', { contact, email, response });
31
+ return null;
32
+ }
33
+ Logger.info('Contact email verification: result', { contact, email, emailVerification: response.emailVerification });
34
+ return response.emailVerification;
35
+ }
36
+ catch (error) {
37
+ Logger.error('Contact email verification: failed to verify contact email', { error, email });
38
+ return null;
39
+ }
40
+ };
41
+ verifyContactsEmail = async (contacts) => {
42
+ try {
43
+ const verifiedContacts = [];
44
+ for (const contact of contacts) {
45
+ const email = contact.emailAddress;
46
+ if (!email) {
47
+ Logger.warn('Contact email verification: no email on contact — skipping', { contact });
48
+ continue;
49
+ }
50
+ const emailVerification = await this.verifyContactEmail(contact, email);
51
+ if (emailVerification) {
52
+ verifiedContacts.push({ ...contact, emailVerification });
53
+ }
54
+ }
55
+ return verifiedContacts;
56
+ }
57
+ catch (error) {
58
+ Logger.error('Contact email verification: failed to verify contact emails', { error });
59
+ return null;
60
+ }
61
+ };
62
+ }
63
+ //# sourceMappingURL=contact-email-verification-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-email-verification-service.js","sourceRoot":"","sources":["../../../../src/services/email-verification/contact-email-verification-service.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
1
  export * from './email-verification-service.js';
2
- export * from './contact-email-verifier.js';
2
+ export * from './contact-email-verification-service.js';
@@ -1,3 +1,3 @@
1
1
  export * from './email-verification-service.js';
2
- export * from './contact-email-verifier.js';
2
+ export * from './contact-email-verification-service.js';
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/services/email-verification/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/services/email-verification/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adtrackify/at-service-common",
3
- "version": "3.18.15",
3
+ "version": "3.18.16",
4
4
  "description": "",
5
5
  "files": [
6
6
  "dist/*"
@@ -1,77 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const at_tracking_event_types_1 = require("@adtrackify/at-tracking-event-types");
4
- const emails_1 = require("../../../libs/emails");
5
- const contact_email_verifier_1 = require("../../../services/email-verification/contact-email-verifier");
6
- const createTestContact = (emailAddress, id = 'c1') => ({
7
- id,
8
- source: at_tracking_event_types_1.CONTACT_ACQUISITION_SOURCE.BDEX,
9
- sourceId: at_tracking_event_types_1.CONTACT_SOURCE_ID.BDEX,
10
- firstName: 'John',
11
- lastName: 'Doe',
12
- emailAddress,
13
- emailStatus: at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE,
14
- pixelId: 'px',
15
- identityId: 'id',
16
- sessionId: 'sess',
17
- createdAt: '1',
18
- updatedAt: '1',
19
- });
20
- const buildService = (impl) => ({ getEmailVerificationWithCaching: impl ?? jest.fn() });
21
- describe('isBlacklistedEmail', () => {
22
- it('flags blacklisted domains and passes clean ones', () => {
23
- expect((0, emails_1.isBlacklistedEmail)('a@consolidated.net')).toBe(true);
24
- expect((0, emails_1.isBlacklistedEmail)('a@mailinator.com')).toBe(true);
25
- expect((0, emails_1.isBlacklistedEmail)('a@example.com')).toBe(false);
26
- });
27
- });
28
- describe('verifyContactEmail', () => {
29
- it('returns null for an invalid email and never calls the service', async () => {
30
- const verify = jest.fn();
31
- const result = await (0, contact_email_verifier_1.verifyContactEmail)(createTestContact('not-an-email'), 'not-an-email', buildService(verify));
32
- expect(result).toBeNull();
33
- expect(verify).not.toHaveBeenCalled();
34
- });
35
- it('returns null for a blacklisted email and never calls the service', async () => {
36
- const verify = jest.fn();
37
- const result = await (0, contact_email_verifier_1.verifyContactEmail)(createTestContact('a@consolidated.net'), 'a@consolidated.net', buildService(verify));
38
- expect(result).toBeNull();
39
- expect(verify).not.toHaveBeenCalled();
40
- });
41
- it('short-circuits a risky Yahoo email to RISKY without calling the service', async () => {
42
- const verify = jest.fn();
43
- const result = await (0, contact_email_verifier_1.verifyContactEmail)(createTestContact('a@yahoo.com'), 'a@yahoo.com', buildService(verify));
44
- expect(result?.state).toBe(at_tracking_event_types_1.EMAIL_STATUS.RISKY);
45
- expect(verify).not.toHaveBeenCalled();
46
- });
47
- it('verifies a Yahoo email via the service when forceVerify is true', async () => {
48
- const verify = jest.fn().mockResolvedValue({ emailVerification: { state: at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE, email: 'a@yahoo.com' } });
49
- const result = await (0, contact_email_verifier_1.verifyContactEmail)(createTestContact('a@yahoo.com'), 'a@yahoo.com', buildService(verify), true);
50
- expect(verify).toHaveBeenCalledWith('a@yahoo.com');
51
- expect(result?.state).toBe(at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE);
52
- });
53
- it('returns the verification result for a clean email', async () => {
54
- const verify = jest.fn().mockResolvedValue({ emailVerification: { state: at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE, email: 'good@example.com' } });
55
- const result = await (0, contact_email_verifier_1.verifyContactEmail)(createTestContact('good@example.com'), 'good@example.com', buildService(verify));
56
- expect(verify).toHaveBeenCalledWith('good@example.com');
57
- expect(result?.state).toBe(at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE);
58
- });
59
- it('returns null when the service yields no verification', async () => {
60
- const verify = jest.fn().mockResolvedValue(undefined);
61
- const result = await (0, contact_email_verifier_1.verifyContactEmail)(createTestContact('good@example.com'), 'good@example.com', buildService(verify));
62
- expect(result).toBeNull();
63
- });
64
- });
65
- describe('verifyContactsEmail', () => {
66
- it('keeps verified contacts, drops failures + no-email, and does not mutate the input', async () => {
67
- const verify = jest.fn(async (email) => email === 'good@example.com' ? { emailVerification: { state: at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE, email } } : undefined);
68
- const good = createTestContact('good@example.com', 'good');
69
- const contacts = [good, createTestContact('not-an-email', 'bad'), createTestContact(undefined, 'noemail')];
70
- const result = await (0, contact_email_verifier_1.verifyContactsEmail)(contacts, buildService(verify));
71
- expect(result).toHaveLength(1);
72
- expect(result?.[0].id).toBe('good');
73
- expect(result?.[0].emailVerification?.state).toBe(at_tracking_event_types_1.EMAIL_STATUS.DELIVERABLE);
74
- expect(good.emailVerification).toBeUndefined();
75
- });
76
- });
77
- //# sourceMappingURL=contact-email-verifier.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contact-email-verifier.spec.js","sourceRoot":"","sources":["../../../../../src/__tests__/services/email-verification/contact-email-verifier.spec.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- import { EmailableVerifyEmailResponse, ThirdPartyContact } from '@adtrackify/at-tracking-event-types';
2
- import type { EmailVerificationService } from './email-verification-service.js';
3
- export declare const verifyContactEmail: (contact: ThirdPartyContact, email: string, emailVerificationService: EmailVerificationService, forceVerify?: boolean) => Promise<EmailableVerifyEmailResponse | null>;
4
- export declare const verifyContactsEmail: (contacts: ThirdPartyContact[], emailVerificationService: EmailVerificationService) => Promise<ThirdPartyContact[] | null>;
@@ -1,61 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.verifyContactsEmail = exports.verifyContactEmail = void 0;
4
- const at_tracking_event_types_1 = require("@adtrackify/at-tracking-event-types");
5
- const helpers_1 = require("../../helpers");
6
- const emails_js_1 = require("../../libs/emails.js");
7
- const verifyContactEmail = async (contact, email, emailVerificationService, forceVerify = false) => {
8
- try {
9
- if (!(0, emails_js_1.validateEmail)(email)) {
10
- helpers_1.Logger.error('Email verification: invalid email', { contact, email });
11
- return null;
12
- }
13
- if ((0, emails_js_1.isBlacklistedEmail)(email)) {
14
- helpers_1.Logger.error('Email verification: blacklisted email', { contact, email });
15
- return null;
16
- }
17
- if ((0, emails_js_1.isDisposableEmail)(email)) {
18
- helpers_1.Logger.error('Email verification: disposable email', { contact, email });
19
- return null;
20
- }
21
- if ((0, emails_js_1.isYahooEmail)(email) && !forceVerify) {
22
- helpers_1.Logger.info('Email verification: risky Yahoo email — skipping Emailable', { contact, email });
23
- return { state: at_tracking_event_types_1.EMAIL_STATUS.RISKY, email, reason: 'Yahoo email - riskier than other emails' };
24
- }
25
- const response = await emailVerificationService.getEmailVerificationWithCaching(email);
26
- if (!response?.emailVerification) {
27
- helpers_1.Logger.error('Email verification: no response from verification service', { contact, email, response });
28
- return null;
29
- }
30
- helpers_1.Logger.info('Email verification: result', { contact, email, emailVerification: response.emailVerification });
31
- return response.emailVerification;
32
- }
33
- catch (error) {
34
- helpers_1.Logger.error('Email verification: failed to verify contact email', { error, email });
35
- return null;
36
- }
37
- };
38
- exports.verifyContactEmail = verifyContactEmail;
39
- const verifyContactsEmail = async (contacts, emailVerificationService) => {
40
- try {
41
- const verifiedContacts = [];
42
- for (const contact of contacts) {
43
- const email = contact.emailAddress;
44
- if (!email) {
45
- helpers_1.Logger.warn('Email verification: no email on contact — skipping', { contact });
46
- continue;
47
- }
48
- const emailVerification = await (0, exports.verifyContactEmail)(contact, email, emailVerificationService);
49
- if (emailVerification) {
50
- verifiedContacts.push({ ...contact, emailVerification });
51
- }
52
- }
53
- return verifiedContacts;
54
- }
55
- catch (error) {
56
- helpers_1.Logger.error('Email verification: failed to verify contact emails', { error });
57
- return null;
58
- }
59
- };
60
- exports.verifyContactsEmail = verifyContactsEmail;
61
- //# sourceMappingURL=contact-email-verifier.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contact-email-verifier.js","sourceRoot":"","sources":["../../../../src/services/email-verification/contact-email-verifier.ts"],"names":[],"mappings":";;;AAAA,iFAAoH;AAEpH,2CAAuC;AACvC,oDAA0G;AAInG,MAAM,kBAAkB,GAAG,KAAK,EACrC,OAA0B,EAC1B,KAAa,EACb,wBAAkD,EAClD,WAAW,GAAG,KAAK,EAC2B,EAAE;IAChD,IAAI;QACF,IAAI,CAAC,IAAA,yBAAa,EAAC,KAAK,CAAC,EAAE;YACzB,gBAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACtE,OAAO,IAAI,CAAC;SACb;QACD,IAAI,IAAA,8BAAkB,EAAC,KAAK,CAAC,EAAE;YAC7B,gBAAM,CAAC,KAAK,CAAC,uCAAuC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1E,OAAO,IAAI,CAAC;SACb;QACD,IAAI,IAAA,6BAAiB,EAAC,KAAK,CAAC,EAAE;YAC5B,gBAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACzE,OAAO,IAAI,CAAC;SACb;QACD,IAAI,IAAA,wBAAY,EAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE;YACvC,gBAAM,CAAC,IAAI,CAAC,4DAA4D,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9F,OAAO,EAAE,KAAK,EAAE,sCAAY,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,yCAAyC,EAAkC,CAAC;SAChI;QAED,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAAC,+BAA+B,CAAC,KAAK,CAAC,CAAC;QACvF,IAAI,CAAC,QAAQ,EAAE,iBAAiB,EAAE;YAChC,gBAAM,CAAC,KAAK,CAAC,2DAA2D,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACxG,OAAO,IAAI,CAAC;SACb;QACD,gBAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAC7G,OAAO,QAAQ,CAAC,iBAAiB,CAAC;KACnC;IAAC,OAAO,KAAK,EAAE;QACd,gBAAM,CAAC,KAAK,CAAC,oDAAoD,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC;KACb;AACH,CAAC,CAAC;AAnCW,QAAA,kBAAkB,sBAmC7B;AAGK,MAAM,mBAAmB,GAAG,KAAK,EACtC,QAA6B,EAC7B,wBAAkD,EACb,EAAE;IACvC,IAAI;QACF,MAAM,gBAAgB,GAAwB,EAAE,CAAC;QACjD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;YAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC;YACnC,IAAI,CAAC,KAAK,EAAE;gBACV,gBAAM,CAAC,IAAI,CAAC,oDAAoD,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC/E,SAAS;aACV;YACD,MAAM,iBAAiB,GAAG,MAAM,IAAA,0BAAkB,EAAC,OAAO,EAAE,KAAK,EAAE,wBAAwB,CAAC,CAAC;YAC7F,IAAI,iBAAiB,EAAE;gBACrB,gBAAgB,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;aAC1D;SACF;QACD,OAAO,gBAAgB,CAAC;KACzB;IAAC,OAAO,KAAK,EAAE;QACd,gBAAM,CAAC,KAAK,CAAC,qDAAqD,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC;KACb;AACH,CAAC,CAAC;AAtBW,QAAA,mBAAmB,uBAsB9B"}
@@ -1,75 +0,0 @@
1
- import { CONTACT_ACQUISITION_SOURCE, CONTACT_SOURCE_ID, EMAIL_STATUS } from '@adtrackify/at-tracking-event-types';
2
- import { isBlacklistedEmail } from '../../../libs/emails';
3
- import { verifyContactEmail, verifyContactsEmail } from '../../../services/email-verification/contact-email-verifier';
4
- const createTestContact = (emailAddress, id = 'c1') => ({
5
- id,
6
- source: CONTACT_ACQUISITION_SOURCE.BDEX,
7
- sourceId: CONTACT_SOURCE_ID.BDEX,
8
- firstName: 'John',
9
- lastName: 'Doe',
10
- emailAddress,
11
- emailStatus: EMAIL_STATUS.DELIVERABLE,
12
- pixelId: 'px',
13
- identityId: 'id',
14
- sessionId: 'sess',
15
- createdAt: '1',
16
- updatedAt: '1',
17
- });
18
- const buildService = (impl) => ({ getEmailVerificationWithCaching: impl ?? jest.fn() });
19
- describe('isBlacklistedEmail', () => {
20
- it('flags blacklisted domains and passes clean ones', () => {
21
- expect(isBlacklistedEmail('a@consolidated.net')).toBe(true);
22
- expect(isBlacklistedEmail('a@mailinator.com')).toBe(true);
23
- expect(isBlacklistedEmail('a@example.com')).toBe(false);
24
- });
25
- });
26
- describe('verifyContactEmail', () => {
27
- it('returns null for an invalid email and never calls the service', async () => {
28
- const verify = jest.fn();
29
- const result = await verifyContactEmail(createTestContact('not-an-email'), 'not-an-email', buildService(verify));
30
- expect(result).toBeNull();
31
- expect(verify).not.toHaveBeenCalled();
32
- });
33
- it('returns null for a blacklisted email and never calls the service', async () => {
34
- const verify = jest.fn();
35
- const result = await verifyContactEmail(createTestContact('a@consolidated.net'), 'a@consolidated.net', buildService(verify));
36
- expect(result).toBeNull();
37
- expect(verify).not.toHaveBeenCalled();
38
- });
39
- it('short-circuits a risky Yahoo email to RISKY without calling the service', async () => {
40
- const verify = jest.fn();
41
- const result = await verifyContactEmail(createTestContact('a@yahoo.com'), 'a@yahoo.com', buildService(verify));
42
- expect(result?.state).toBe(EMAIL_STATUS.RISKY);
43
- expect(verify).not.toHaveBeenCalled();
44
- });
45
- it('verifies a Yahoo email via the service when forceVerify is true', async () => {
46
- const verify = jest.fn().mockResolvedValue({ emailVerification: { state: EMAIL_STATUS.DELIVERABLE, email: 'a@yahoo.com' } });
47
- const result = await verifyContactEmail(createTestContact('a@yahoo.com'), 'a@yahoo.com', buildService(verify), true);
48
- expect(verify).toHaveBeenCalledWith('a@yahoo.com');
49
- expect(result?.state).toBe(EMAIL_STATUS.DELIVERABLE);
50
- });
51
- it('returns the verification result for a clean email', async () => {
52
- const verify = jest.fn().mockResolvedValue({ emailVerification: { state: EMAIL_STATUS.DELIVERABLE, email: 'good@example.com' } });
53
- const result = await verifyContactEmail(createTestContact('good@example.com'), 'good@example.com', buildService(verify));
54
- expect(verify).toHaveBeenCalledWith('good@example.com');
55
- expect(result?.state).toBe(EMAIL_STATUS.DELIVERABLE);
56
- });
57
- it('returns null when the service yields no verification', async () => {
58
- const verify = jest.fn().mockResolvedValue(undefined);
59
- const result = await verifyContactEmail(createTestContact('good@example.com'), 'good@example.com', buildService(verify));
60
- expect(result).toBeNull();
61
- });
62
- });
63
- describe('verifyContactsEmail', () => {
64
- it('keeps verified contacts, drops failures + no-email, and does not mutate the input', async () => {
65
- const verify = jest.fn(async (email) => email === 'good@example.com' ? { emailVerification: { state: EMAIL_STATUS.DELIVERABLE, email } } : undefined);
66
- const good = createTestContact('good@example.com', 'good');
67
- const contacts = [good, createTestContact('not-an-email', 'bad'), createTestContact(undefined, 'noemail')];
68
- const result = await verifyContactsEmail(contacts, buildService(verify));
69
- expect(result).toHaveLength(1);
70
- expect(result?.[0].id).toBe('good');
71
- expect(result?.[0].emailVerification?.state).toBe(EMAIL_STATUS.DELIVERABLE);
72
- expect(good.emailVerification).toBeUndefined();
73
- });
74
- });
75
- //# sourceMappingURL=contact-email-verifier.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contact-email-verifier.spec.js","sourceRoot":"","sources":["../../../../../src/__tests__/services/email-verification/contact-email-verifier.spec.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- import { EmailableVerifyEmailResponse, ThirdPartyContact } from '@adtrackify/at-tracking-event-types';
2
- import type { EmailVerificationService } from './email-verification-service.js';
3
- export declare const verifyContactEmail: (contact: ThirdPartyContact, email: string, emailVerificationService: EmailVerificationService, forceVerify?: boolean) => Promise<EmailableVerifyEmailResponse | null>;
4
- export declare const verifyContactsEmail: (contacts: ThirdPartyContact[], emailVerificationService: EmailVerificationService) => Promise<ThirdPartyContact[] | null>;
@@ -1,56 +0,0 @@
1
- import { EMAIL_STATUS } from '@adtrackify/at-tracking-event-types';
2
- import { Logger } from '../../helpers';
3
- import { isBlacklistedEmail, isDisposableEmail, isYahooEmail, validateEmail } from '../../libs/emails.js';
4
- export const verifyContactEmail = async (contact, email, emailVerificationService, forceVerify = false) => {
5
- try {
6
- if (!validateEmail(email)) {
7
- Logger.error('Email verification: invalid email', { contact, email });
8
- return null;
9
- }
10
- if (isBlacklistedEmail(email)) {
11
- Logger.error('Email verification: blacklisted email', { contact, email });
12
- return null;
13
- }
14
- if (isDisposableEmail(email)) {
15
- Logger.error('Email verification: disposable email', { contact, email });
16
- return null;
17
- }
18
- if (isYahooEmail(email) && !forceVerify) {
19
- Logger.info('Email verification: risky Yahoo email — skipping Emailable', { contact, email });
20
- return { state: EMAIL_STATUS.RISKY, email, reason: 'Yahoo email - riskier than other emails' };
21
- }
22
- const response = await emailVerificationService.getEmailVerificationWithCaching(email);
23
- if (!response?.emailVerification) {
24
- Logger.error('Email verification: no response from verification service', { contact, email, response });
25
- return null;
26
- }
27
- Logger.info('Email verification: result', { contact, email, emailVerification: response.emailVerification });
28
- return response.emailVerification;
29
- }
30
- catch (error) {
31
- Logger.error('Email verification: failed to verify contact email', { error, email });
32
- return null;
33
- }
34
- };
35
- export const verifyContactsEmail = async (contacts, emailVerificationService) => {
36
- try {
37
- const verifiedContacts = [];
38
- for (const contact of contacts) {
39
- const email = contact.emailAddress;
40
- if (!email) {
41
- Logger.warn('Email verification: no email on contact — skipping', { contact });
42
- continue;
43
- }
44
- const emailVerification = await verifyContactEmail(contact, email, emailVerificationService);
45
- if (emailVerification) {
46
- verifiedContacts.push({ ...contact, emailVerification });
47
- }
48
- }
49
- return verifiedContacts;
50
- }
51
- catch (error) {
52
- Logger.error('Email verification: failed to verify contact emails', { error });
53
- return null;
54
- }
55
- };
56
- //# sourceMappingURL=contact-email-verifier.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contact-email-verifier.js","sourceRoot":"","sources":["../../../../src/services/email-verification/contact-email-verifier.ts"],"names":[],"mappings":"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"}