@emailjs/browser
Version:
Official EmailJS SDK for browsers
272 lines (247 loc) • 9.67 kB
JavaScript
var emailjs = (function (exports) {
'use strict';
class EmailJSResponseStatus {
constructor() {
let _status = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
let _text = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Network Error';
this.status = _status;
this.text = _text;
}
}
const createWebStorage = () => {
if (typeof localStorage === 'undefined') return;
return {
get: key => Promise.resolve(localStorage.getItem(key)),
set: (key, value) => Promise.resolve(localStorage.setItem(key, value)),
remove: key => Promise.resolve(localStorage.removeItem(key))
};
};
const store = {
origin: 'https://api.emailjs.com',
blockHeadless: false,
storageProvider: createWebStorage()
};
const buildOptions = options => {
if (!options) return {};
// support compatibility with SDK v3
if (typeof options === 'string') {
return {
publicKey: options
};
}
// eslint-disable-next-line @typescript-eslint/no-base-to-string
if (options.toString() === '[object Object]') {
return options;
}
return {};
};
/**
* EmailJS global SDK config
* @param {object} options - the EmailJS global SDK config options
* @param {string} origin - the non-default EmailJS origin
*/
const init = function (options) {
let origin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'https://api.emailjs.com';
if (!options) return;
const opts = buildOptions(options);
store.publicKey = opts.publicKey;
store.blockHeadless = opts.blockHeadless;
store.storageProvider = opts.storageProvider;
store.blockList = opts.blockList;
store.limitRate = opts.limitRate;
store.origin = opts.origin || origin;
};
const sendPost = async function (url, data) {
let headers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
const response = await fetch(store.origin + url, {
method: 'POST',
headers,
body: data
});
const message = await response.text();
const responseStatus = new EmailJSResponseStatus(response.status, message);
if (response.ok) {
return responseStatus;
}
throw responseStatus;
};
const validateParams = (publicKey, serviceID, templateID) => {
if (!publicKey || typeof publicKey !== 'string') {
throw 'The public key is required. Visit https://dashboard.emailjs.com/admin/account';
}
if (!serviceID || typeof serviceID !== 'string') {
throw 'The service ID is required. Visit https://dashboard.emailjs.com/admin';
}
if (!templateID || typeof templateID !== 'string') {
throw 'The template ID is required. Visit https://dashboard.emailjs.com/admin/templates';
}
};
const validateTemplateParams = templateParams => {
// eslint-disable-next-line @typescript-eslint/no-base-to-string
if (templateParams && templateParams.toString() !== '[object Object]') {
throw 'The template params have to be the object. Visit https://www.emailjs.com/docs/sdk/send/';
}
};
const isHeadless = navigator => {
return navigator.webdriver || !navigator.languages || navigator.languages.length === 0;
};
const headlessError = () => {
return new EmailJSResponseStatus(451, 'Unavailable For Headless Browser');
};
const validateBlockListParams = (list, watchVariable) => {
if (!Array.isArray(list)) {
throw 'The BlockList list has to be an array';
}
if (typeof watchVariable !== 'string') {
throw 'The BlockList watchVariable has to be a string';
}
};
const isBlockListDisabled = options => {
return !options.list?.length || !options.watchVariable;
};
const getValue = (data, name) => {
return data instanceof FormData ? data.get(name) : data[name];
};
const isBlockedValueInParams = (options, params) => {
if (isBlockListDisabled(options)) return false;
validateBlockListParams(options.list, options.watchVariable);
const value = getValue(params, options.watchVariable);
if (typeof value !== 'string') return false;
return options.list.includes(value);
};
const blockedEmailError = () => {
return new EmailJSResponseStatus(403, 'Forbidden');
};
const validateLimitRateParams = (throttle, id) => {
if (typeof throttle !== 'number' || throttle < 0) {
throw 'The LimitRate throttle has to be a positive number';
}
if (id && typeof id !== 'string') {
throw 'The LimitRate ID has to be a non-empty string';
}
};
const getLeftTime = async (id, throttle, storage) => {
const lastTime = Number((await storage.get(id)) || 0);
return throttle - Date.now() + lastTime;
};
const isLimitRateHit = async (defaultID, options, storage) => {
if (!options.throttle || !storage) {
return false;
}
validateLimitRateParams(options.throttle, options.id);
const id = options.id || defaultID;
const leftTime = await getLeftTime(id, options.throttle, storage);
if (leftTime > 0) {
return true;
}
await storage.set(id, Date.now().toString());
return false;
};
const limitRateError = () => {
return new EmailJSResponseStatus(429, 'Too Many Requests');
};
/**
* Send a template to the specific EmailJS service
* @param {string} serviceID - the EmailJS service ID
* @param {string} templateID - the EmailJS template ID
* @param {object} templateParams - the template params, what will be set to the EmailJS template
* @param {object} options - the EmailJS SDK config options
* @returns {Promise<EmailJSResponseStatus>}
*/
const send = async (serviceID, templateID, templateParams, options) => {
const opts = buildOptions(options);
const publicKey = opts.publicKey || store.publicKey;
const blockHeadless = opts.blockHeadless || store.blockHeadless;
const storageProvider = opts.storageProvider || store.storageProvider;
const blockList = {
...store.blockList,
...opts.blockList
};
const limitRate = {
...store.limitRate,
...opts.limitRate
};
if (blockHeadless && isHeadless(navigator)) {
return Promise.reject(headlessError());
}
validateParams(publicKey, serviceID, templateID);
validateTemplateParams(templateParams);
if (templateParams && isBlockedValueInParams(blockList, templateParams)) {
return Promise.reject(blockedEmailError());
}
if (await isLimitRateHit(location.pathname, limitRate, storageProvider)) {
return Promise.reject(limitRateError());
}
const params = {
lib_version: '4.4.1',
user_id: publicKey,
service_id: serviceID,
template_id: templateID,
template_params: templateParams
};
return sendPost('/api/v1.0/email/send', JSON.stringify(params), {
'Content-type': 'application/json'
});
};
const validateForm = form => {
if (!form || form.nodeName !== 'FORM') {
throw 'The 3rd parameter is expected to be the HTML form element or the style selector of the form';
}
};
const findHTMLForm = form => {
return typeof form === 'string' ? document.querySelector(form) : form;
};
/**
* Send a form the specific EmailJS service
* @param {string} serviceID - the EmailJS service ID
* @param {string} templateID - the EmailJS template ID
* @param {string | HTMLFormElement} form - the form element or selector
* @param {object} options - the EmailJS SDK config options
* @returns {Promise<EmailJSResponseStatus>}
*/
const sendForm = async (serviceID, templateID, form, options) => {
const opts = buildOptions(options);
const publicKey = opts.publicKey || store.publicKey;
const blockHeadless = opts.blockHeadless || store.blockHeadless;
const storageProvider = store.storageProvider || opts.storageProvider;
const blockList = {
...store.blockList,
...opts.blockList
};
const limitRate = {
...store.limitRate,
...opts.limitRate
};
if (blockHeadless && isHeadless(navigator)) {
return Promise.reject(headlessError());
}
const currentForm = findHTMLForm(form);
validateParams(publicKey, serviceID, templateID);
validateForm(currentForm);
const formData = new FormData(currentForm);
if (isBlockedValueInParams(blockList, formData)) {
return Promise.reject(blockedEmailError());
}
if (await isLimitRateHit(location.pathname, limitRate, storageProvider)) {
return Promise.reject(limitRateError());
}
formData.append('lib_version', '4.4.1');
formData.append('service_id', serviceID);
formData.append('template_id', templateID);
formData.append('user_id', publicKey);
return sendPost('/api/v1.0/email/send-form', formData);
};
var index = {
init,
send,
sendForm,
EmailJSResponseStatus
};
exports.EmailJSResponseStatus = EmailJSResponseStatus;
exports.default = index;
exports.init = init;
exports.send = send;
exports.sendForm = sendForm;
Object.defineProperty(exports, '__esModule', { value: true });
return exports;
})({});