Compare commits

...

8 Commits

Author SHA1 Message Date
Zack Schuster 27d51c2300 test: fix compile errors 2020-11-29 20:53:13 -08:00
Zack Schuster f56b3c106b chore: upgrade deps 2020-11-29 20:49:27 -08:00
Zack Schuster ca135f8f38 smtp/client: remove unnecessary callback invocation 2020-11-29 20:40:27 -08:00
Zack Schuster 44d31b579d smtp/connection: use WeakSet for greylist tracking 2020-11-29 20:40:27 -08:00
Zack Schuster 987bc95e7f smtp/client: add sendAsync api 2020-11-29 20:40:27 -08:00
Zack Schuster 9cd062f10d test/client: fix callback counter test 2020-11-29 20:40:27 -08:00
Zack Schuster d799559261 smtp/client: invoke callback when send is successful
allows awaiting message result when send is promisified
2020-11-29 20:40:27 -08:00
Zack Schuster c13356b51e smtp/date: add isRFC2822Date api & use in tests 2020-11-29 20:40:27 -08:00
9 changed files with 301 additions and 160 deletions

View File

@ -16,23 +16,23 @@
},
"type": "module",
"devDependencies": {
"@ledge/configs": "23.0.0",
"@ledge/configs": "23.3.223",
"@rollup/plugin-typescript": "6.1.0",
"@types/mailparser": "2.7.4",
"@types/mailparser": "3.0.0",
"@types/smtp-server": "3.5.5",
"@typescript-eslint/eslint-plugin": "4.6.0",
"@typescript-eslint/parser": "4.6.0",
"@typescript-eslint/eslint-plugin": "4.8.2",
"@typescript-eslint/parser": "4.8.2",
"ava": "3.13.0",
"eslint": "7.12.1",
"eslint": "7.14.0",
"eslint-config-prettier": "6.15.0",
"eslint-plugin-prettier": "3.1.4",
"mailparser": "2.8.0",
"prettier": "2.1.2",
"rollup": "2.32.1",
"smtp-server": "3.7.0",
"mailparser": "3.0.0",
"prettier": "2.2.1",
"rollup": "2.34.0",
"smtp-server": "3.8.0",
"ts-node": "9.0.0",
"tslib": "2.0.3",
"typescript": "4.0.5"
"typescript": "4.1.2"
},
"engine": [
"node >= 10"
@ -48,6 +48,9 @@
"import": "./rollup/email.mjs",
"require": "./rollup/email.cjs"
},
"resolutions": {
"nodemailer": "6.4.16"
},
"scripts": {
"build": "rollup -c rollup.config.ts",
"lint": "eslint *.ts \"+(smtp|test)/*.ts\"",

View File

@ -69,6 +69,23 @@ export class SMTPClient {
});
}
/**
* @public
* @param {Message} msg the message to send
* @returns {Promise<Message>} a promise that resolves to the fully processed message
*/
public sendAsync(msg: Message) {
return new Promise<Message>((resolve, reject) => {
this.send(msg, (err, msg) => {
if (err != null) {
reject(err);
} else {
resolve(msg);
}
});
});
}
/**
* @public
* @description Converts a message to the raw object used by the internal stack.

View File

@ -120,10 +120,7 @@ export class SMTPConnection extends EventEmitter {
protected tls: boolean | SMTPSocketOptions = false;
protected port: number;
private greylistResponseTracker = new WeakMap<
(...rest: any[]) => void,
boolean
>();
private greylistResponseTracker = new WeakSet<(...rest: any[]) => void>();
/**
* SMTP class written using python's (2.7) smtplib.py as a base.
@ -411,9 +408,9 @@ export class SMTPConnection extends EventEmitter {
} else if (
(code === 450 || code === 451) &&
msg.message.toLowerCase().includes('greylist') &&
this.greylistResponseTracker.get(response) === false
this.greylistResponseTracker.has(response) === false
) {
this.greylistResponseTracker.set(response, true);
this.greylistResponseTracker.add(response);
setTimeout(() => {
this.send(cmd + CRLF, response);
}, GREYLIST_DELAY);
@ -435,7 +432,7 @@ export class SMTPConnection extends EventEmitter {
}
};
this.greylistResponseTracker.set(response, false);
this.greylistResponseTracker.delete(response);
this.send(cmd + CRLF, response);
}

View File

@ -33,3 +33,18 @@ export function getRFC2822DateUTC(date = new Date()) {
dates.push('+0000');
return dates.join(' ');
}
/**
* RFC 2822 regex
* @see https://tools.ietf.org/html/rfc2822#section-3.3
* @see https://github.com/moment/moment/blob/a831fc7e2694281ce31e4f090bbcf90a690f0277/src/lib/create/from-string.js#L101
*/
const rfc2822re = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/.compile();
/**
* @param {string} [date] a string to check for conformance to the [rfc2822](https://tools.ietf.org/html/rfc2822#section-3.3) standard
* @returns {boolean} the result of the conformance check
*/
export function isRFC2822Date(date: string) {
return rfc2822re.test(date);
}

