mailgun.js 3.7.0 → 4.0.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +335 -1
  3. package/dist/index.d.ts +2 -2
  4. package/dist/lib/client.d.ts +2 -6
  5. package/dist/lib/domains.d.ts +19 -13
  6. package/dist/lib/domainsCredentials.d.ts +14 -0
  7. package/dist/lib/events.d.ts +3 -3
  8. package/dist/lib/interfaces/DomainCredentials.d.ts +52 -0
  9. package/dist/lib/interfaces/DomainTracking.d.ts +4 -4
  10. package/dist/lib/interfaces/Domains.d.ts +53 -3
  11. package/dist/lib/interfaces/Events.d.ts +66 -2
  12. package/dist/lib/interfaces/IFormData.d.ts +4 -12
  13. package/dist/lib/interfaces/MultipleValidation.d.ts +55 -0
  14. package/dist/lib/interfaces/Validate.d.ts +12 -0
  15. package/dist/lib/interfaces/Webhooks.d.ts +5 -1
  16. package/dist/lib/interfaces/lists.d.ts +1 -1
  17. package/dist/lib/multipleValidation.d.ts +10 -0
  18. package/dist/lib/parse.d.ts +0 -6
  19. package/dist/lib/request.d.ts +4 -3
  20. package/dist/lib/validate.d.ts +5 -2
  21. package/dist/lib/webhooks.d.ts +3 -3
  22. package/dist/mailgun.node.js +2 -2
  23. package/dist/mailgun.node.js.LICENSE.txt +1 -1
  24. package/dist/mailgun.web.js +2 -2
  25. package/dist/mailgun.web.js.LICENSE.txt +1 -1
  26. package/index.ts +3 -3
  27. package/lib/client.ts +8 -14
  28. package/lib/domains.ts +82 -26
  29. package/lib/domainsCredentials.ts +88 -0
  30. package/lib/events.ts +6 -6
  31. package/lib/interfaces/DomainCredentials.ts +68 -0
  32. package/lib/interfaces/DomainTracking.ts +4 -4
  33. package/lib/interfaces/Domains.ts +65 -4
  34. package/lib/interfaces/Events.ts +66 -2
  35. package/lib/interfaces/IFormData.ts +5 -15
  36. package/lib/interfaces/MultipleValidation.ts +62 -0
  37. package/lib/interfaces/Validate.ts +15 -0
  38. package/lib/interfaces/Webhooks.ts +6 -1
  39. package/lib/interfaces/lists.ts +1 -1
  40. package/lib/multipleValidation.ts +37 -0
  41. package/lib/request.ts +28 -10
  42. package/lib/validate.ts +10 -4
  43. package/lib/webhooks.ts +19 -10
  44. package/package.json +7 -8
  45. package/test/client.test.ts +25 -8
  46. package/test/data/emailsValidation1.csv +3 -0
  47. package/test/domains.test.ts +119 -15
  48. package/test/domainsCredentials.test.ts +97 -0
  49. package/test/events.test.ts +17 -25
  50. package/test/ips.test.ts +2 -1
  51. package/test/lists.test.ts +2 -1
  52. package/test/mailListMembers.test.ts +2 -1
  53. package/test/messageAttachment.test.ts +2 -1
  54. package/test/messages.test.ts +2 -1
  55. package/test/multipleValidation.test.ts +159 -0
  56. package/test/request.test.ts +6 -5
  57. package/test/routes.test.ts +2 -1
  58. package/test/stats.test.ts +2 -1
  59. package/test/suppressions.test.ts +2 -1
  60. package/test/validate.test.ts +8 -4
  61. package/test/webhooks.test.ts +8 -7
  62. package/webpack/webpack.dev.config.js +10 -0
  63. package/lib/parse.ts +0 -27
  64. package/test/parse.test.ts +0 -74
@@ -1,19 +1,9 @@
1
- interface Headers {
2
- [key: string]: any;
3
- }
1
+ import NodeFormData from 'form-data';
4
2
 
