This commit is contained in:
parent
bc07c01ba7
commit
4131c21645
|
@ -18,6 +18,7 @@
|
|||
"@types/mailparser": "^2.7.0",
|
||||
"@types/node": "^13.9.1",
|
||||
"@types/node-fetch": "^2.5.5",
|
||||
"@types/nodemailer": "^6.4.0",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-dom": "^16.9.5",
|
||||
"@types/smtp-server": "^3.5.3",
|
||||
|
@ -25,6 +26,7 @@
|
|||
"concurrently": "^5.1.0",
|
||||
"jest": "^25.1.0",
|
||||
"node-fetch": "^2.6.0",
|
||||
"nodemailer": "^6.4.5",
|
||||
"nodemon": "^2.0.2",
|
||||
"prettier": "^1.19.1",
|
||||
"typescript": "^3.8.3"
|
||||
|
|
|
@ -33,6 +33,7 @@ const webApp = express()
|
|||
});
|
||||
|
||||
export const emailServer = new SMTPServer({
|
||||
authOptional: true,
|
||||
async onData(stream, session, callback) {
|
||||
const paths = session.envelope.rcptTo.flatMap(({ address }) => {
|
||||
const match = address.match(/^(\w+)@kill-the-newsletter.com$/);
|
||||
|
@ -44,7 +45,7 @@ export const emailServer = new SMTPServer({
|
|||
});
|
||||
if (paths.length === 0) return callback();
|
||||
const email = await simpleParser(stream);
|
||||
const entry = Entry({
|
||||
const { entry } = Entry({
|
||||
title: email.subject,
|
||||
author: email.from.text,
|
||||
content: typeof email.html !== "boolean" ? email.html : email.textAsHtml
|
||||
|
@ -54,8 +55,10 @@ export const emailServer = new SMTPServer({
|
|||
fs.readFileSync(path).toString()
|
||||
);
|
||||
xml.feed.updated = now();
|
||||
if (xml.feed.entry === undefined) xml.feed.entry = [];
|
||||
xml.feed.entry.unshift(entry);
|
||||
while (renderXML(xml).length > 500_000) xml.feed.entry.pop();
|
||||
while (xml.feed.entry.length > 0 && renderXML(xml).length > 500_000)
|
||||
xml.feed.entry.pop();
|
||||
fs.writeFileSync(path, renderXML(xml));
|
||||
}
|
||||
callback();
|
||||
|
@ -275,7 +278,7 @@ function feedURL(token: string) {
|
|||
return `https://www.kill-the-newsletter.com/feeds/${token}.xml`;
|
||||
}
|
||||
|
||||
function feedEmail(token: string) {
|
||||
export function feedEmail(token: string) {
|
||||
return `${token}@kill-the-newsletter.com`;
|
||||
}
|
||||
|
||||
|
|
60
src/test.ts
60
src/test.ts
|
@ -1,17 +1,61 @@
|
|||
import { developmentWebServer, emailServer, feedPath } from ".";
|
||||
import { developmentWebServer, emailServer, feedPath, feedEmail } from ".";
|
||||
import { createTransport } from "nodemailer";
|
||||
import fetch from "node-fetch";
|
||||
import fs from "fs";
|
||||
|
||||
test("create feed", async () => {
|
||||
const token = await createFeed();
|
||||
const feed = fs.readFileSync(feedPath(token)).toString();
|
||||
|
||||
expect(feed).toMatch("My Feed");
|
||||
expect(readFeed(token)).toMatch("My Feed");
|
||||
});
|
||||
|
||||
test("receive email", async () => {
|
||||
const token = await createFeed();
|
||||
})
|
||||
describe("receive email", () => {
|
||||
const transporter = createTransport({
|
||||
host: "localhost",
|
||||
port: 2525,
|
||||
tls: { rejectUnauthorized: false }
|
||||
});
|
||||
|
||||
test("HTML content", async () => {
|
||||
const token = await createFeed();
|
||||
await transporter.sendMail({
|
||||
from: "publisher@example.com",
|
||||
to: feedEmail(token),
|
||||
subject: "New Message",
|
||||
html: "<p>HTML content</p>"
|
||||
});
|
||||
const feed = readFeed(token);
|
||||
expect(feed).toMatch("publisher@example.com");
|
||||
expect(feed).toMatch("New Message");
|
||||
expect(feed).toMatch("HTML content");
|
||||
});
|
||||
|
||||
test("text content", async () => {
|
||||
const token = await createFeed();
|
||||
await transporter.sendMail({
|
||||
from: "publisher@example.com",
|
||||
to: feedEmail(token),
|
||||
subject: "New Message",
|
||||
text: "TEXT content"
|
||||
});
|
||||
const feed = readFeed(token);
|
||||
expect(feed).toMatch("TEXT content");
|
||||
});
|
||||
|
||||
test("truncation", async () => {
|
||||
const token = await createFeed();
|
||||
for (const repetition of [...new Array(4).keys()])
|
||||
await transporter.sendMail({
|
||||
from: "publisher@example.com",
|
||||
to: feedEmail(token),
|
||||
subject: "New Message",
|
||||
text: `REPETITION ${repetition} `.repeat(10_000)
|
||||
});
|
||||
const feed = readFeed(token);
|
||||
expect(feed).toMatch("REPETITION 3");
|
||||
expect(feed).not.toMatch("REPETITION 0");
|
||||
}, 10_000);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
developmentWebServer.close();
|
||||
|
@ -26,3 +70,7 @@ async function createFeed(): Promise<string> {
|
|||
const responseText = await response.text();
|
||||
return responseText.match(/(\w{20}).xml/)![1];
|
||||
}
|
||||
|
||||
function readFeed(token: string): string {
|
||||
return fs.readFileSync(feedPath(token)).toString();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue