mailgun.js 3.7.3 → 4.1.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +2 -2
  3. package/dist/lib/client.d.ts +0 -4
  4. package/dist/lib/domains.d.ts +19 -13
  5. package/dist/lib/domainsCredentials.d.ts +14 -0
  6. package/dist/lib/events.d.ts +3 -3
  7. package/dist/lib/interfaces/DomainCredentials.d.ts +52 -0
  8. package/dist/lib/interfaces/DomainTracking.d.ts +4 -4
  9. package/dist/lib/interfaces/Domains.d.ts +53 -3
  10. package/dist/lib/interfaces/Events.d.ts +66 -2
  11. package/dist/lib/interfaces/MultipleValidation.d.ts +55 -0
  12. package/dist/lib/interfaces/Supressions.d.ts +6 -0
  13. package/dist/lib/interfaces/Validate.d.ts +12 -0
  14. package/dist/lib/interfaces/Webhooks.d.ts +5 -1
  15. package/dist/lib/multipleValidation.d.ts +10 -0
  16. package/dist/lib/parse.d.ts +0 -6
  17. package/dist/lib/request.d.ts +5 -1
  18. package/dist/lib/suppressions.d.ts +12 -3
  19. package/dist/lib/validate.d.ts +5 -2
  20. package/dist/lib/webhooks.d.ts +3 -3
  21. package/dist/mailgun.node.js +2 -2
  22. package/dist/mailgun.node.js.LICENSE.txt +1 -1
  23. package/dist/mailgun.web.js +2 -2
  24. package/dist/mailgun.web.js.LICENSE.txt +1 -1
  25. package/lib/client.ts +6 -12
  26. package/lib/domains.ts +82 -26
  27. package/lib/domainsCredentials.ts +88 -0
  28. package/lib/events.ts +6 -6
  29. package/lib/interfaces/DomainCredentials.ts +68 -0
  30. package/lib/interfaces/DomainTracking.ts +4 -4
  31. package/lib/interfaces/Domains.ts +65 -4
  32. package/lib/interfaces/Events.ts +66 -2
  33. package/lib/interfaces/MultipleValidation.ts +62 -0
  34. package/lib/interfaces/Supressions.ts +7 -0
  35. package/lib/interfaces/Validate.ts +15 -0
  36. package/lib/interfaces/Webhooks.ts +6 -1
  37. package/lib/ip-pools.ts +2 -2
  38. package/lib/multipleValidation.ts +37 -0
  39. package/lib/request.ts +86 -34
  40. package/lib/suppressions.ts +36 -5
  41. package/lib/validate.ts +10 -4
  42. package/lib/webhooks.ts +19 -10
  43. package/package.json +1 -1
  44. package/test/client.test.ts +21 -5
  45. package/test/data/emailsValidation1.csv +3 -0
  46. package/test/domains.test.ts +118 -15
  47. package/test/domainsCredentials.test.ts +97 -0
  48. package/test/events.test.ts +15 -24
  49. package/test/multipleValidation.test.ts +159 -0
  50. package/test/validate.test.ts +7 -4
  51. package/test/webhooks.test.ts +6 -6
  52. package/webpack/webpack.dev.config.js +10 -0
  53. package/lib/parse.ts +0 -27
  54. package/test/parse.test.ts +0 -75
@@ -0,0 +1,62 @@
1
+ /* eslint-disable camelcase */
2
+ export interface MultipleValidationJob {
3
+ created_at: number;
4
+ download_url: {
5
+ csv: string;
6
+ json: string;
7
+ };
8
+ id: string;
9
+ quantity: number;
10
+ records_processed: number;
11
+ status: string;
12
+ summary: {
13
+ result: {
14
+ catch_all: number;
15
+ deliverable: number;
16
+ do_not_send: number;
17
+ undeliverable: number;
18
+ unknown: number;
19
+ };
20
+ risk: {
21
+ high: number;
22
+ low: number;
23
+ medium: number;
24
+ unknown: number;
25
+ }
26
+ }
27
+ }
28
+
29
+ export interface CreatedMultipleValidationJob {
30
+ id: string;
31
+ message: string;
32
+ }
33
+
34
+ export interface PagesList {
35
+ prev: string;
36
+ first: string;
37
+ last: string;
38
+ next: string;
39
+ }
40
+
41
+ export interface MultipleValidationJobsListResult {
42
+ jobs: MultipleValidationJob[];
43
+ paging: PagesList;
44
+ total: number;
45
+ }
46
+
47
+ export interface MultipleValidationJobsListResponse {
48
+ status: 200;
49
+ body: MultipleValidationJobsListResult
50
+ }
51
+
52
+ export interface CanceledMultipleValidationJob {
53
+ body: string;
54
+ status: number;
55
+ }
56
+
57
+ export interface IMultipleValidationClient {
58
+ list() : Promise<MultipleValidationJobsListResult>
59
+ get(listId: string) : Promise<MultipleValidationJob>
60
+ create(listId: string, file: any) : Promise<CreatedMultipleValidationJob>
61
+ destroy(listId: string) : Promise<CanceledMultipleValidationJob>
62
+ }
@@ -16,3 +16,10 @@ export interface UnsubscribeData {
16
16
  tags: any;
17
17
  created_at: string | Date;
18
18
  }
