This commit is contained in:
Leandro Facchinetti 2020-03-19 00:20:28 -04:00
parent bc07c01ba7
commit 4131c21645
3 changed files with 62 additions and 9 deletions

View File

@ -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"

View File

@ -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`;
}

View File

@ -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();
}