Skip to content

Commit bbdf081

Browse files
Merge pull request #367 from mailgun/provide-all-methods-of-unsubscribe-creation
fix: Creating one unsubscribe with the tag property
2 parents 558649c + 3ccc575 commit bbdf081

File tree

8 files changed

+26352
-78
lines changed

8 files changed

+26352
-78
lines changed

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ The following service methods are available to instantiated clients. The example
111111
- [create](#create-2)
112112
- [Bounces Example](#bounces-example-2)
113113
- [Unsubscribes Example](#unsubscribes-example-2)
114+
- [Unsubscribe from one tag](#unsubscribe-from-one-tag)
114115
- [Unsubscribe from particular tags](#unsubscribe-from-particular-tags)
115116
- [Complaints Example](#complaints-example-2)
116117
- [destroy](#destroy-1)
@@ -1042,7 +1043,7 @@ Method naming conventions:
10421043

10431044
Promise returns:
10441045

1045-
```JSON
1046+
```js
10461047
{
10471048
message: "1 address has been added to the bounces table"
10481049
}
@@ -1051,7 +1052,7 @@ Method naming conventions:
10511052
- #### Unsubscribes Example:
10521053

10531054
```js
1054-
mg.suppressions.create('foobar.example.com', 'unsubscribes', [{address: '[email protected]'}])
1055+
mg.suppressions.create('foobar.example.com', 'unsubscribes', {address: '[email protected]'})
10551056
.then(msg => console.log(msg)) // logs response data
10561057
.catch(err => console.error(err)); // logs any error
10571058
```
@@ -1072,7 +1073,19 @@ Method naming conventions:
10721073
message: "1 address has been added to the unsubscribes table"
10731074
}
10741075
```
1076+
- #### Unsubscribe from one tag
1077+
```js
1078+
mg.suppressions.create('foobar.example.com', 'unsubscribes', {address: '[email protected]', tag: 'your_tag_to_unsubscribe']})
1079+
.then(msg => console.log(msg)) // logs response data
1080+
.catch(err => console.error(err)); // logs any error
1081+
```
1082+
Promise returns:
10751083

1084+
```JS
1085+
{
1086+
message: "1 address has been added to the unsubscribes table"
1087+
}
1088+
```
10761089
- #### Unsubscribe from particular tags
10771090
```js
10781091
mg.suppressions.create('foobar.example.com', 'unsubscribes', [{address: '[email protected]', tags: ['your_tag_to_unsubscribe', 'another_tag_to_unsubscribe']}])

dist/Classes/Suppressions/SuppressionsClient.d.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { IBounce, IComplaint, ISuppressionClient, IUnsubscribe, IWhiteList } fro
55
import { SuppressionList, SuppressionListResponse, SuppressionDataType, SuppressionCreationData, SuppressionCreationResult, SuppressionListQuery, SuppressionDestroyResult } from '../../Types/Suppressions';
66
export default class SuppressionClient extends NavigationThruPages<SuppressionList> implements ISuppressionClient {
77
request: Request;
8-
models: Map<string, any>;
8+
models: object;
99
constructor(request: Request);
1010
protected parseList(response: SuppressionListResponse, Model: {
1111
new (data: SuppressionDataType): IBounce | IComplaint | IUnsubscribe | IWhiteList;
@@ -14,7 +14,8 @@ export default class SuppressionClient extends NavigationThruPages<SuppressionLi
1414
new (dataType: SuppressionDataType): T;
1515
}): T;
1616
private createWhiteList;
17-
private checkType;
17+
private createUnsubscribe;
18+
private getModel;
1819
private prepareResponse;
1920
list(domain: string, type: string, query?: SuppressionListQuery): Promise<SuppressionList>;
2021
get(domain: string, type: string, address: string): Promise<IBounce | IComplaint | IUnsubscribe | IWhiteList>;

dist/README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ The following service methods are available to instantiated clients. The example
111111
- [create](#create-2)
112112
- [Bounces Example](#bounces-example-2)
113113
- [Unsubscribes Example](#unsubscribes-example-2)
114+
- [Unsubscribe from one tag](#unsubscribe-from-one-tag)
114115
- [Unsubscribe from particular tags](#unsubscribe-from-particular-tags)
115116
- [Complaints Example](#complaints-example-2)
116117
- [destroy](#destroy-1)
@@ -1042,7 +1043,7 @@ Method naming conventions:
10421043

10431044
Promise returns:
10441045

1045-
```JSON
1046+
```js
10461047
{
10471048
message: "1 address has been added to the bounces table"
10481049
}
@@ -1051,7 +1052,7 @@ Method naming conventions:
10511052
- #### Unsubscribes Example:
10521053

10531054
```js
1054-
mg.suppressions.create('foobar.example.com', 'unsubscribes', [{address: '[email protected]'}])
1055+
mg.suppressions.create('foobar.example.com', 'unsubscribes', {address: '[email protected]'})
10551056
.then(msg => console.log(msg)) // logs response data
10561057
.catch(err => console.error(err)); // logs any error
10571058
```
@@ -1072,7 +1073,19 @@ Method naming conventions:
10721073
message: "1 address has been added to the unsubscribes table"
10731074
}
10741075
```
1076+
- #### Unsubscribe from one tag
1077+
```js
1078+
mg.suppressions.create('foobar.example.com', 'unsubscribes', {address: '[email protected]', tag: 'your_tag_to_unsubscribe']})
1079+
.then(msg => console.log(msg)) // logs response data
1080+
.catch(err => console.error(err)); // logs any error
1081+
```
1082+
Promise returns:
10751083

1084+
```JS
1085+
{
1086+
message: "1 address has been added to the unsubscribes table"
1087+
}
1088+
```
10761089
- #### Unsubscribe from particular tags
10771090
```js
10781091
mg.suppressions.create('foobar.example.com', 'unsubscribes', [{address: '[email protected]', tags: ['your_tag_to_unsubscribe', 'another_tag_to_unsubscribe']}])

dist/mailgun.node.js

Lines changed: 15386 additions & 3 deletions
Large diffs are not rendered by default.

dist/mailgun.web.js

Lines changed: 10757 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/Classes/Suppressions/SuppressionsClient.ts

Lines changed: 71 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,17 @@ export default class SuppressionClient
4040
extends NavigationThruPages<SuppressionList>
4141
implements ISuppressionClient {
4242
request: Request;
43-
models: Map<string, any>;
43+
models: object;
4444

4545
constructor(request: Request) {
4646
super(request);
4747
this.request = request;
48-
this.models = new Map();
49-
this.models.set('bounces', Bounce);
50-
this.models.set('complaints', Complaint);
51-
this.models.set('unsubscribes', Unsubscribe);
52-
this.models.set('whitelists', WhiteList);
48+
this.models = {
49+
bounces: Bounce,
50+
complaints: Complaint,
51+
unsubscribes: Unsubscribe,
52+
whitelists: WhiteList,
53+
};
5354
}
5455

5556
protected parseList(
@@ -78,9 +79,10 @@ export default class SuppressionClient
7879

7980
private createWhiteList(
8081
domain: string,
81-
data: SuppressionCreationData | SuppressionCreationData[]
82+
data: SuppressionCreationData | SuppressionCreationData[],
83+
isDataArray: boolean
8284
): Promise<SuppressionCreationResult> {
83-
if (Array.isArray(data)) {
85+
if (isDataArray) {
8486
throw new APIError({
8587
status: 400,
8688
statusText: 'Data property should be an object',
@@ -94,14 +96,59 @@ export default class SuppressionClient
9496
.then(this.prepareResponse);
9597
}
9698

97-
private checkType(type: string) {
98-
if (!this.models.has(type)) {
99+
private createUnsubscribe(
100+
domain: string,
101+
data: SuppressionCreationData | SuppressionCreationData[]
102+
): Promise<SuppressionCreationResult> {
103+
if (Array.isArray(data)) { // User provided an array
104+
const isContainsTag = data.some((unsubscribe: SuppressionCreationData) => unsubscribe.tag);
105+
if (isContainsTag) {
106+
throw new APIError({
107+
status: 400,
108+
statusText: 'Tag property should not be used for creating multiple unsubscribes.',
109+
body: {
110+
message: 'Tag property can be used only if one unsubscribe provided as second argument of create method. Please use tags instead.'
111+
}
112+
} as APIErrorOptions);
113+
}
114+
return this.request
115+
.post(urljoin('v3', domain, 'unsubscribes'), JSON.stringify(data), createOptions)
116+
.then(this.prepareResponse);
117+
}
118+
119+
if (data?.tags) {
120+
throw new APIError({
121+
status: 400,
122+
statusText: 'Tags property should not be used for creating one unsubscribe.',
123+
body: {
124+
message: 'Tags property can be used if you provides an array of unsubscribes as second argument of create method. Please use tag instead'
125+
}
126+
} as APIErrorOptions);
127+
}
128+
if (Array.isArray(data.tag)) {
99129
throw new APIError({
100130
status: 400,
101-
statusText: 'Unknown type value',
102-
body: { message: 'Type may be only one of [bounces, complaints, unsubscribes, whitelists]' }
131+
statusText: 'Tag property can not be an array',
132+
body: {
133+
message: 'Please use array of unsubscribes as second argument of create method to be able to provide few tags'
134+
}
103135
} as APIErrorOptions);
104136
}
137+
/* We need Form Data for unsubscribes if we want to support the "tag" property */
138+
return this.request
139+
.postWithFD(urljoin('v3', domain, 'unsubscribes'), data)
140+
.then(this.prepareResponse);
141+
}
142+
143+
private getModel(type: string) {
144+
if (type in this.models) {
145+
return this.models[type as keyof typeof this.models];
146+
}
147+
throw new APIError({
148+
status: 400,
149+
statusText: 'Unknown type value',
150+
body: { message: 'Type may be only one of [bounces, complaints, unsubscribes, whitelists]' }
151+
} as APIErrorOptions);
105152
}
106153

107154
private prepareResponse(response: SuppressionCreationResponse): SuppressionCreationResult {
@@ -118,8 +165,7 @@ export default class SuppressionClient
118165
type: string,
119166
query?: SuppressionListQuery
120167
): Promise<SuppressionList> {
121-
this.checkType(type);
122-
const model = this.models.get(type);
168+
const model = this.getModel(type);
123169
return this.requestListWithPages(urljoin('v3', domain, type), query, model);
124170
}
125171

@@ -128,9 +174,7 @@ export default class SuppressionClient
128174
type: string,
129175
address: string
130176
): Promise<IBounce | IComplaint | IUnsubscribe | IWhiteList> {
131-
this.checkType(type);
132-
133-
const model = this.models.get(type);
177+
const model = this.getModel(type);
134178
return this.request
135179
.get(urljoin('v3', domain, type, encodeURIComponent(address)))
136180
.then((response: SuppressionResponse) => this._parseItem<typeof model>(response.body, model));
@@ -141,14 +185,20 @@ export default class SuppressionClient
141185
type: string,
142186
data: SuppressionCreationData | SuppressionCreationData[]
143187
): Promise<SuppressionCreationResult> {
144-
this.checkType(type);
188+
this.getModel(type);
145189
// supports adding multiple suppressions by default
146190
let postData;
191+
const isDataArray = Array.isArray(data);
192+
147193
if (type === 'whitelists') {
148-
return this.createWhiteList(domain, data);
194+
return this.createWhiteList(domain, data, isDataArray);
195+
}
196+
197+
if (type === 'unsubscribes') {
198+
return this.createUnsubscribe(domain, data);
149199
}
150200

151-
if (!Array.isArray(data)) {
201+
if (!isDataArray) {
152202
postData = [data];
153203
} else {
154204
postData = [...data];
@@ -164,7 +214,7 @@ export default class SuppressionClient
164214
type: string,
165215
address: string
166216
): Promise<SuppressionDestroyResult> {
167-
this.checkType(type);
217+
this.getModel(type);
168218
return this.request
169219
.delete(urljoin('v3', domain, type, encodeURIComponent(address)))
170220
.then((response: SuppressionDestroyResponse) => ({

lib/Types/Suppressions/Suppressions.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,8 @@ export type SuppressionCreationData = {
5959
code?: number;
6060
error?: string;
6161
domain?: string;
62-
tag?: string;
62+
tag?: string; // works only with FormData usage for one unsubscribe
6363
created_at?: string ;
64-
/* Official documentation says that endpoint for "unsubscribes" supports "tag" property
65-
but in reality it ignores the value of it.
66-
At the same time "tags" property seems working fine.
67-
https://github.com/mailgun/mailgun.js/issues/365
68-
*/
6964
tags?: string[];
7065
}
7166

0 commit comments

Comments
 (0)