19
+
20
+ export interface WhiteListData {
21
+ type: string;
22
+ value: string;
23
+ reason: string;
24
+ createdAt: string | Date;
25
+ }
@@ -0,0 +1,15 @@
1
+ /* eslint-disable camelcase */
2
+
3
+ export interface ValidationResult {
4
+ address: string;
5
+ is_disposable_address: boolean;
6
+ is_role_address: boolean;
7
+ reason: string[];
8
+ result: string;
9
+ risk: string;
10
+ }
11
+
12
+ export interface ValidationResponse {
13
+ status: number;
14
+ body: ValidationResult;
15
+ }
@@ -9,7 +9,7 @@ export interface WebhookResponseBody {
9
9
  }
10
10
 
11
11
  export interface WebhookResponse {
12
- status: string;
12
+ status: number;
13
13
  body: WebhookResponseBody;
14
14
  }
15
15
 
@@ -23,3 +23,8 @@ export interface WebhooksQuery {
23
23
  limit?: number;
24
24
  skip?: number;
25
25
  }
26
+
27
+ export interface ValidationResponse {
28
+ code: number;
29
+ message: string;
30
+ }
package/lib/ip-pools.ts CHANGED
@@ -16,12 +16,12 @@ export default class IpPoolsClient {
16
16
  }
17
17
 
18
18
  create(data: { name: string, description?: string, ips?: string[] }) {
19
- return this.request.post('/v1/ip_pools', data)
19
+ return this.request.postWithFD('/v1/ip_pools', data)
20
20
  .then((response: { body: { message: string, pool_id: string } }) => response?.body);
21
21
  }
22
22
 
23
23
  update(poolId: string, data: IpPoolUpdateData) : Promise<any> {
24
- return this.request.patch(`/v1/ip_pools/${poolId}`, data)
24
+ return this.request.patchWithFD(`/v1/ip_pools/${poolId}`, data)
25
25
  .then((response: { body: any }) => response?.body);
26
26
  }
27
27
 
@@ -0,0 +1,37 @@
1
+ import {
2
+ CanceledMultipleValidationJob,
3
+ CreatedMultipleValidationJob,
4
+ IMultipleValidationClient,
5
+ MultipleValidationJob,
6
+ MultipleValidationJobsListResult
7
+ }
8
+ from './interfaces/MultipleValidation';
9
+ import Request from './request';
10
+
11
+ export default class MultipleValidationClient implements IMultipleValidationClient {
12
+ request: Request;
13
+
14
+ constructor(request: Request) {
15
+ this.request = request;
16
+ }
17
+
18
+ list(): Promise<MultipleValidationJobsListResult> {
19
+ return this.request.get('/v4/address/validate/bulk')
20
+ .then((response) => response.body as MultipleValidationJobsListResult);
21
+ }
22
+
23
+ get(listId: string): Promise<MultipleValidationJob> {
24
+ return this.request.get(`/v4/address/validate/bulk/${listId}`)
25
+ .then((response) => response.body);
26
+ }
27
+
28
+ create(listId: string, file: any): Promise<CreatedMultipleValidationJob> {
29
+ return this.request.postWithFD(`/v4/address/validate/bulk/${listId}`, file)
30
+ .then((response) => response.body);
31
+ }
32
+
33
+ destroy(listId: string): Promise<CanceledMultipleValidationJob> {
34
+ return this.request.delete(`/v4/address/validate/bulk/${listId}`)
35
+ .then((response) => response);
36
+ }
37
+ }
package/lib/request.ts CHANGED
@@ -50,7 +50,7 @@ class Request {
50
50
  private url: string;
51
51
  private timeout: number;
52
52
  private headers: any;
53
- private formData: InputFormData;
53
+ private FormDataConstructor: InputFormData;
54
54
 
55
55
  constructor(options: RequestOptions, formData: InputFormData) {
56
56
  this.username = options.username;
@@ -58,7 +58,7 @@ class Request {
58
58
  this.url = options.url as string;
59
59
  this.timeout = options.timeout;
60
60
  this.headers = options.headers || {};
61
- this.formData = formData;
61
+ this.FormDataConstructor = formData;
62
62
  }
63
63
 
64
64
  async request(method: string, url: string, inputOptions?: any): Promise<APIResponse> {
@@ -107,10 +107,12 @@ class Request {
107
107
  } as APIErrorOptions);
108
108
  }
109
109
 
110
- return {
110
+ const res = {
111
111
  body: await response?.json(),
112
112
  status: response?.status
113
113
  };
114
+
115
+ return res;
114
116
  }
115
117
 
116
118
  query(method: string, url: string, query: any, options?: any) : Promise<APIResponse> {
@@ -142,6 +144,9 @@ class Request {
142
144
  }
143
145
 
144
146
  postWithFD(url: string, data: any): Promise<APIResponse> {
147
+ if (!data) {
148
+ throw new Error('Please provide data object');
149
+ }
145
150
  const params: any = {
146
151
  headers: { 'Content-Type': null }
147
152
  };
@@ -150,6 +155,9 @@ class Request {
150
155
  }
151
156
 
152
157
  putWithFD(url: string, data: any): Promise<APIResponse> {
158
+ if (!data) {
159
+ throw new Error('Please provide data object');
160
+ }
153
161
  const params: any = {
154
162
  headers: { 'Content-Type': null }
155
163
  };
@@ -157,50 +165,94 @@ class Request {
157
165
  return this.command('put', url, formData, params);
158
166
  }
159
167
 
168
+ patchWithFD(url: string, data: any): Promise<APIResponse> {
169
+ if (!data) {
170
+ throw new Error('Please provide data object');
171
+ }
172
+ const params: any = {
173
+ headers: { 'Content-Type': null }
174
+ };
175
+ const formData = this.createFormData(data);
176
+ return this.command('patch', url, formData, params);
177
+ }
178
+
160
179
  createFormData(data: any): NodeFormData | FormData {
180
+ const formData: NodeFormData | FormData = Object.keys(data)
181
+ .filter(function (key) { return data[key]; })
182
+ .reduce((formDataAcc: NodeFormData | FormData, key) => {
183
+ const fileKeys = ['attachment', 'inline', 'file'];
184
+ if (fileKeys.includes(key)) {
185
+ this.addFilesToFD(key, data[key], formDataAcc);
186
+ return formDataAcc;
187
+ }
188
+
189
+ if (key === 'message') { // mime message
190
+ this.addMimeDataToFD(key, data[key], formDataAcc);
191
+ return formDataAcc;
192
+ }
193
+
194
+ this.addCommonPropertyToFD(key, data[key], formDataAcc);
195
+ return formDataAcc;
196
+ }, new this.FormDataConstructor());
197
+ return formData;
198
+ }
199
+
200
+ private addMimeDataToFD(
201
+ key: string,
202
+ data: Buffer | Blob,
203
+ formDataInstance: NodeFormData | FormData
204
+ ): void {
205
+ if (isNodeFormData(formDataInstance)) {
206
+ if (Buffer.isBuffer(data)) {
207
+ formDataInstance.append(key, data, { filename: 'MimeMessage' });
208
+ }
209
+ } else {
210
+ formDataInstance.append(key, data as Blob, 'MimeMessage');
211
+ }
212
+ }
213
+
214
+ private addFilesToFD(
215
+ propertyName: string,
216
+ value: any,
217
+ formDataInstance: NodeFormData | FormData
218
+ ): void {
161
219
  const appendFileToFD = (
162
220
  key: string,
163
221
  obj: any,
164
- formDataInstance: NodeFormData | FormData
222
+ formData: NodeFormData | FormData
165
223
  ): void => {
166
224
  const isStreamData = isStream(obj);
167
225
  const objData = isStreamData ? obj : obj.data;
226
+ // getAttachmentOptions should be called with obj parameter to prevent loosing filename
168
227
  const options = getAttachmentOptions(obj);
169
- if (isNodeFormData(formDataInstance)) {
170
- formDataInstance.append(key, objData, options);
228
+ if (isNodeFormData(formData)) {
229
+ formData.append(key, objData, options);
171
230
  return;
172
231
  }
173
- formDataInstance.append(key, objData, options.filename);
232
+ formData.append(key, objData, options.filename);
174
233
  };
175
234
 
176
- const formData: NodeFormData | FormData = Object.keys(data)
177
- .filter(function (key) { return data[key]; })
178
- .reduce((formDataAcc: NodeFormData | FormData, key) => {
179
- if (key === 'attachment' || key === 'inline') {
180
- const obj = data[key];
181
-
182
- if (Array.isArray(obj)) {
183
- obj.forEach(function (item) {
184
- appendFileToFD(key, item, formDataAcc);
185
- });
186
- } else {
187
- appendFileToFD(key, obj, formDataAcc);
188
- }
189
-
190
- return formDataAcc;
191
- }
235
+ if (Array.isArray(value)) {
236
+ value.forEach(function (item) {
237
+ appendFileToFD(propertyName, item, formDataInstance);
238
+ });
239
+ } else {
240
+ appendFileToFD(propertyName, value, formDataInstance);
241
+ }
242
+ }
192
243
 
193
- if (Array.isArray(data[key])) {
194
- data[key].forEach(function (item: any) {
195
- formDataAcc.append(key, item);
196
- });
197
- } else if (data[key] != null) {
198
- formDataAcc.append(key, data[key]);
199
- }
200
- return formDataAcc;
201
- // eslint-disable-next-line new-cap
202
- }, new this.formData());
203
- return formData;
244
+ private addCommonPropertyToFD(
245
+ key: string,
246
+ value: any,
247
+ formDataAcc: NodeFormData | FormData
248
+ ): void {
249
+ if (Array.isArray(value)) {
250
+ value.forEach(function (item: any) {
251
+ formDataAcc.append(key, item);
252
+ });
253
+ } else if (value != null) {
254
+ formDataAcc.append(key, value);
255
+ }
204
256
  }
205
257
 
206
258
  put(url: string, data: any, options?: any): Promise<APIResponse> {
@@ -3,7 +3,12 @@ import url from 'url';
3
3
  import urljoin from 'url-join';
4
4
 
5
5
  import Request from './request';
6
- import { BounceData, ComplaintData, UnsubscribeData } from './interfaces/Supressions';
6
+ import {
7
+ BounceData,
8
+ ComplaintData,
9
+ UnsubscribeData,
10
+ WhiteListData
11
+ } from './interfaces/Supressions';
7
12
 
8
13
  const createOptions = {
9
14
  headers: { 'Content-Type': 'application/json' }
@@ -51,7 +56,21 @@ class Unsubscribe {
51
56
  }
52
57
  }
53
58
 
54
- type TModel = typeof Bounce | typeof Complaint | typeof Unsubscribe;
59
+ class WhiteList {
60
+ type: string;
61
+ value: string;
62
+ reason: string;
63
+ createdAt: Date;
64
+
65
+ constructor(data: WhiteListData) {
66
+ this.type = 'whitelists';
67
+ this.value = data.value;
68
+ this.reason = data.reason;
69
+ this.createdAt = new Date(data.createdAt);
70
+ }
71
+ }
72
+
73
+ type TModel = typeof Bounce | typeof Complaint | typeof Unsubscribe | typeof WhiteList;
55
74
 
56
75
  export default class SuppressionClient {
57
76
  request: any;
@@ -59,6 +78,7 @@ export default class SuppressionClient {
59
78
  bounces: typeof Bounce;
60
79
  complaints: typeof Complaint;
61
80
  unsubscribes: typeof Unsubscribe;
81
+ whitelists: typeof WhiteList;
62
82
  };
63
83
 
64
84
  constructor(request: Request) {
@@ -66,7 +86,8 @@ export default class SuppressionClient {
66
86
  this.models = {
67
87
  bounces: Bounce,
68
88
  complaints: Complaint,
69
- unsubscribes: Unsubscribe
89
+ unsubscribes: Unsubscribe,
90
+ whitelists: WhiteList,
70
91
  };
71
92
  }
72
93
 
@@ -106,6 +127,12 @@ export default class SuppressionClient {
106
127
  return new Model(response.body);
107
128
  }
108
129
 
130
+ private createWhiteList(domain: string, data: any) {
131
+ return this.request
132
+ .postWithFD(urljoin('v3', domain, 'whitelists'), data, createOptions)
133
+ .then((response: { body: any }) => response.body);
134
+ }
135
+
109
136
  list(domain: string, type: string, query: any) {
110
137
  const model = (this.models as any)[type];
111
138
 
@@ -125,14 +152,18 @@ export default class SuppressionClient {
125
152
  create(domain: string, type: string, data: any) {
126
153
  // supports adding multiple suppressions by default
127
154
  let postData;
155
+ if (type === 'whitelists') {
156
+ return this.createWhiteList(domain, data);
157
+ }
158
+
128
159
  if (!Array.isArray(data)) {
129
160
  postData = [data];
130
161
  } else {
131
- postData = { ...data };
162
+ postData = [...data];
132
163
  }
133
164
 
134
165
  return this.request
135
- .post(urljoin('v3', domain, type), postData, createOptions)
166
+ .post(urljoin('v3', domain, type), JSON.stringify(postData), createOptions)
136
167
  .then((response: { body: any }) => response.body);
137
168
  }
138
169
 
package/lib/validate.ts CHANGED
@@ -1,14 +1,20 @@
1
+ import APIResponse from './interfaces/ApiResponse';
2
+ import { IMultipleValidationClient } from './interfaces/MultipleValidation';
3
+ import { ValidationResult, ValidationResponse } from './interfaces/Validate';
1
4
  import Request from './request';
2
5
 
3
6
  export default class ValidateClient {
7
+ public multipleValidation;
4
8
  request: Request;
5
9
 
6
- constructor(request: Request) {
10
+ constructor(request: Request, multipleValidationClient: IMultipleValidationClient) {
7
11
  this.request = request;
12
+ this.multipleValidation = multipleValidationClient;
8
13
  }
9
14
 
10
- get(address: string) {
11
- return this.request.get('/v3/address/validate', { address })
12
- .then((response) => response.body);
15
+ get(address: string): Promise<ValidationResult> {
16
+ return this.request.get('/v4/address/validate', { address })
17
+ .then((response : APIResponse) => response)
18
+ .then((res : ValidationResponse) => res.body as ValidationResult);
13
19
  }
14
20
  }
package/lib/webhooks.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import urljoin from 'url-join';
2
- import { WebhookList, WebhookResponse, WebhooksQuery } from './interfaces/Webhooks';
2
+
3
+ import {
4
+ ValidationResponse,
5
+ WebhookList,
6
+ WebhookResponse,
7
+ WebhooksQuery
8
+ } from './interfaces/Webhooks';
3
9
  import Request from './request';
4
10
 
5
11
  class Webhook {
@@ -13,7 +19,7 @@ class Webhook {
13
19
  }
14
20
 
15
21
  export default class WebhookClient {
16
- request: any;
22
+ request: Request;
17
23
 
18
24
  constructor(request: Request) {
19
25
  this.request = request;
@@ -36,36 +42,39 @@ export default class WebhookClient {
36
42
 
37
43
  _parseWebhookTest(response: { body: { code: number, message: string } })
38
44
  : {code: number, message:string} {
39
- return { code: response.body.code, message: response.body.message };
45
+ return { code: response.body.code, message: response.body.message } as ValidationResponse;
40
46
  }
41
47
 
42
48
  list(domain: string, query: WebhooksQuery): Promise<WebhookList> {
43
- return this.request.get(urljoin('/v2/domains', domain, 'webhooks'), query)
49
+ return this.request.get(urljoin('/v3/domains', domain, 'webhooks'), query)
44
50
  .then(this._parseWebhookList);
45
51
  }
46
52
 
47
53
  get(domain: string, id: string): Promise<Webhook> {
48
- return this.request.get(urljoin('/v2/domains', domain, 'webhooks', id))
54
+ return this.request.get(urljoin('/v3/domains', domain, 'webhooks', id))
49
55
  .then(this._parseWebhookWithID(id));
50
56
  }
51
57
 
52
- create(domain: string, id: string, url: string, test = false): Promise<Webhook> {
58
+ create(domain: string,
59
+ id: string,
60
+ url: string,
61
+ test = false): Promise<Webhook | ValidationResponse> {
53
62
  if (test) {
54
- return this.request.putWithFD(urljoin('/v2/domains', domain, 'webhooks', id, 'test'), { url })
63
+ return this.request.putWithFD(urljoin('/v3/domains', domain, 'webhooks', id, 'test'), { url })
55
64
  .then(this._parseWebhookTest);
56
65
  }
57
66
 
58
- return this.request.postWithFD(urljoin('/v2/domains', domain, 'webhooks'), { id, url })
67
+ return this.request.postWithFD(urljoin('/v3/domains', domain, 'webhooks'), { id, url })
59
68
  .then(this._parseWebhookWithID(id));
60
69
  }
61
70
 
62
71
  update(domain: string, id: string, url: string): Promise<Webhook> {
63
- return this.request.putWithFD(urljoin('/v2/domains', domain, 'webhooks', id), { url })
72
+ return this.request.putWithFD(urljoin('/v3/domains', domain, 'webhooks', id), { url })
64
73
  .then(this._parseWebhookWithID(id));
65
74
  }
66
75
 
67
76
  destroy(domain: string, id: string) : Promise<Webhook> {
68
- return this.request.delete(urljoin('/v2/domains', domain, 'webhooks', id))
77
+ return this.request.delete(urljoin('/v3/domains', domain, 'webhooks', id))
69
78
  .then(this._parseWebhookWithID(id));
70
79
  }
71
80
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mailgun.js",
3
- "version": "3.7.3",
3
+ "version": "4.1.1",
4
4
  "main": "dist/mailgun.node.js",
5
5
  "browser": "dist/mailgun.web.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,8 +11,12 @@ import SuppressionsClient from '../lib/suppressions';
11
11
  import MessagesClient from '../lib/messages';
12
12
  import RoutesClient from '../lib/routes';
13
13
  import ValidateClient from '../lib/validate';
14
- import ParseClient from '../lib/parse';
14
+
15
15
  import { InputFormData } from '../lib/interfaces/IFormData';
16
+ import StatsClient from '../lib/stats';
17
+ import ListsClient from '../lib/lists';
18
+ import IpPoolsClient from '../lib/ip-pools';
19
+ import IpsClient from '../lib/ips';
16
20
 
17
21
  describe('Client', function () {
18
22
  let client: any;
@@ -62,6 +66,10 @@ describe('Client', function () {
62
66
  client.suppressions.should.be.instanceOf(SuppressionsClient);
63
67
  });
64
68
 
69
+ it('creates stats client', function () {
70
+ client.stats.should.be.instanceOf(StatsClient);
71
+ });
72
+
65
73
  it('creates messages client', function () {
66
74
  client.messages.should.be.instanceOf(MessagesClient);
67
75
  });
@@ -70,11 +78,19 @@ describe('Client', function () {
70
78
  client.routes.should.be.instanceOf(RoutesClient);
71
79
  });
72
80
 
73
- it('creates address validate client', function () {
74
- client.validate.should.be.instanceOf(ValidateClient);
81
+ it('creates ips client', function () {
82
+ client.ips.should.be.instanceOf(IpsClient);
75
83
  });
76
84
 
77
- it('creates address parse client', function () {
78
- client.parse.should.be.instanceOf(ParseClient);
85
+ it('creates ip_pools client', function () {
86
+ client.ip_pools.should.be.instanceOf(IpPoolsClient);
87
+ });
88
+
89
+ it('creates lists client', function () {
90
+ client.lists.should.be.instanceOf(ListsClient);
91
+ });
92
+
93
+ it('creates address validate client', function () {
94
+ client.validate.should.be.instanceOf(ValidateClient);
79
95
  });
80
96
  });
@@ -0,0 +1,3 @@
1
+ email
2
+ 1testEmailAdressForCheck@test.com
3
+ 2testEmailAdressForCheck@test.com