Skip to content

Commit 5f21dde

Browse files
authored
Merge pull request #53 from emailjs-com/sdk-v4
SDK v4
2 parents 4179e8d + c238f03 commit 5f21dde

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1489
-227
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ name: CI
66
on:
77
# Triggers the workflow on push or pull request events but only for the master branch
88
push:
9-
branches: [ master ]
9+
branches: [ master, sdk-v4 ]
1010
pull_request:
11-
branches: [ master ]
11+
branches: [ master, sdk-v4 ]
1212

1313
# Allows you to run this workflow manually from the Actions tab
1414
workflow_dispatch:

README.md

Lines changed: 131 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
SDK for [EmailJS.com](https://www.emailjs.com) customers.
44
\
5-
Use you EmailJS account for sending emails.
5+
Use your EmailJS account for sending emails.
66

77
[![codecov](https://codecov.io/gh/emailjs-com/emailjs-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/emailjs-com/emailjs-sdk)
88
[![npm version](https://img.shields.io/npm/v/@emailjs/browser.svg)](https://www.npmjs.com/package/@emailjs/browser)
99

1010
## Disclaimer
1111

1212
This is a browser-only version, otherwise use
13+
1314
- [Node.js SDK](https://www.npmjs.com/package/@emailjs/nodejs)
1415
- [Flutter SDK](https://pub.dev/packages/emailjs)
1516
- [REST API](https://www.emailjs.com/docs/rest-api/send/)
@@ -20,7 +21,7 @@ This is a browser-only version, otherwise use
2021

2122
## Intro
2223

23-
EmailJS helps to send emails using client-side technologies only.
24+
EmailJS helps you send emails directly from code with one command.
2425
No server is required – just connect EmailJS to one of the supported
2526
email services, create an email template, and use our SDK
2627
to trigger an email.
@@ -29,67 +30,163 @@ to trigger an email.
2930

3031
Install EmailJS SDK using [npm](https://www.npmjs.com/):
3132

32-
```bash
33+
```bash
3334
$ npm install @emailjs/browser
3435
```
3536

3637
Or manually:
3738

38-
```html
39+
```html
3940
<script
4041
type="text/javascript"
41-
src="https://cdn.jsdelivr.net/npm/@emailjs/browser@3/dist/email.min.js">
42+
src="https://cdn.jsdelivr.net/npm/@emailjs/browser@4/dist/email.min.js">
4243
</script>
4344
<script type="text/javascript">
4445
(function () {
45-
emailjs.init('<YOUR_PUBLIC_KEY>');
46+
emailjs.init({
47+
publicKey: 'YOUR_PUBLIC_KEY',
48+
});
4649
})();
4750
</script>
4851
```
4952

5053
## Examples
5154

52-
**send email**
55+
**Send the email using the customized send method**
5356

54-
```js
57+
```js
5558
var templateParams = {
56-
name: 'James',
57-
notes: 'Check this out!'
59+
name: 'James',
60+
notes: 'Check this out!',
5861
};
5962

60-
emailjs.send('<YOUR_SERVICE_ID>','<YOUR_TEMPLATE_ID>', templateParams)
61-
.then(function(response) {
62-
console.log('SUCCESS!', response.status, response.text);
63-
}, function(err) {
64-
console.log('FAILED...', err);
65-
});
63+
emailjs.send('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', templateParams).then(
64+
function (response) {
65+
console.log('SUCCESS!', response.status, response.text);
66+
},
67+
function (err) {
68+
console.log('FAILED...', err);
69+
},
70+
);
71+
```
72+
73+
**Send the email from a form using the sendForm method**
74+
75+
```js
76+
emailjs.sendForm('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', '#myForm').then(
77+
function (response) {
78+
console.log('SUCCESS!', response.status, response.text);
79+
},
80+
function (err) {
81+
console.log('FAILED...', err);
82+
},
83+
);
6684
```
6785

68-
**send form**
86+
**Using Angular / VueJS / ReactJS / Svelte / any other modern framework**
87+
88+
```js
89+
import emailjs from '@emailjs/browser';
90+
91+
const templateParams = {
92+
name: 'James',
93+
notes: 'Check this out!',
94+
};
95+
96+
emailjs
97+
.send('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', templateParams, {
98+
publicKey: 'YOUR_PUBLIC_KEY',
99+
})
100+
.then(
101+
(response) => {
102+
console.log('SUCCESS!', response.status, response.text);
103+
},
104+
(err) => {
105+
console.log('FAILED...', err);
106+
},
107+
);
108+
```
109+
110+
## Configuration
111+
112+
**Options**
113+
114+
Options can be declared globally using the **init** method or locally as the fourth parameter of a function.
115+
\
116+
The local parameter will have higher priority than the global one.
117+
118+
| Name | Type | Default | Description |
119+
| ------------- | --------- | ------- | -------------------------------------------------------- |
120+
| publicKey | String | | The public key is required to invoke the method. |
121+
| blockHeadless | Boolean | False | Method will return error 451 if the browser is headless. |
122+
| blockList | BlockList | | Block list settings. |
123+
| limitRate | LimitRate | | Limit rate configuration. |
124+
125+
**BlockList**
126+
127+
Allows to ignore a method call if the watched variable contains a value from the block list.
128+
\
129+
The method will return the error 403 if the request is blocked.
130+
131+
| Name | Type | Description |
132+
| ------------- | -------- | -------------------------------------------------- |
133+
| list | String[] | The array of strings contains values for blocking. |
134+
| watchVariable | String | A name of the variable to be watched. |
135+
136+
**LimitRate**
137+
138+
Allows to set the limit rate for calling a method.
139+
\
140+
If the request hits the limit rate, the method will return the error 429.
141+
142+
| Name | Type | Default | Description |
143+
| -------- | ------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
144+
| id | String | page path | The limit rate is per page by default. To override the behavior, set the ID. It can be a custom ID for each page, group, or application. |
145+
| throttle | Number | | _(ms)_ After how many milliseconds a next request is allowed. |
146+
147+
**Declare global settings**
148+
149+
```js
150+
import emailjs from '@emailjs/browser';
69151

70-
```js
71-
emailjs.sendForm('<YOUR_SERVICE_ID>','<YOUR_TEMPLATE_ID>', '#myForm')
72-
.then(function(response) {
73-
console.log('SUCCESS!', response.status, response.text);
74-
}, function(err) {
75-
console.log('FAILED...', err);
76-
});
152+
emailjs.init({
153+
publicKey: 'YOUR_PUBLIC_KEY',
154+
blockHeadless: true,
155+
blockList: {
156+
list: ['foo@emailjs.com', 'bar@emailjs.com'],
157+
},
158+
limitRate: {
159+
throttle: 10000, // 10s
160+
},
161+
});
77162
```
78163

79-
**Angular X / VueJS / ReactJS**
164+
**Overwrite settings locally**
80165

81-
```js
166+
```js
82167
import emailjs from '@emailjs/browser';
83168

84169
const templateParams = {
85-
name: 'James',
86-
notes: 'Check this out!'
170+
name: 'James',
171+
notes: 'Check this out!',
87172
};
88173

89-
emailjs.send('<YOUR_SERVICE_ID>','<YOUR_TEMPLATE_ID>', templateParams, '<YOUR_PUBLIC_KEY>')
90-
.then((response) => {
91-
console.log('SUCCESS!', response.status, response.text);
92-
}, (err) => {
93-
console.log('FAILED...', err);
94-
});
174+
emailjs
175+
.send('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', templateParams, {
176+
publicKey: 'YOUR_PUBLIC_KEY',
177+
blockList: {
178+
watchVariable: 'userEmail',
179+
},
180+
limitRate: {
181+
throttle: 0, // turn off the limit rate for these requests
182+
},
183+
})
184+
.then(
185+
(response) => {
186+
console.log('SUCCESS!', response.status, response.text);
187+
},
188+
(err) => {
189+
console.log('FAILED...', err);
190+
},
191+
);
95192
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"build:lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
3131
"build:bundle": "webpack --env production",
3232
"build": "npm run build:clean && npm run build:lint && npm run build:ts && npm run build:cjs && npm run build:bundle",
33-
"test": "jest --coverage",
33+
"test": "jest --coverage --no-cache",
3434
"lint": "tsc --noEmit && eslint src"
3535
},
3636
"keywords": [

src/api/sendPost.ts

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,23 @@
11
import { EmailJSResponseStatus } from '../models/EmailJSResponseStatus';
22
import { store } from '../store/store';
33

4-
export const sendPost = (
4+
export const sendPost = async (
55
url: string,
66
data: string | FormData,
77
headers: Record<string, string> = {},
88
): Promise<EmailJSResponseStatus> => {
9-
return new Promise((resolve, reject) => {
10-
const xhr = new XMLHttpRequest();
11-
12-
xhr.addEventListener('load', ({ target }) => {
13-
const responseStatus = new EmailJSResponseStatus(target as XMLHttpRequest);
14-
15-
if (responseStatus.status === 200 || responseStatus.text === 'OK') {
16-
resolve(responseStatus);
17-
} else {
18-
reject(responseStatus);
19-
}
20-
});
21-
22-
xhr.addEventListener('error', ({ target }) => {
23-
reject(new EmailJSResponseStatus(target as XMLHttpRequest));
24-
});
9+
const response = await fetch(store.origin + url, {
10+
method: 'POST',
11+
headers,
12+
body: data,
13+
});
2514

26-
xhr.open('POST', store._origin + url, true);
15+
const message = await response.text();
16+
const responseStatus = new EmailJSResponseStatus(response.status, message);
2717

28-
Object.keys(headers).forEach((key) => {
29-
xhr.setRequestHeader(key, headers[key]);
30-
});
18+
if (response.ok) {
19+
return responseStatus;
20+
}
3121

32-
xhr.send(data);
33-
});
22+
throw responseStatus;
3423
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { it, expect } from '@jest/globals';
2+
3+
import { EmailJSResponseStatus } from '../../models/EmailJSResponseStatus';
4+
import { blockedEmailError } from './blockedEmailError';
5+
6+
it('should return EmailJSResponseStatus', () => {
7+
expect(blockedEmailError()).toBeInstanceOf(EmailJSResponseStatus);
8+
});
9+
10+
it('should return status 403', () => {
11+
expect(blockedEmailError()).toEqual({
12+
status: 403,
13+
text: 'Forbidden',
14+
});
15+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { EmailJSResponseStatus } from '../../models/EmailJSResponseStatus';
2+
3+
export const blockedEmailError = () => {
4+
return new EmailJSResponseStatus(403, 'Forbidden');
5+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { it, expect } from '@jest/globals';
2+
3+
import { EmailJSResponseStatus } from '../../models/EmailJSResponseStatus';
4+
import { headlessError } from './headlessError';
5+
6+
it('should return EmailJSResponseStatus', () => {
7+
expect(headlessError()).toBeInstanceOf(EmailJSResponseStatus);
8+
});
9+
10+
it('should return status 451', () => {
11+
expect(headlessError()).toEqual({
12+
status: 451,
13+
text: 'Unavailable For Headless Browser',
14+
});
15+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { EmailJSResponseStatus } from '../../models/EmailJSResponseStatus';
2+
3+
export const headlessError = () => {
4+
return new EmailJSResponseStatus(451, 'Unavailable For Headless Browser');
5+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { it, expect } from '@jest/globals';
2+
3+
import { EmailJSResponseStatus } from '../../models/EmailJSResponseStatus';
4+
import { limitRateError } from './limitRateError';
5+
6+
it('should return EmailJSResponseStatus', () => {
7+
expect(limitRateError()).toBeInstanceOf(EmailJSResponseStatus);
8+
});
9+
10+
it('should return status 451', () => {
11+
expect(limitRateError()).toEqual({
12+
status: 429,
13+
text: 'Too Many Requests',
14+
});
15+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { EmailJSResponseStatus } from '../../models/EmailJSResponseStatus';
2+
3+
export const limitRateError = () => {
4+
return new EmailJSResponseStatus(429, 'Too Many Requests');
5+
};

0 commit comments

Comments
 (0)