View File

@ -18,7 +18,7 @@ function send(
secure?: boolean;
} = {}
) {
return new Promise((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
t.plan(5);
const msg = {

View File

@ -4,7 +4,13 @@ import test from 'ava';
import { simpleParser, ParsedMail } from 'mailparser';
import { SMTPServer } from 'smtp-server';
import { DEFAULT_TIMEOUT, SMTPClient, Message, MessageHeaders } from '../email';
import {
DEFAULT_TIMEOUT,
SMTPClient,
Message,
MessageHeaders,
isRFC2822Date,
} from '../email';
const parseMap = new Map<string, ParsedMail>();
const port = 3000;
@ -43,7 +49,7 @@ async function send(headers: Partial<MessageHeaders>) {
if (err) {
reject(err);
} else {
resolve(parseMap.get(headers.subject as string));
resolve(parseMap.get(headers.subject as string) as ParsedMail);
}
});
});
@ -57,19 +63,45 @@ test.after(async (t) => {
});
test('client invokes callback exactly once for invalid connection', async (t) => {
t.plan(1);
const msg = {
from: 'foo@bar.baz',
to: 'foo@bar.baz',
subject: 'hello world',
text: 'hello world',
};
try {
const invalidClient = new SMTPClient({ host: 'bar.baz' });
await promisify(invalidClient.send.bind(invalidClient))(new Message(msg));
} catch (err) {
t.true(err instanceof Error);
}
await t.notThrowsAsync(
new Promise<void>((resolve, reject) => {
let counter = 0;
const invalidClient = new SMTPClient({ host: 'bar.baz' });
const incrementListener = () => {
if (counter > 0) {
reject();
} else {
counter++;
}
};
invalidClient.smtp.addListener('incrementTestCounter', incrementListener);
invalidClient.send(new Message(msg), (err) => {
if (err == null || counter > 0) {
reject();
} else {
invalidClient.smtp.emit('incrementTestCounter');
}
});
// @ts-expect-error the error event is only accessible from the protected socket property
invalidClient.smtp.sock.once('error', () => {
invalidClient.smtp.removeListener(
'incrementTestCounter',
incrementListener
);
if (counter === 1) {
resolve();
} else {
reject();
}
});
})
);
});
test('client has a default connection timeout', async (t) => {
@ -240,7 +272,7 @@ test('client supports greylisting', async (t) => {
const p = greylistPort++;
await t.notThrowsAsync(
new Promise((resolve, reject) => {
new Promise<void>((resolve, reject) => {
greylistServer.listen(p, () => {
new SMTPClient({
port: p,
@ -289,7 +321,7 @@ test('client only responds once to greylisting', async (t) => {
const p = greylistPort++;
const { message: error } = await t.throwsAsync(
new Promise((resolve, reject) => {
new Promise<void>((resolve, reject) => {
greylistServer.listen(p, () => {
new SMTPClient({
port: p,
@ -309,3 +341,83 @@ test('client only responds once to greylisting', async (t) => {
);
t.is(error, "bad response on command 'RCPT': greylist");
});
test('client send can have result awaited when promisified', async (t) => {
// bind necessary to retain internal access to client prototype
const sendAsync = promisify(client.send.bind(client));
const msg = {
subject: 'this is a test TEXT message from emailjs',
from: 'piglet@gmail.com',
bcc: 'pooh@gmail.com',
text: "It is hard to be brave when you're only a Very Small Animal.",
};
try {
const message = await sendAsync(new Message(msg));
t.true(message instanceof Message);
t.like(message, {
alternative: null,
content: 'text/plain; charset=utf-8',
text: "It is hard to be brave when you're only a Very Small Animal.",
header: {
bcc: 'pooh@gmail.com',
from: 'piglet@gmail.com',
subject: '=?UTF-8?Q?this_is_a_test_TEXT_message_from_emailjs?=',
},
});
t.deepEqual(message.attachments, []);
t.true(isRFC2822Date(message.header.date as string));
t.regex(message.header['message-id'] as string, /^<.*[@]{1}.*>$/);
} catch (err) {
t.fail(err);
}
});
test('client sendAsync can have result awaited', async (t) => {
const msg = {
subject: 'this is a test TEXT message from emailjs',
from: 'piglet@gmail.com',
bcc: 'pooh@gmail.com',
text: "It is hard to be brave when you're only a Very Small Animal.",
};
try {
const message = await client.sendAsync(new Message(msg));
t.true(message instanceof Message);
t.like(message, {
alternative: null,
content: 'text/plain; charset=utf-8',
text: "It is hard to be brave when you're only a Very Small Animal.",
header: {
bcc: 'pooh@gmail.com',
from: 'piglet@gmail.com',
subject: '=?UTF-8?Q?this_is_a_test_TEXT_message_from_emailjs?=',
},
});
t.deepEqual(message.attachments, []);
t.true(isRFC2822Date(message.header.date as string));
t.regex(message.header['message-id'] as string, /^<.*[@]{1}.*>$/);
} catch (err) {
t.fail(err);
}
});
test('client sendAsync can have error caught when awaited', async (t) => {
const msg = {
subject: 'this is a test TEXT message from emailjs',
from: 'piglet@gmail.com',
bcc: 'pooh@gmail.com',
text: "It is hard to be brave when you're only a Very Small Animal.",
};
try {
const invalidClient = new SMTPClient({ host: 'bar.baz' });
const message = await invalidClient.sendAsync(new Message(msg));
t.true(message instanceof Message);
t.fail();
} catch (err) {
t.true(err instanceof Error);
t.pass();
}
});

View File

@ -1,18 +1,15 @@
import test from 'ava';
import { getRFC2822Date, getRFC2822DateUTC } from '../email';
import { getRFC2822Date, getRFC2822DateUTC, isRFC2822Date } from '../email';
const toD_utc = (dt: number) => getRFC2822DateUTC(new Date(dt));
const toD = (dt: number, utc = false) => getRFC2822Date(new Date(dt), utc);
test('rfc2822 non-UTC', async (t) => {
// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
// thanks to moment.js for the listing: https://github.com/moment/moment/blob/a831fc7e2694281ce31e4f090bbcf90a690f0277/src/lib/create/from-string.js#L101
const rfc2822re = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
t.regex(toD(0), rfc2822re);
t.regex(toD(329629726785), rfc2822re);
t.regex(toD(729629726785), rfc2822re);
t.regex(toD(1129629726785), rfc2822re);
t.regex(toD(1529629726785), rfc2822re);
t.true(isRFC2822Date(toD(0)));
t.true(isRFC2822Date(toD(329629726785)));
t.true(isRFC2822Date(toD(729629726785)));
t.true(isRFC2822Date(toD(1129629726785)));
t.true(isRFC2822Date(toD(1529629726785)));
});
test('rfc2822 UTC', async (t) => {

View File

@ -44,7 +44,7 @@ function send(headers: Partial<MessageHeaders>) {
if (err) {
reject(err);
} else {
resolve(parseMap.get(headers.subject as string));
resolve(parseMap.get(headers.subject as string) as ParsedMail);
}
});
});

242
yarn.lock
View File

@ -46,10 +46,10 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@ledge/configs@23.0.0":
version "23.0.0"
resolved "https://registry.npmjs.org/@ledge/configs/-/configs-23.0.0.tgz#263621257da40011f20fcc20b26a9c6376b55cfc"
integrity sha512-4yvm4OIS92LpiR5fmFYCOvkurssjxNCYnpms5kI7xPVzeQHdP7o/Kx40Gbb4qmFQEV3u7Isxy6gy49hIcpqd8w==
"@ledge/configs@23.3.223":
version "23.3.223"
resolved "https://registry.npmjs.org/@ledge/configs/-/configs-23.3.223.tgz#6b4eea31cc5a5ef95c3e283fcdbff6fb6da70822"
integrity sha512-rdRLIY+Qn70cJjRA9KRkt6UW9I5plQNd7KJO7Sre+CY25we3SZ5fRdo4aJlG4sg9/4qGqanedVC7/cczOQMWMw==
"@nodelib/fs.scandir@2.1.3":
version "2.1.3"
@ -111,17 +111,17 @@
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
"@types/mailparser@2.7.4":
version "2.7.4"
resolved "https://registry.npmjs.org/@types/mailparser/-/mailparser-2.7.4.tgz#7faae72f874077fbb89c075ad898e6fd8a41119e"
integrity sha512-JGIV4RtcjBO1jsD0RTDoXOmm1zzHr07rWPmNREBBM1oAjjfy99Ne4Y7s/akVSZoksm/JWQMcFQ42LbsufHRVfg==
"@types/mailparser@3.0.0":
version "3.0.0"
resolved "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.0.0.tgz#a3cc643e5f2abea3f5a68b59a126b6313ef317ef"
integrity sha512-LsGznUos/+iY83fVjoduIr3PUGfkgtcEvR7HqXpmiP4TsdZo6jf31EcmjDcROmluj1PDMhWRXOxy4ndkx78wUQ==
dependencies:
"@types/node" "*"
"@types/node@*":
version "14.14.6"
resolved "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f"
integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw==
version "14.14.10"
resolved "https://registry.npmjs.org/@types/node/-/node-14.14.10.tgz#5958a82e41863cfc71f2307b3748e3491ba03785"
integrity sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ==
"@types/nodemailer@*":
version "6.4.0"
@ -143,61 +143,61 @@
"@types/node" "*"
"@types/nodemailer" "*"
"@typescript-eslint/eslint-plugin@4.6.0":
version "4.6.0"
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.0.tgz#210cd538bb703f883aff81d3996961f5dba31fdb"
integrity sha512-1+419X+Ynijytr1iWI+/IcX/kJryc78YNpdaXR1aRO1sU3bC0vZrIAF1tIX7rudVI84W7o7M4zo5p1aVt70fAg==
"@typescript-eslint/eslint-plugin@4.8.2":
version "4.8.2"
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.8.2.tgz#cf9102ec800391caa574f589ffe0623cca1d9308"
integrity sha512-gQ06QLV5l1DtvYtqOyFLXD9PdcILYqlrJj2l+CGDlPtmgLUzc1GpqciJFIRvyfvgLALpnxYINFuw+n9AZhPBKQ==
dependencies:
"@typescript-eslint/experimental-utils" "4.6.0"
"@typescript-eslint/scope-manager" "4.6.0"
"@typescript-eslint/experimental-utils" "4.8.2"
"@typescript-eslint/scope-manager" "4.8.2"
debug "^4.1.1"
functional-red-black-tree "^1.0.1"
regexpp "^3.0.0"
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/experimental-utils@4.6.0":
version "4.6.0"
resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.0.tgz#f750aef4dd8e5970b5c36084f0a5ca2f0db309a4"
integrity sha512-pnh6Beh2/4xjJVNL+keP49DFHk3orDHHFylSp3WEjtgW3y1U+6l+jNnJrGlbs6qhAz5z96aFmmbUyKhunXKvKw==
"@typescript-eslint/experimental-utils@4.8.2":
version "4.8.2"
resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.8.2.tgz#8909a5732f19329cf5ef0c39766170476bff5e50"
integrity sha512-hpTw6o6IhBZEsQsjuw/4RWmceRyESfAiEzAEnXHKG1X7S5DXFaZ4IO1JO7CW1aQ604leQBzjZmuMI9QBCAJX8Q==
dependencies:
"@types/json-schema" "^7.0.3"
"@typescript-eslint/scope-manager" "4.6.0"
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/typescript-estree" "4.6.0"
"@typescript-eslint/scope-manager" "4.8.2"
"@typescript-eslint/types" "4.8.2"
"@typescript-eslint/typescript-estree" "4.8.2"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/parser@4.6.0":
version "4.6.0"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.6.0.tgz#7e9ff7df2f21d5c8f65f17add3b99eeeec33199d"
integrity sha512-Dj6NJxBhbdbPSZ5DYsQqpR32MwujF772F2H3VojWU6iT4AqL4BKuoNWOPFCoSZvCcADDvQjDpa6OLDAaiZPz2Q==
"@typescript-eslint/parser@4.8.2":
version "4.8.2"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.8.2.tgz#78dccbe5124de2b8dea2d4c363dee9f769151ca8"
integrity sha512-u0leyJqmclYr3KcXOqd2fmx6SDGBO0MUNHHAjr0JS4Crbb3C3d8dwAdlazy133PLCcPn+aOUFiHn72wcuc5wYw==
dependencies:
"@typescript-eslint/scope-manager" "4.6.0"
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/typescript-estree" "4.6.0"
"@typescript-eslint/scope-manager" "4.8.2"
"@typescript-eslint/types" "4.8.2"
"@typescript-eslint/typescript-estree" "4.8.2"
debug "^4.1.1"
"@typescript-eslint/scope-manager@4.6.0":
version "4.6.0"
resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.6.0.tgz#b7d8b57fe354047a72dfb31881d9643092838662"
integrity sha512-uZx5KvStXP/lwrMrfQQwDNvh2ppiXzz5TmyTVHb+5TfZ3sUP7U1onlz3pjoWrK9konRyFe1czyxObWTly27Ang==
"@typescript-eslint/scope-manager@4.8.2":
version "4.8.2"
resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.8.2.tgz#a18388c63ae9c17adde519384f539392f2c4f0d9"
integrity sha512-qHQ8ODi7mMin4Sq2eh/6eu03uVzsf5TX+J43xRmiq8ujng7ViQSHNPLOHGw/Wr5dFEoxq/ubKhzClIIdQy5q3g==
dependencies:
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/visitor-keys" "4.6.0"
"@typescript-eslint/types" "4.8.2"
"@typescript-eslint/visitor-keys" "4.8.2"
"@typescript-eslint/types@4.6.0":
version "4.6.0"
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.6.0.tgz#157ca925637fd53c193c6bf226a6c02b752dde2f"
integrity sha512-5FAgjqH68SfFG4UTtIFv+rqYJg0nLjfkjD0iv+5O27a0xEeNZ5rZNDvFGZDizlCD1Ifj7MAbSW2DPMrf0E9zjA==
"@typescript-eslint/types@4.8.2":
version "4.8.2"
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.8.2.tgz#c862dd0e569d9478eb82d6aee662ea53f5661a36"
integrity sha512-z1/AVcVF8ju5ObaHe2fOpZYEQrwHyZ7PTOlmjd3EoFeX9sv7UekQhfrCmgUO7PruLNfSHrJGQvrW3Q7xQ8EoAw==
"@typescript-eslint/typescript-estree@4.6.0":
version "4.6.0"
resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.0.tgz#85bd98dcc8280511cfc5b2ce7b03a9ffa1732b08"
integrity sha512-s4Z9qubMrAo/tw0CbN0IN4AtfwuehGXVZM0CHNMdfYMGBDhPdwTEpBrecwhP7dRJu6d9tT9ECYNaWDHvlFSngA==
"@typescript-eslint/typescript-estree@4.8.2":
version "4.8.2"
resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.8.2.tgz#eeec34707d8577600fb21661b5287226cc8b3bed"
integrity sha512-HToGNwI6fekH0dOw3XEVESUm71Onfam0AKin6f26S2FtUmO7o3cLlWgrIaT1q3vjB3wCTdww3Dx2iGq5wtUOCg==
dependencies:
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/visitor-keys" "4.6.0"
"@typescript-eslint/types" "4.8.2"
"@typescript-eslint/visitor-keys" "4.8.2"
debug "^4.1.1"
globby "^11.0.1"
is-glob "^4.0.1"
@ -205,12 +205,12 @@
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/visitor-keys@4.6.0":
version "4.6.0"
resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.0.tgz#fb05d6393891b0a089b243fc8f9fb8039383d5da"
integrity sha512-38Aa9Ztl0XyFPVzmutHXqDMCu15Xx8yKvUo38Gu3GhsuckCh3StPI5t2WIO9LHEsOH7MLmlGfKUisU8eW1Sjhg==
"@typescript-eslint/visitor-keys@4.8.2":
version "4.8.2"
resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.8.2.tgz#62cd3fbbbf65f8eccfbe6f159eb1b84a243a3f77"
integrity sha512-Vg+/SJTMZJEKKGHW7YC21QxgKJrSbxoYYd3MEUGtW7zuytHuEcksewq0DUmo4eh/CTNrVJGSdIY9AtRb6riWFw==
dependencies:
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/types" "4.8.2"
eslint-visitor-keys "^2.0.0"
acorn-jsx@^5.2.0:
@ -577,9 +577,9 @@ cli-truncate@^2.1.0:
string-width "^4.2.0"
cliui@^7.0.2:
version "7.0.3"
resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz#ef180f26c8d9bff3927ee52428bfec2090427981"
integrity sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw==
version "7.0.4"
resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
@ -705,9 +705,9 @@ date-time@^3.1.0:
time-zone "^1.0.0"
debug@^4.0.1, debug@^4.1.1, debug@^4.2.0:
version "4.2.0"
resolved "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1"
integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==
version "4.3.1"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
dependencies:
ms "2.1.2"
@ -938,10 +938,10 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
eslint@7.12.1:
version "7.12.1"
resolved "https://registry.npmjs.org/eslint/-/eslint-7.12.1.tgz#bd9a81fa67a6cfd51656cdb88812ce49ccec5801"
integrity sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg==
eslint@7.14.0:
version "7.14.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-7.14.0.tgz#2d2cac1d28174c510a97b377f122a5507958e344"
integrity sha512-5YubdnPXrlrYAFCKybPuHIAH++PINe1pmKNc5wQRB9HSbqIK1ywAnntE3Wwua4giKu0bjligf1gLF6qxMGOYRA==
dependencies:
"@babel/code-frame" "^7.0.0"
"@eslint/eslintrc" "^0.2.1"
@ -1318,9 +1318,9 @@ ignore@^5.1.4:
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
import-fresh@^3.0.0, import-fresh@^3.2.1:
version "3.2.1"
resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66"
integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==
version "3.2.2"
resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e"
integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==
dependencies:
parent-module "^1.0.0"
resolve-from "^4.0.0"
@ -1400,10 +1400,10 @@ is-ci@^2.0.0:
dependencies:
ci-info "^2.0.0"
is-core-module@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz#58531b70aed1db7c0e8d4eb1a0a2d1ddd64bd12d"
integrity sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==
is-core-module@^2.1.0:
version "2.2.0"
resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
dependencies:
has "^1.0.3"
@ -1652,10 +1652,10 @@ lowercase-keys@^2.0.0:
resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
mailparser@2.8.0:
version "2.8.0"
resolved "https://registry.npmjs.org/mailparser/-/mailparser-2.8.0.tgz#fbafa33d0a1a0531d75fabaf49d321290b10a014"
integrity sha512-Ja5H6/I1NKIFdFJF5HdZkaMGCN8F+1lu3870ZmrabkHQshhrPk4OWeEMiF0OVo82+6XJqemJPCg6pqgXaj3B6Q==
mailparser@3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/mailparser/-/mailparser-3.0.0.tgz#0c275cb3be02563fb8e10357529808ede277d70d"
integrity sha512-173gOV5y8kkCmvEZRgx0/XrOZ96F0Nm+tq382+/jIzPsBu9IYbn07l4t4DJqG4x5OSeKoBf5af/n1RRg+vbf8g==
dependencies:
encoding-japanese "1.0.30"
he "1.2.0"
@ -1664,8 +1664,8 @@ mailparser@2.8.0:
libmime "5.0.0"
linkify-it "3.0.2"
mailsplit "5.0.0"
nodemailer "6.4.10"
tlds "1.207.0"
nodemailer "6.4.11"
tlds "1.209.0"
mailsplit@5.0.0:
version "5.0.0"
@ -1779,10 +1779,10 @@ natural-compare@^1.4.0:
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
nodemailer@6.4.10:
version "6.4.10"
resolved "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.10.tgz#f4c8dc7991c57f41fd081bef224ef01f7065143d"
integrity sha512-j+pS9CURhPgk6r0ENr7dji+As2xZiHSvZeVnzKniLOw1eRAyM/7flP0u65tCnsapV8JFu+t0l/5VeHsCZEeh9g==
nodemailer@6.4.11, nodemailer@6.4.16:
version "6.4.16"
resolved "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.16.tgz#5cb6391b1d79ab7eff32d6f9f48366b5a7117293"
integrity sha512-68K0LgZ6hmZ7PVmwL78gzNdjpj5viqBdFqKrTtr9bZbJYj6BRj5W6WGkxXrEnUl3Co3CBXi3CZBUlpV/foGnOQ==
normalize-package-data@^2.5.0:
version "2.5.0"
@ -2025,10 +2025,10 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"
prettier@2.1.2:
version "2.1.2"
resolved "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5"
integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==
prettier@2.2.1:
version "2.2.1"
resolved "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
pretty-ms@^7.0.1:
version "7.0.1"
@ -2104,9 +2104,9 @@ regexpp@^3.0.0, regexpp@^3.1.0:
integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
registry-auth-token@^4.0.0:
version "4.2.0"
resolved "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz#1d37dffda72bbecd0f581e4715540213a65eb7da"
integrity sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==
version "4.2.1"
resolved "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250"
integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==
dependencies:
rc "^1.2.8"
@ -2140,11 +2140,11 @@ resolve-from@^5.0.0:
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
resolve@^1.10.0, resolve@^1.17.0:
version "1.18.1"
resolved "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130"
integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==
version "1.19.0"
resolved "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
dependencies:
is-core-module "^2.0.0"
is-core-module "^2.1.0"
path-parse "^1.0.6"
responselike@^1.0.2:
@ -2181,10 +2181,10 @@ rimraf@^3.0.2:
dependencies:
glob "^7.1.3"
rollup@2.32.1:
version "2.32.1"
resolved "https://registry.npmjs.org/rollup/-/rollup-2.32.1.tgz#625a92c54f5b4d28ada12d618641491d4dbb548c"
integrity sha512-Op2vWTpvK7t6/Qnm1TTh7VjEZZkN8RWgf0DHbkKzQBwNf748YhXbozHVefqpPp/Fuyk/PQPAnYsBxAEtlMvpUw==
rollup@2.34.0:
version "2.34.0"
resolved "https://registry.npmjs.org/rollup/-/rollup-2.34.0.tgz#ecc7f1d4ce2cb88bb51bec2f56b984f3c35b8271"
integrity sha512-dW5iLvttZzdVehjEuNJ1bWvuMEJjOWGmnuFS82WeKHTGXDkRHQeq/ExdifkSyJv9dLcR86ysKRmrIDyR6O0X8g==
optionalDependencies:
fsevents "~2.1.2"
@ -2275,14 +2275,14 @@ slice-ansi@^3.0.0:
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
smtp-server@3.7.0:
version "3.7.0"
resolved "https://registry.npmjs.org/smtp-server/-/smtp-server-3.7.0.tgz#62ac989e4a02b1098615837360fdd95a63b1f151"
integrity sha512-hL4kXlv0A4KEI2N3+pgx/4b/WlOxGJgVxL5N449rd809q9fy7n1ewJeTj4xAVUAFD6vnY53xC8w15j43wKMHrQ==
smtp-server@3.8.0:
version "3.8.0"
resolved "https://registry.npmjs.org/smtp-server/-/smtp-server-3.8.0.tgz#21d7f3f7cee2778883c9a73e1824a657c9680565"
integrity sha512-MuHxJj6vyInpFZTt0J8kkPHEw+VrJTYLcadu5N/8xmU0AowPdZonTptRQvYxC1MGQ5FlC1YtbtMXeeY+TV5aNg==
dependencies:
base32.js "0.1.0"
ipv6-normalize "1.0.1"
nodemailer "6.4.10"
nodemailer "6.4.16"
source-map-support@^0.5.17, source-map-support@^0.5.19:
version "0.5.19"
@ -2319,9 +2319,9 @@ spdx-expression-parse@^3.0.0:
spdx-license-ids "^3.0.0"
spdx-license-ids@^3.0.0:
version "3.0.6"
resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce"
integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==
version "3.0.7"
resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65"
integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
sprintf-js@~1.0.2:
version "1.0.3"
@ -2329,9 +2329,9 @@ sprintf-js@~1.0.2:
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
stack-utils@^2.0.2:
version "2.0.2"
resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593"
integrity sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg==
version "2.0.3"
resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277"
integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==
dependencies:
escape-string-regexp "^2.0.0"
@ -2451,10 +2451,10 @@ time-zone@^1.0.0:
resolved "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d"
integrity sha1-mcW/VZWJZq9tBtg73zgA3IL67F0=
tlds@1.207.0:
version "1.207.0"
resolved "https://registry.npmjs.org/tlds/-/tlds-1.207.0.tgz#459264e644cf63ddc0965fece3898913286b1afd"
integrity sha512-k7d7Q1LqjtAvhtEOs3yN14EabsNO8ZCoY6RESSJDB9lst3bTx3as/m1UuAeCKzYxiyhR1qq72ZPhpSf+qlqiwg==
tlds@1.209.0:
version "1.209.0"
resolved "https://registry.npmjs.org/tlds/-/tlds-1.209.0.tgz#13cfdc039331d49730ca7bfa9526fc9b319e2cec"
integrity sha512-KVsZ1NSpBodpo42/JIwTyau7SqUxV/qQMp2epSDPa99885LpHWLaVCCt8CWzGe4X5YIVNr+b6bUys9e9eEb5OA==
to-readable-stream@^1.0.0:
version "1.0.0"
@ -2530,10 +2530,10 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"
typescript@4.0.5:
version "4.0.5"
resolved "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389"
integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
typescript@4.1.2:
version "4.1.2"
resolved "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9"
integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==
uc.micro@^1.0.1:
version "1.0.6"
@ -2665,27 +2665,27 @@ xdg-basedir@^4.0.0:
resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
y18n@^5.0.2:
y18n@^5.0.5:
version "5.0.5"
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18"
integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==
yargs-parser@^20.2.2:
version "20.2.3"
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz#92419ba867b858c868acf8bae9bf74af0dd0ce26"
integrity sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww==
version "20.2.4"
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
yargs@^16.0.3:
version "16.1.0"
resolved "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz#fc333fe4791660eace5a894b39d42f851cd48f2a"
integrity sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==
version "16.1.1"
resolved "https://registry.npmjs.org/yargs/-/yargs-16.1.1.tgz#5a4a095bd1ca806b0a50d0c03611d38034d219a1"
integrity sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w==
dependencies:
cliui "^7.0.2"
escalade "^3.1.1"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
string-width "^4.2.0"
y18n "^5.0.2"
y18n "^5.0.5"
yargs-parser "^20.2.2"
yn@3.1.1: