This commit is contained in:
Leandro Facchinetti 2020-03-22 10:23:05 -04:00
parent d984e361f5
commit 57abf1340d
2 changed files with 36 additions and 30 deletions

View File

@ -4,7 +4,7 @@ import mailparser from "mailparser";
import React from "react"; import React from "react";
import ReactDOMServer from "react-dom/server"; import ReactDOMServer from "react-dom/server";
import xml2js from "xml2js"; import xml2js from "xml2js";
import fs from "fs"; import { promises as fs } from "fs";
import cryptoRandomString from "crypto-random-string"; import cryptoRandomString from "crypto-random-string";
export const webServer = express() export const webServer = express()
@ -19,10 +19,11 @@ export const webServer = express()
) )
) )
) )
.post("/", (req, res) => { .post("/", (req, res, next) => {
(async () => {
const name = req.body.name; const name = req.body.name;
const identifier = createIdentifier(); const identifier = createIdentifier();
fs.writeFileSync( await fs.writeFile(
feedPath(identifier), feedPath(identifier),
renderXML(Feed({ name, identifier })) renderXML(Feed({ name, identifier }))
); );
@ -34,6 +35,7 @@ export const webServer = express()
</Layout> </Layout>
) )
); );
})().catch(next);
}) })
.listen(8000); .listen(8000);
@ -41,15 +43,6 @@ export const emailServer = new SMTPServer({
disabledCommands: ["AUTH", "STARTTLS"], disabledCommands: ["AUTH", "STARTTLS"],
onData(stream, session, callback) { onData(stream, session, callback) {
(async () => { (async () => {
const paths = session.envelope.rcptTo.flatMap(({ address }) => {
const match = address.match(/^(\w+)@kill-the-newsletter.com$/);
if (match === null) return [];
const identifier = match[1];
const path = feedPath(identifier);
if (!fs.existsSync(path)) return [];
return [path];
});
if (paths.length === 0) return callback();
const email = await mailparser.simpleParser(stream); const email = await mailparser.simpleParser(stream);
const { entry } = Entry({ const { entry } = Entry({
title: email.subject, title: email.subject,
@ -57,16 +50,20 @@ export const emailServer = new SMTPServer({
// FIXME: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/43234 / typeof email.html !== "boolean" => email.html !== false // FIXME: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/43234 / typeof email.html !== "boolean" => email.html !== false
content: typeof email.html !== "boolean" ? email.html : email.textAsHtml content: typeof email.html !== "boolean" ? email.html : email.textAsHtml
}); });
for (const path of paths) { for (const { address } of session.envelope.rcptTo) {
const xml = await new xml2js.Parser().parseStringPromise( const match = address.match(/^(\w+)@kill-the-newsletter.com$/);
fs.readFileSync(path, "utf8") if (match === null) continue;
); const identifier = match[1];
const path = feedPath(identifier);
const xmlText = await fs.readFile(path, "utf8").catch(() => null);
if (xmlText === null) continue;
const xml = await new xml2js.Parser().parseStringPromise(xmlText);
xml.feed.updated = now(); xml.feed.updated = now();
if (xml.feed.entry === undefined) xml.feed.entry = []; if (xml.feed.entry === undefined) xml.feed.entry = [];
xml.feed.entry.unshift(entry); xml.feed.entry.unshift(entry);
while (xml.feed.entry.length > 0 && renderXML(xml).length > 500_000) while (xml.feed.entry.length > 0 && renderXML(xml).length > 500_000)
xml.feed.entry.pop(); xml.feed.entry.pop();
fs.writeFileSync(path, renderXML(xml)); await fs.writeFile(path, renderXML(xml));
} }
callback(); callback();
})().catch(callback); })().catch(callback);

View File

@ -49,6 +49,15 @@ describe("receive email", () => {
expect(feed).toMatch("REPETITION 3"); expect(feed).toMatch("REPETITION 3");
expect(feed).not.toMatch("REPETITION 0"); expect(feed).not.toMatch("REPETITION 0");
}); });
test("non-existing address", async () => {
await emailClient.sendMail({
from: "publisher@example.com",
to: `non-existing@kill-the-newsletter.com`,
subject: "New Message",
html: "<p>HTML content</p>"
});
});
}); });
afterAll(() => { afterAll(() => {