mirror of
https://github.com/lukevella/rallly.git
synced 2025-04-28 09:46:39 +02:00
🧑💻 Use mailpit as dev/test smtp server (#1486)
This commit is contained in:
parent
b00b685bbd
commit
285860ec9e
12 changed files with 124 additions and 242 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
@ -69,8 +69,7 @@ jobs:
|
|||
- uses: ./.github/actions/yarn-install
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
run: sudo apt-get update
|
||||
|
||||
- name: Install playwright dependencies
|
||||
run: yarn playwright install --with-deps chromium
|
||||
|
|
|
@ -5,4 +5,4 @@ SECRET_PASSWORD=abcdef1234567890abcdef1234567890
|
|||
DATABASE_URL=postgres://postgres:postgres@localhost:5450/rallly
|
||||
SUPPORT_EMAIL=support@rallly.co
|
||||
SMTP_HOST=localhost
|
||||
SMTP_PORT=4025
|
||||
SMTP_PORT=1025
|
|
@ -97,7 +97,6 @@
|
|||
"cross-env": "^7.0.3",
|
||||
"i18next-scanner": "^4.2.0",
|
||||
"i18next-scanner-typescript": "^1.1.1",
|
||||
"smtp-tester": "^2.1.0",
|
||||
"vitest": "^2.1.1",
|
||||
"wait-on": "^6.0.1"
|
||||
}
|
||||
|
|
|
@ -1,33 +1,24 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { prisma } from "@rallly/database";
|
||||
import { load } from "cheerio";
|
||||
import smtpTester from "smtp-tester";
|
||||
|
||||
import { captureEmailHTML } from "./mailpit/mailpit";
|
||||
|
||||
const testUserEmail = "test@example.com";
|
||||
let mailServer: smtpTester.MailServer;
|
||||
|
||||
/**
|
||||
* Get the 6-digit code from the email
|
||||
* @returns 6-digit code
|
||||
*/
|
||||
const getCode = async () => {
|
||||
const { email } = await mailServer.captureOne(testUserEmail, {
|
||||
wait: 5000,
|
||||
});
|
||||
const html = await captureEmailHTML(testUserEmail);
|
||||
|
||||
if (!email.html) {
|
||||
throw new Error("Email doesn't contain HTML");
|
||||
}
|
||||
|
||||
const $ = load(email.html);
|
||||
const $ = load(html);
|
||||
|
||||
return $("#code").text().trim();
|
||||
};
|
||||
|
||||
test.describe.serial(() => {
|
||||
test.beforeAll(() => {
|
||||
mailServer = smtpTester.init(4025);
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
try {
|
||||
await prisma.user.deleteMany({
|
||||
|
@ -38,8 +29,6 @@ test.describe.serial(() => {
|
|||
} catch {
|
||||
// User doesn't exist
|
||||
}
|
||||
|
||||
mailServer.stop(() => {});
|
||||
});
|
||||
|
||||
test.describe("new user", () => {
|
||||
|
@ -110,15 +99,9 @@ test.describe.serial(() => {
|
|||
|
||||
await page.getByRole("button", { name: "Login with Email" }).click();
|
||||
|
||||
const { email } = await mailServer.captureOne(testUserEmail, {
|
||||
wait: 5000,
|
||||
});
|
||||
const html = await captureEmailHTML(testUserEmail);
|
||||
|
||||
if (!email.html) {
|
||||
throw new Error("Email doesn't contain HTML");
|
||||
}
|
||||
|
||||
const $ = load(email.html);
|
||||
const $ = load(html);
|
||||
|
||||
const magicLink = $("#magicLink").attr("href");
|
||||
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
import type { Page } from "@playwright/test";
|
||||
import { expect, test } from "@playwright/test";
|
||||
import type { MailServer } from "smtp-tester";
|
||||
import smtpTester from "smtp-tester";
|
||||
import { NewPollPage } from "tests/new-poll-page";
|
||||
|
||||
import { deleteAllMessages } from "./mailpit/mailpit";
|
||||
|
||||
test.describe.serial(() => {
|
||||
let page: Page;
|
||||
|
||||
let mailServer: MailServer;
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
page = await browser.newPage();
|
||||
mailServer = smtpTester.init(4025);
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
mailServer.stop(() => {});
|
||||
await deleteAllMessages(); // Clean the mailbox before tests
|
||||
});
|
||||
|
||||
test("create a new poll", async () => {
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
import type { Page } from "@playwright/test";
|
||||
import { expect, test } from "@playwright/test";
|
||||
import type { MailServer } from "smtp-tester";
|
||||
import smtpTester from "smtp-tester";
|
||||
import type { EditOptionsPage } from "tests/edit-options-page";
|
||||
import { NewPollPage } from "tests/new-poll-page";
|
||||
|
||||
test.describe("edit options", () => {
|
||||
let page: Page;
|
||||
let editOptionsPage: EditOptionsPage;
|
||||
let mailServer: MailServer;
|
||||
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
page = await browser.newPage();
|
||||
mailServer = smtpTester.init(4025);
|
||||
const newPollPage = new NewPollPage(page);
|
||||
await newPollPage.goto();
|
||||
const pollPage = await newPollPage.createPollAndCloseDialog();
|
||||
|
@ -20,10 +16,6 @@ test.describe("edit options", () => {
|
|||
editOptionsPage = await pollPage.editOptions();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
mailServer.stop(() => {});
|
||||
});
|
||||
|
||||
test("should show warning when deleting options with votes in them", async () => {
|
||||
editOptionsPage.switchToSpecifyTimes();
|
||||
|
||||
|
|
56
apps/web/tests/mailpit/mailpit.ts
Normal file
56
apps/web/tests/mailpit/mailpit.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import type { MailpitListMessagesResponse, MailpitMessage } from "./types";
|
||||
|
||||
const MAILPIT_API_URL = "http://localhost:8025/api";
|
||||
|
||||
export async function getMessages(): Promise<MailpitListMessagesResponse> {
|
||||
const response = await fetch(`${MAILPIT_API_URL}/v1/messages`);
|
||||
const data = (await response.json()) as MailpitListMessagesResponse;
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function getMessage(id: string): Promise<MailpitMessage> {
|
||||
const response = await fetch(`${MAILPIT_API_URL}/v1/message/${id}`);
|
||||
const data = (await response.json()) as MailpitMessage;
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function deleteAllMessages(): Promise<void> {
|
||||
await fetch(`${MAILPIT_API_URL}/v1/messages`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
}
|
||||
|
||||
export async function captureOne(
|
||||
to: string,
|
||||
options: { wait?: number } = {},
|
||||
): Promise<{ email: MailpitMessage }> {
|
||||
const startTime = Date.now();
|
||||
const timeout = options.wait ?? 5000;
|
||||
|
||||
while (Date.now() - startTime < timeout) {
|
||||
const { messages } = await getMessages();
|
||||
const message = messages.find(
|
||||
(msg) =>
|
||||
new Date(msg.Created) > new Date(startTime) &&
|
||||
msg.To.some((recipient) => recipient.Address === to),
|
||||
);
|
||||
|
||||
if (message) {
|
||||
const fullMessage = await getMessage(message.ID);
|
||||
return { email: fullMessage };
|
||||
}
|
||||
|
||||
// Wait a bit before trying again
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
throw new Error(`No email received for ${to} within ${timeout}ms`);
|
||||
}
|
||||
|
||||
export async function captureEmailHTML(to: string): Promise<string> {
|
||||
const { email } = await captureOne(to);
|
||||
if (!email.HTML) {
|
||||
throw new Error("Email doesn't contain HTML");
|
||||
}
|
||||
return email.HTML;
|
||||
}
|
46
apps/web/tests/mailpit/types.ts
Normal file
46
apps/web/tests/mailpit/types.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
export interface MailpitAttachment {
|
||||
ContentID: string;
|
||||
ContentType: string;
|
||||
FileName: string;
|
||||
PartID: string;
|
||||
Size: number;
|
||||
}
|
||||
|
||||
export interface MailpitEmailAddress {
|
||||
Address: string;
|
||||
Name: string;
|
||||
}
|
||||
|
||||
export interface MailpitMessageSummary {
|
||||
Attachments: number;
|
||||
Bcc: MailpitEmailAddress[];
|
||||
Cc: MailpitEmailAddress[];
|
||||
Created: string;
|
||||
From: MailpitEmailAddress;
|
||||
ID: string;
|
||||
MessageID: string;
|
||||
Read: boolean;
|
||||
ReplyTo: MailpitEmailAddress[];
|
||||
Size: number;
|
||||
Snippet: string;
|
||||
Subject: string;
|
||||
Tags: string[];
|
||||
To: MailpitEmailAddress[];
|
||||
}
|
||||
|
||||
export interface MailpitMessage extends MailpitMessageSummary {
|
||||
HTML: string;
|
||||
Text: string;
|
||||
Inline: MailpitAttachment[];
|
||||
ReturnPath: string;
|
||||
Date: string;
|
||||
}
|
||||
|
||||
export interface MailpitListMessagesResponse {
|
||||
messages: MailpitMessageSummary[];
|
||||
messages_count: number;
|
||||
start: number;
|
||||
tags: string[];
|
||||
total: number;
|
||||
unread: number;
|
||||
}
|
|
@ -16,7 +16,7 @@ export class NewPollPage {
|
|||
async createPoll() {
|
||||
const page = this.page;
|
||||
|
||||
await page.type('[placeholder="Monthly Meetup"]', "Monthly Meetup");
|
||||
await page.fill('[placeholder="Monthly Meetup"]', "Monthly Meetup");
|
||||
// click on label to focus on input
|
||||
await page.click('text="Location"');
|
||||
await page.keyboard.type("Joe's Coffee Shop");
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import type { Page, Request } from "@playwright/test";
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { load } from "cheerio";
|
||||
import type { MailServer } from "smtp-tester";
|
||||
import smtpTester from "smtp-tester";
|
||||
import type { PollPage } from "tests/poll-page";
|
||||
|
||||
import { captureOne } from "./mailpit/mailpit";
|
||||
import { NewPollPage } from "./new-poll-page";
|
||||
|
||||
test.describe(() => {
|
||||
|
@ -13,9 +12,7 @@ test.describe(() => {
|
|||
let touchRequest: Promise<Request>;
|
||||
let editSubmissionUrl: string;
|
||||
|
||||
let mailServer: MailServer;
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
mailServer = smtpTester.init(4025);
|
||||
page = await browser.newPage();
|
||||
touchRequest = page.waitForRequest(
|
||||
(request) =>
|
||||
|
@ -27,10 +24,6 @@ test.describe(() => {
|
|||
pollPage = await newPollPage.createPollAndCloseDialog();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
mailServer.stop(() => {});
|
||||
});
|
||||
|
||||
test("should call touch endpoint", async () => {
|
||||
// make sure call to touch RPC is made
|
||||
expect(await touchRequest).not.toBeNull();
|
||||
|
@ -54,17 +47,15 @@ test.describe(() => {
|
|||
|
||||
await invitePage.addParticipant("Anne", "test@example.com");
|
||||
|
||||
await expect(page.locator("text='Anne'")).toBeVisible();
|
||||
|
||||
const { email } = await mailServer.captureOne("test@example.com", {
|
||||
const { email } = await captureOne("test@example.com", {
|
||||
wait: 5000,
|
||||
});
|
||||
|
||||
expect(email.headers.subject).toBe(
|
||||
"Thanks for responding to Monthly Meetup",
|
||||
);
|
||||
await expect(page.locator("text='Anne'")).toBeVisible();
|
||||
|
||||
const $ = load(email.html as string);
|
||||
expect(email.Subject).toBe("Thanks for responding to Monthly Meetup");
|
||||
|
||||
const $ = load(email.HTML);
|
||||
const href = $("#editSubmissionUrl").attr("href");
|
||||
|
||||
if (!href) {
|
||||
|
|
|
@ -45,8 +45,8 @@ services:
|
|||
MINIO_ROOT_PASSWORD: minio123
|
||||
volumes:
|
||||
- s3-data:/data
|
||||
mailhog:
|
||||
image: mailhog/mailhog
|
||||
mailpit:
|
||||
image: axllent/mailpit
|
||||
ports:
|
||||
- "8025:8025"
|
||||
- "1025:1025"
|
||||
|
|
181
yarn.lock
181
yarn.lock
|
@ -4732,14 +4732,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz#5f1b518ec5fa54437c0b7c4a821546c64fed6922"
|
||||
integrity sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==
|
||||
|
||||
"@selderee/plugin-htmlparser2@^0.10.0":
|
||||
version "0.10.0"
|
||||
resolved "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.10.0.tgz"
|
||||
integrity sha512-gW69MEamZ4wk1OsOq1nG1jcyhXIQcnrsX5JwixVw/9xaiav8TCyjESAruu1Rz9yyInhgBXxkNwMeygKnN2uxNA==
|
||||
dependencies:
|
||||
domhandler "^5.0.3"
|
||||
selderee "^0.10.0"
|
||||
|
||||
"@selderee/plugin-htmlparser2@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz"
|
||||
|
@ -6633,14 +6625,6 @@
|
|||
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz"
|
||||
integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==
|
||||
|
||||
"@types/mailparser@^3.4.0":
|
||||
version "3.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/mailparser/-/mailparser-3.4.4.tgz#0bd71e205573b9dd9a445e10a8b8cb0e45420998"
|
||||
integrity sha512-C6Znp2QVS25JqtuPyxj38Qh+QoFcLycdxsvcc6IZCGekhaMBzbdTXzwGzhGoYb3TfKu8IRCNV0sV1o3Od97cEQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
iconv-lite "^0.6.3"
|
||||
|
||||
"@types/mdast@^4.0.0":
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6"
|
||||
|
@ -6704,13 +6688,6 @@
|
|||
resolved "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz"
|
||||
integrity sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ==
|
||||
|
||||
"@types/nodemailer@*":
|
||||
version "6.4.10"
|
||||
resolved "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.10.tgz"
|
||||
integrity sha512-oPW/IdhkU3FyZc1dzeqmS+MBjrjZNiiINnrEOrWALzccJlP5xTlbkNr2YnTnnyj9Eqm5ofjRoASEbrCYpA7BrA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/nodemailer@^6.4.14":
|
||||
version "6.4.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.14.tgz#5c81a5e856db7f8ede80013e6dbad7c5fb2283e2"
|
||||
|
@ -6847,14 +6824,6 @@
|
|||
resolved "https://registry.npmjs.org/@types/smoothscroll-polyfill/-/smoothscroll-polyfill-0.3.1.tgz"
|
||||
integrity sha512-+KkHw4y+EyeCtVXET7woHUhIbfWFCflc0E0mZnSV+ZdjPQeHt/9KPEuT7gSW/kFQ8O3EG30PLO++YhChDt8+Ag==
|
||||
|
||||
"@types/smtp-server@^3.5.7":
|
||||
version "3.5.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/smtp-server/-/smtp-server-3.5.10.tgz#06d0338aea519469529847a12b0903678fdd6bea"
|
||||
integrity sha512-i3Jx7sJ2qF52vjaOf3HguulXlWRFf6BSfsRLsIdmytDyVGv7KkhSs+gR9BXJnJWg1Ljkh/56Fh1Xqwa6u6X7zw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/nodemailer" "*"
|
||||
|
||||
"@types/unist@*", "@types/unist@^2.0.0":
|
||||
version "2.0.6"
|
||||
resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz"
|
||||
|
@ -7718,11 +7687,6 @@ balanced-match@^1.0.0:
|
|||
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
base32.js@0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz"
|
||||
integrity sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==
|
||||
|
||||
base64-js@^1.3.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
|
||||
|
@ -8740,11 +8704,6 @@ emoji-regex@^9.2.2:
|
|||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
|
||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||
|
||||
encoding-japanese@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz"
|
||||
integrity sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==
|
||||
|
||||
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz"
|
||||
|
@ -10074,11 +10033,6 @@ hast-util-whitespace@^3.0.0:
|
|||
dependencies:
|
||||
"@types/hast" "^3.0.0"
|
||||
|
||||
he@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz"
|
||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||
|
||||
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
|
||||
|
@ -10098,17 +10052,6 @@ html-parse-stringify@^3.0.1:
|
|||
dependencies:
|
||||
void-elements "3.1.0"
|
||||
|
||||
html-to-text@9.0.3:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.3.tgz"
|
||||
integrity sha512-hxDF1kVCF2uw4VUJ3vr2doc91pXf2D5ngKcNviSitNkhP9OMOaJkDrFIFL6RMvko7NisWTEiqGpQ9LAxcVok1w==
|
||||
dependencies:
|
||||
"@selderee/plugin-htmlparser2" "^0.10.0"
|
||||
deepmerge "^4.2.2"
|
||||
dom-serializer "^2.0.0"
|
||||
htmlparser2 "^8.0.1"
|
||||
selderee "^0.10.0"
|
||||
|
||||
html-to-text@9.0.5:
|
||||
version "9.0.5"
|
||||
resolved "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz"
|
||||
|
@ -10235,13 +10178,6 @@ iconv-lite@0.4.24:
|
|||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
iconv-lite@0.6.3, iconv-lite@^0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz"
|
||||
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||
|
||||
ics@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/ics/-/ics-3.1.0.tgz"
|
||||
|
@ -10375,11 +10311,6 @@ invariant@^2.2.4:
|
|||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
ipv6-normalize@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz"
|
||||
integrity sha512-Bm6H79i01DjgGTCWjUuCjJ6QDo1HB96PT/xCYuyJUP9WFbVDrLSbG4EZCvOCun2rNswZb0c3e4Jt/ws795esHA==
|
||||
|
||||
iron-session@^6.3.1:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.npmjs.org/iron-session/-/iron-session-6.3.1.tgz"
|
||||
|
@ -10976,26 +10907,6 @@ levn@^0.4.1:
|
|||
prelude-ls "^1.2.1"
|
||||
type-check "~0.4.0"
|
||||
|
||||
libbase64@1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/libbase64/-/libbase64-1.2.1.tgz"
|
||||
integrity sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==
|
||||
|
||||
libmime@5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.npmjs.org/libmime/-/libmime-5.2.0.tgz"
|
||||
integrity sha512-X2U5Wx0YmK0rXFbk67ASMeqYIkZ6E5vY7pNWRKtnNzqjvdYYG8xtPDpCnuUEnPU9vlgNev+JoSrcaKSUaNvfsw==
|
||||
dependencies:
|
||||
encoding-japanese "2.0.0"
|
||||
iconv-lite "0.6.3"
|
||||
libbase64 "1.2.1"
|
||||
libqp "2.0.1"
|
||||
|
||||
libqp@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/libqp/-/libqp-2.0.1.tgz"
|
||||
integrity sha512-Ka0eC5LkF3IPNQHJmYBWljJsw0UvM6j+QdKRbWyCdTmYwvIDE6a7bCm0UkTAL/K+3KXK5qXT/ClcInU01OpdLg==
|
||||
|
||||
lilconfig@^2.0.5, lilconfig@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz"
|
||||
|
@ -11006,13 +10917,6 @@ lines-and-columns@^1.1.6:
|
|||
resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
linkify-it@4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz"
|
||||
integrity sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
|
||||
linkify-react@^4.1.3:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/linkify-react/-/linkify-react-4.1.3.tgz#461d348b4bdab3fcd0452ae1b5bbc22536395b97"
|
||||
|
@ -11169,30 +11073,6 @@ magic-string@^0.30.3:
|
|||
dependencies:
|
||||
"@jridgewell/sourcemap-codec" "^1.4.15"
|
||||
|
||||
mailparser@^3.5.0:
|
||||
version "3.6.3"
|
||||
resolved "https://registry.npmjs.org/mailparser/-/mailparser-3.6.3.tgz"
|
||||
integrity sha512-Yi6poKSsZsmjEcUexv3H4w4+TIeyN9u3+TCdC43VK7fe4rUOGDJ3wL4kMhNLiTOScCA1Rpzldv1hcf6g1MLtZQ==
|
||||
dependencies:
|
||||
encoding-japanese "2.0.0"
|
||||
he "1.2.0"
|
||||
html-to-text "9.0.3"
|
||||
iconv-lite "0.6.3"
|
||||
libmime "5.2.0"
|
||||
linkify-it "4.0.1"
|
||||
mailsplit "5.4.0"
|
||||
nodemailer "6.8.0"
|
||||
tlds "1.236.0"
|
||||
|
||||
mailsplit@5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.npmjs.org/mailsplit/-/mailsplit-5.4.0.tgz"
|
||||
integrity sha512-wnYxX5D5qymGIPYLwnp6h8n1+6P6vz/MJn5AzGjZ8pwICWssL+CCQjWBIToOVHASmATot4ktvlLo6CyLfOXWYA==
|
||||
dependencies:
|
||||
libbase64 "1.2.1"
|
||||
libmime "5.2.0"
|
||||
libqp "2.0.1"
|
||||
|
||||
map-obj@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
|
||||
|
@ -11959,16 +11839,6 @@ node-releases@^2.0.8:
|
|||
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz"
|
||||
integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==
|
||||
|
||||
nodemailer@6.7.3:
|
||||
version "6.7.3"
|
||||
resolved "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.3.tgz"
|
||||
integrity sha512-KUdDsspqx89sD4UUyUKzdlUOper3hRkDVkrKh/89G+d9WKsU5ox51NWS4tB1XR5dPUdR4SP0E3molyEfOvSa3g==
|
||||
|
||||
nodemailer@6.8.0:
|
||||
version "6.8.0"
|
||||
resolved "https://registry.npmjs.org/nodemailer/-/nodemailer-6.8.0.tgz"
|
||||
integrity sha512-EjYvSmHzekz6VNkNd12aUqAco+bOkRe3Of5jVhltqKhEsjw/y0PYPJfp83+s9Wzh1dspYAkUW/YNQ350NATbSQ==
|
||||
|
||||
nodemailer@^6.9.9:
|
||||
version "6.9.9"
|
||||
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.9.tgz#4549bfbf710cc6addec5064dd0f19874d24248d9"
|
||||
|
@ -12315,14 +12185,6 @@ parse5@^7.0.0:
|
|||
dependencies:
|
||||
entities "^4.4.0"
|
||||
|
||||
parseley@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.npmjs.org/parseley/-/parseley-0.11.0.tgz"
|
||||
integrity sha512-VfcwXlBWgTF+unPcr7yu3HSSA6QUdDaDnrHcytVfj5Z8azAyKBDrYnSIfeSxlrEayndNcLmrXzg+Vxbo6DWRXQ==
|
||||
dependencies:
|
||||
leac "^0.6.0"
|
||||
peberminta "^0.8.0"
|
||||
|
||||
parseley@^0.12.0:
|
||||
version "0.12.1"
|
||||
resolved "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz"
|
||||
|
@ -12399,11 +12261,6 @@ pathval@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25"
|
||||
integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==
|
||||
|
||||
peberminta@^0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.npmjs.org/peberminta/-/peberminta-0.8.0.tgz"
|
||||
integrity sha512-YYEs+eauIjDH5nUEGi18EohWE0nV2QbGTqmxQcqgZ/0g+laPCQmuIqq7EBLVi9uim9zMgfJv0QBZEnQ3uHw/Tw==
|
||||
|
||||
peberminta@^0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz"
|
||||
|
@ -13453,7 +13310,7 @@ safe-regex-test@^1.0.0:
|
|||
get-intrinsic "^1.1.3"
|
||||
is-regex "^1.1.4"
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
|
||||
"safer-buffer@>= 2.1.2 < 3":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
@ -13487,13 +13344,6 @@ section-matter@^1.0.0:
|
|||
extend-shallow "^2.0.1"
|
||||
kind-of "^6.0.0"
|
||||
|
||||
selderee@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.npmjs.org/selderee/-/selderee-0.10.0.tgz"
|
||||
integrity sha512-DEL/RW/f4qLw/NrVg97xKaEBC8IpzIG2fvxnzCp3Z4yk4jQ3MXom+Imav9wApjxX2dfS3eW7x0DXafJr85i39A==
|
||||
dependencies:
|
||||
parseley "^0.11.0"
|
||||
|
||||
selderee@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz"
|
||||
|
@ -13642,25 +13492,6 @@ smoothscroll-polyfill@^0.4.4:
|
|||
resolved "https://registry.npmjs.org/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.4.tgz"
|
||||
integrity sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg==
|
||||
|
||||
smtp-server@^3.11.0:
|
||||
version "3.11.0"
|
||||
resolved "https://registry.npmjs.org/smtp-server/-/smtp-server-3.11.0.tgz"
|
||||
integrity sha512-j/W6mEKeMNKuiM9oCAAjm87agPEN1O3IU4cFLT4ZOCyyq3UXN7HiIXF+q7izxJcYSar15B/JaSxcijoPCR8Tag==
|
||||
dependencies:
|
||||
base32.js "0.1.0"
|
||||
ipv6-normalize "1.0.1"
|
||||
nodemailer "6.7.3"
|
||||
|
||||
smtp-tester@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/smtp-tester/-/smtp-tester-2.1.0.tgz#ed67ef933767cacb8defcbf0683f29d75335a1ca"
|
||||
integrity sha512-HfOBdHkdwoBO+Qb06H8ShVEc08nnvDbtYWzdT5iQMIeInBdLKu17XOhuaC79uM24zPApRfN3JAg627TIy3y/Ww==
|
||||
dependencies:
|
||||
"@types/mailparser" "^3.4.0"
|
||||
"@types/smtp-server" "^3.5.7"
|
||||
mailparser "^3.5.0"
|
||||
smtp-server "^3.11.0"
|
||||
|
||||
socket.io-adapter@~2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12"
|
||||
|
@ -14320,11 +14151,6 @@ tinyspy@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a"
|
||||
integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==
|
||||
|
||||
tlds@1.236.0:
|
||||
version "1.236.0"
|
||||
resolved "https://registry.npmjs.org/tlds/-/tlds-1.236.0.tgz"
|
||||
integrity sha512-oP2PZ3KeGlgpHgsEfrtva3/K9kzsJUNliQSbCfrJ7JMCWFoCdtG+9YMq/g2AnADQ1v5tVlbtvKJZ4KLpy/P6MA==
|
||||
|
||||
to-absolute-glob@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz"
|
||||
|
@ -14587,11 +14413,6 @@ typescript@^5.2.2:
|
|||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz"
|
||||
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
|
||||
|
||||
uc.micro@^1.0.1:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz"
|
||||
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||
|
||||
unbox-primitive@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz"
|
||||
|
|
Loading…
Add table
Reference in a new issue