5
- interface AppendOptions {
6
- header?: string | Headers;
7
- knownLength?: number;
8
- filename?: string;
9
- filepath?: string;
10
- contentType?: string;
3
+ export interface IFormDataOptions {
4
+ [key: string]: any;
11
5
  }
12
6
 
13
- export default abstract class IFormData {
14
- // eslint-disable-next-line no-useless-constructor
15
- constructor() { // description of type. Should not be used for creating objects
16
- }
17
-
18
- abstract append(key: string, value: any, options?: AppendOptions | string): void
7
+ export interface InputFormData {
8
+ new (options?: HTMLFormElement | IFormDataOptions): NodeFormData | FormData;
19
9
  }
@@ -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
+ }
@@ -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
+ }
@@ -9,7 +9,7 @@ export interface CreateUpdateList {
9
9
  address: string;
10
10
  name?: string;
11
11
  description?: string;
12
- access_level?: 'read-only' | 'members'| 'everyone';
12
+ access_level?: 'readonly' | 'members'| 'everyone';
13
13
  reply_preference?: 'list' | 'sender';
14
14
  }
15
15
 
@@ -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
@@ -1,14 +1,20 @@
1
+ import NodeFormData from 'form-data';
1
2
  import base64 from 'base-64';
2
3
  import urljoin from 'url-join';
3
4
  import ky from 'ky-universal';
4
5
  import APIError from './error';
5
6
  import RequestOptions from './interfaces/RequestOptions';
6
7
  import APIErrorOptions from './interfaces/APIErrorOptions';
7
- import IFormData from './interfaces/IFormData';
8
+ import { InputFormData } from './interfaces/IFormData';
8
9
  import APIResponse from './interfaces/ApiResponse';
9
10
 
10
11
  const isStream = (attachment: any) => typeof attachment === 'object' && typeof attachment.pipe === 'function';
11
12
 
13
+ function isNodeFormData(formDataInstance: NodeFormData | FormData)
14
+ : formDataInstance is NodeFormData {
15
+ return (<NodeFormData>formDataInstance).getHeaders !== undefined;
16
+ }
17
+
12
18
  const getAttachmentOptions = (item: any): {
13
19
  filename?: string,
14
20
  contentType?: string,
@@ -44,9 +50,9 @@ class Request {
44
50
  private url: string;
45
51
  private timeout: number;
46
52
  private headers: any;
47
- private formData: new () => IFormData;
53
+ private formData: InputFormData;
48
54
 
49
- constructor(options: RequestOptions, formData: new () => IFormData) {
55
+ constructor(options: RequestOptions, formData: InputFormData) {
50
56
  this.username = options.username;
51
57
  this.key = options.key;
52
58
  this.url = options.url as string;
@@ -101,10 +107,12 @@ class Request {
101
107
  } as APIErrorOptions);
102
108
  }
103
109
 
104
- return {
110
+ const res = {
105
111
  body: await response?.json(),
106
112
  status: response?.status
107
113
  };
114
+
115
+ return res;
108
116
  }
109
117
 
110
118
  query(method: string, url: string, query: any, options?: any) : Promise<APIResponse> {
@@ -136,6 +144,9 @@ class Request {
136
144
  }
137
145
 
138
146
  postWithFD(url: string, data: any): Promise<APIResponse> {
147
+ if (!data) {
148
+ throw new Error('Please provide data object');
149
+ }
139
150
  const params: any = {
140
151
  headers: { 'Content-Type': null }
141
152
  };
@@ -144,6 +155,9 @@ class Request {
144
155
  }
145
156
 
146
157
  putWithFD(url: string, data: any): Promise<APIResponse> {
158
+ if (!data) {
159
+ throw new Error('Please provide data object');
160
+ }
147
161
  const params: any = {
148
162
  headers: { 'Content-Type': null }
149
163
  };
@@ -151,22 +165,26 @@ class Request {
151
165
  return this.command('put', url, formData, params);
152
166
  }
153
167
 
154
- createFormData(data: any): IFormData {
155
- const appendFileToFD = (key: string, obj : any, formDataInstance: IFormData): void => {
168
+ createFormData(data: any): NodeFormData | FormData {
169
+ const appendFileToFD = (
170
+ key: string,
171
+ obj: any,
172
+ formDataInstance: NodeFormData | FormData
173
+ ): void => {
156
174
  const isStreamData = isStream(obj);
157
175
  const objData = isStreamData ? obj : obj.data;
158
176
  const options = getAttachmentOptions(obj);
159
- if (isStreamData) {
177
+ if (isNodeFormData(formDataInstance)) {
160
178
  formDataInstance.append(key, objData, options);
161
179
  return;
162
180
  }
163
181
  formDataInstance.append(key, objData, options.filename);
164
182
  };
165
183
 
166
- const formData: IFormData = Object.keys(data)
184
+ const formData: NodeFormData | FormData = Object.keys(data)
167
185
  .filter(function (key) { return data[key]; })
168
- .reduce((formDataAcc, key) => {
169
- if (key === 'attachment' || key === 'inline') {
186
+ .reduce((formDataAcc: NodeFormData | FormData, key) => {
187
+ if (key === 'attachment' || key === 'inline' || key === 'file') {
170
188
  const obj = data[key];
171
189
 
172
190
  if (Array.isArray(obj)) {
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.0",
3
+ "version": "4.0.0",
4
4
  "main": "dist/mailgun.node.js",
5
5
  "browser": "dist/mailgun.web.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,12 +12,12 @@
12
12
  ],
13
13
  "repository": {
14
14
  "type": "git",
15
- "url": "git://github.com/mailgun/mailgun-js.git"
15
+ "url": "git://github.com/mailgun/mailgun.js.git"
16
16
  },
17
17
  "bugs": {
18
- "url": "https://github.com/mailgun/mailgun-js/issues"
18
+ "url": "https://github.com/mailgun/mailgun.js/issues"
19
19
  },
20
- "homepage": "https://github.com/mailgun/mailgun-js#readme",
20
+ "homepage": "https://github.com/mailgun/mailgun.js#readme",
21
21
  "scripts": {
22
22
  "build": "webpack --config ./webpack/webpack.dev.config.js --progress --color",
23
23
  "build:release": "webpack --config ./webpack/webpack.release.config.js --progress --color",
@@ -102,11 +102,10 @@
102
102
  "section": "Other changes"
103
103
  }
104
104
  ],
105
- "commitUrlFormat": "https://github.com/mailgun/mailgun-js/commits/{{hash}}",
106
- "compareUrlFormat": "https://github.com/mailgun/mailgun-js/compare/{{previousTag}}...{{currentTag}}",
105
+ "commitUrlFormat": "https://github.com/mailgun/mailgun.js/commits/{{hash}}",
106
+ "compareUrlFormat": "https://github.com/mailgun/mailgun.js/compare/{{previousTag}}...{{currentTag}}",
107
107
  "scripts": {
108
- "prerelease": "npm test && webpack --config ./webpack/webpack.release.config.js --progress --color && git add -A dist",
109
- "posttag": "git push && git push --tags && rm -rf build"
108
+ "prerelease": "npm test && webpack --config ./webpack/webpack.release.config.js --progress --color && git add -A dist"
110
109
  }
111
110
  }
112
111
  }
@@ -11,7 +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
+ 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';
15
20
 
16
21
  describe('Client', function () {
17
22
  let client: any;
@@ -22,13 +27,13 @@ describe('Client', function () {
22
27
  key: 'key',
23
28
  public_key: 'key',
24
29
  timeout: 10000
25
- }, formData);
30
+ }, formData as InputFormData);
26
31
  });
27
32
 
28
33
  it('raises error when username is not provided', function () {
29
34
  expect(
30
35
  function () {
31
- return new Client({ key: 'key' } as any, formData);
36
+ return new Client({ key: 'key' } as any, formData as InputFormData);
32
37
  }
33
38
  ).to.throw('Parameter "username" is required');
34
39
  });
@@ -36,7 +41,7 @@ describe('Client', function () {
36
41
  it('raises error when key is not provided', function () {
37
42
  expect(
38
43
  function () {
39
- return new Client({ username: 'username' } as any, formData);
44
+ return new Client({ username: 'username' } as any, formData as InputFormData);
40
45
  }
41
46
  ).to.throw('Parameter "key" is required');
42
47
  });
@@ -61,6 +66,10 @@ describe('Client', function () {
61
66
  client.suppressions.should.be.instanceOf(SuppressionsClient);
62
67
  });
63
68
 
69
+ it('creates stats client', function () {
70
+ client.stats.should.be.instanceOf(StatsClient);
71
+ });
72
+
64
73
  it('creates messages client', function () {
65
74
  client.messages.should.be.instanceOf(MessagesClient);
66
75
  });
@@ -69,11 +78,19 @@ describe('Client', function () {
69
78
  client.routes.should.be.instanceOf(RoutesClient);
70
79
  });
71
80
 
72
- it('creates address validate client', function () {
73
- client.validate.should.be.instanceOf(ValidateClient);
81
+ it('creates ips client', function () {
82
+ client.ips.should.be.instanceOf(IpsClient);
74
83
  });
75
84
 
76
- it('creates address parse client', function () {
77
- 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);
78
95
  });
79
96
  });
@@ -0,0 +1,3 @@
1
+ email
2
+ 1testEmailAdressForCheck@test.com
3
+ 2testEmailAdressForCheck@test.com