From d1d6a9ba82012cd549a15bbef22aaebc48ff28cb Mon Sep 17 00:00:00 2001 From: Leandro Facchinetti Date: Fri, 20 Mar 2020 15:08:04 -0400 Subject: [PATCH] . --- src/index.tsx | 53 ++++++++++++++++++++++++++++----------------------- src/test.ts | 27 +++++++++++++------------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 9f701ed..f511ac8 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -23,13 +23,16 @@ const webApp = express() ) .post("/", (req, res) => { const name = req.body.name; - const token = newToken(); - fs.writeFileSync(feedPath(token), renderXML(Feed({ name, token }))); + const identifier = newIdentifier(); + fs.writeFileSync( + feedPath(identifier), + renderXML(Feed({ name, identifier })) + ); res.send( renderHTML(

“{name}” Inbox Created

- +
) ); @@ -41,8 +44,8 @@ const emailApp: SMTPServerOptions = { const paths = session.envelope.rcptTo.flatMap(({ address }) => { const match = address.match(/^(\w+)@kill-the-newsletter.com$/); if (match === null) return []; - const token = match[1]; - const path = feedPath(token); + const identifier = match[1]; + const path = feedPath(identifier); if (!fs.existsSync(path)) return []; return [path]; }); @@ -179,23 +182,23 @@ function Form() { ); } -function Created({ token }: { token: string }) { +function Created({ identifier }: { identifier: string }) { return ( <>

Sign up for the newsletter with
- {feedEmail(token)} + {feedEmail(identifier)}

Subscribe to the Atom feed at
- {feedURL(token)} + {feedURL(identifier)}

Don’t share these addresses.
- They contain a security token that other people could use + They contain an identifier that other people could use
to send you spam and to control your newsletter subscriptions.

@@ -209,7 +212,7 @@ function Created({ token }: { token: string }) { ); } -function Feed({ name, token }: { name: string; token: string }) { +function Feed({ name, identifier }: { name: string; identifier: string }) { return { feed: { $: { xmlns: "http://www.w3.org/2005/Atom" }, @@ -218,7 +221,7 @@ function Feed({ name, token }: { name: string; token: string }) { $: { rel: "self", type: "application/atom+xml", - href: feedURL(token) + href: feedURL(identifier) } }, { @@ -229,15 +232,17 @@ function Feed({ name, token }: { name: string; token: string }) { } } ], - id: id(token), + id: urn(identifier), title: name, - subtitle: `Kill the Newsletter! Inbox “${feedEmail(token)}”`, + subtitle: `Kill the Newsletter! Inbox: ${feedEmail( + identifier + )} → ${feedURL(identifier)}`, updated: now(), ...Entry({ title: `“${name}” Inbox Created`, author: "Kill the Newsletter!", content: ReactDOMServer.renderToStaticMarkup( - + ) }) } @@ -255,7 +260,7 @@ function Entry({ }) { return { entry: { - id: id(newToken()), + id: urn(newIdentifier()), title, author: { name: author }, updated: now(), @@ -264,7 +269,7 @@ function Entry({ }; } -function newToken(): string { +function newIdentifier(): string { return cryptoRandomString({ length: 20, characters: "1234567890qwertyuiopasdfghjklzxcvbnm" @@ -275,20 +280,20 @@ function now(): string { return new Date().toISOString(); } -function feedPath(token: string): string { - return `static/feeds/${token}.xml`; +function feedPath(identifier: string): string { + return `static/feeds/${identifier}.xml`; } -function feedURL(token: string): string { - return `https://www.kill-the-newsletter.com/feeds/${token}.xml`; +function feedURL(identifier: string): string { + return `https://www.kill-the-newsletter.com/feeds/${identifier}.xml`; } -export function feedEmail(token: string): string { - return `${token}@kill-the-newsletter.com`; +export function feedEmail(identifier: string): string { + return `${identifier}@kill-the-newsletter.com`; } -function id(token: string): string { - return `urn:kill-the-newsletter:${token}`; +function urn(identifier: string): string { + return `urn:kill-the-newsletter:${identifier}`; } function renderHTML(component: React.ReactElement): string { diff --git a/src/test.ts b/src/test.ts index efb8041..9288746 100644 --- a/src/test.ts +++ b/src/test.ts @@ -4,9 +4,9 @@ import axios from "axios"; import qs from "qs"; test("create feed", async () => { - const token = await createFeed(); + const identifier = await createFeed(); - expect(await readFeed(token)).toMatch("My Feed"); + expect(await readFeed(identifier)).toMatch("My Feed"); }); describe("receive email", () => { @@ -17,41 +17,41 @@ describe("receive email", () => { }); test("HTML content", async () => { - const token = await createFeed(); + const identifier = await createFeed(); await transporter.sendMail({ from: "publisher@example.com", - to: feedEmail(token), + to: feedEmail(identifier), subject: "New Message", html: "

HTML content

" }); - const feed = await readFeed(token); + const feed = await readFeed(identifier); expect(feed).toMatch("publisher@example.com"); expect(feed).toMatch("New Message"); expect(feed).toMatch("HTML content"); }); test("text content", async () => { - const token = await createFeed(); + const identifier = await createFeed(); await transporter.sendMail({ from: "publisher@example.com", - to: feedEmail(token), + to: feedEmail(identifier), subject: "New Message", text: "TEXT content" }); - const feed = await readFeed(token); + const feed = await readFeed(identifier); expect(feed).toMatch("TEXT content"); }); test("truncation", async () => { - const token = await createFeed(); + const identifier = await createFeed(); for (const repetition of [...new Array(4).keys()]) await transporter.sendMail({ from: "publisher@example.com", - to: feedEmail(token), + to: feedEmail(identifier), subject: "New Message", text: `REPETITION ${repetition} `.repeat(10_000) }); - const feed = await readFeed(token); + const feed = await readFeed(identifier); expect(feed).toMatch("REPETITION 3"); expect(feed).not.toMatch("REPETITION 0"); }, 10_000); @@ -74,6 +74,7 @@ async function createFeed(): Promise { ).data.match(/(\w{20}).xml/)![1]; } -async function readFeed(token: string): Promise { - return (await axios.get(`http://localhost:8000/feeds/${token}.xml`)).data; +async function readFeed(identifier: string): Promise { + return (await axios.get(`http://localhost:8000/feeds/${identifier}.xml`)) + .data; }