Extract URLs
This commit is contained in:
parent
64db4b3a7b
commit
4950b2cffe
|
@ -46,7 +46,9 @@
|
||||||
"env": {
|
"env": {
|
||||||
"NODE_ENV": "production",
|
"NODE_ENV": "production",
|
||||||
"WEB_PORT": "8000",
|
"WEB_PORT": "8000",
|
||||||
"EMAIL_PORT": "25"
|
"EMAIL_PORT": "25",
|
||||||
|
"BASE_URL": "https://www.kill-the-newsletter.com",
|
||||||
|
"EMAIL_DOMAIN": "kill-the-newsletter.com"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,9 @@ import cryptoRandomString from "crypto-random-string";
|
||||||
|
|
||||||
export const WEB_PORT = process.env.WEB_PORT ?? 8000;
|
export const WEB_PORT = process.env.WEB_PORT ?? 8000;
|
||||||
export const EMAIL_PORT = process.env.EMAIL_PORT ?? 2525;
|
export const EMAIL_PORT = process.env.EMAIL_PORT ?? 2525;
|
||||||
|
export const BASE_URL = process.env.BASE_URL ?? "http://localhost:8000";
|
||||||
|
export const EMAIL_DOMAIN =
|
||||||
|
process.env.EMAIL_DOMAIN ?? "kill-the-newsletter.com";
|
||||||
|
|
||||||
export const webServer = express()
|
export const webServer = express()
|
||||||
.use(express.static("static"))
|
.use(express.static("static"))
|
||||||
|
@ -49,7 +52,7 @@ export const webServer = express()
|
||||||
next(error);
|
next(error);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.get("/entry", (req, res) =>
|
.get("/alternate", (req, res) =>
|
||||||
res.send(
|
res.send(
|
||||||
renderHTML(
|
renderHTML(
|
||||||
<Layout>
|
<Layout>
|
||||||
|
@ -66,7 +69,7 @@ export const webServer = express()
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="https://www.kill-the-newsletter.com">
|
<a href={BASE_URL}>
|
||||||
<strong>Create an Inbox</strong>
|
<strong>Create an Inbox</strong>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -89,7 +92,7 @@ export const emailServer = new SMTPServer({
|
||||||
typeof email.html === "string" ? email.html : email.textAsHtml ?? "",
|
typeof email.html === "string" ? email.html : email.textAsHtml ?? "",
|
||||||
});
|
});
|
||||||
for (const { address } of session.envelope.rcptTo) {
|
for (const { address } of session.envelope.rcptTo) {
|
||||||
const match = address.match(/^(\w+)@kill-the-newsletter.com$/);
|
const match = address.match(new RegExp(`^(\\w+)@${EMAIL_DOMAIN}$`));
|
||||||
if (match === null) continue;
|
if (match === null) continue;
|
||||||
const identifier = match[1];
|
const identifier = match[1];
|
||||||
const path = feedPath(identifier);
|
const path = feedPath(identifier);
|
||||||
|
@ -213,7 +216,7 @@ function Created({ identifier }: { identifier: string }) {
|
||||||
</p>
|
</p>
|
||||||
<p>Enjoy your readings!</p>
|
<p>Enjoy your readings!</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="https://www.kill-the-newsletter.com">
|
<a href={BASE_URL}>
|
||||||
<strong>Create Another Inbox</strong>
|
<strong>Create Another Inbox</strong>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -234,7 +237,7 @@ function Feed({ name, identifier }: { name: string; identifier: string }) {
|
||||||
{
|
{
|
||||||
"@rel": "alternate",
|
"@rel": "alternate",
|
||||||
"@type": "text/html",
|
"@type": "text/html",
|
||||||
"@href": "https://www.kill-the-newsletter.com/",
|
"@href": `${BASE_URL}/alternate`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
id: urn(identifier),
|
id: urn(identifier),
|
||||||
|
@ -273,7 +276,7 @@ function Entry({
|
||||||
link: {
|
link: {
|
||||||
"@rel": "alternate",
|
"@rel": "alternate",
|
||||||
"@type": "text/html",
|
"@type": "text/html",
|
||||||
"@href": "https://www.kill-the-newsletter.com/entry",
|
"@href": `${BASE_URL}/alternate`,
|
||||||
},
|
},
|
||||||
content: { "@type": "html", "#": content },
|
content: { "@type": "html", "#": content },
|
||||||
},
|
},
|
||||||
|
@ -296,11 +299,11 @@ function feedPath(identifier: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
function feedURL(identifier: string): string {
|
function feedURL(identifier: string): string {
|
||||||
return `https://www.kill-the-newsletter.com/feeds/${identifier}.xml`;
|
return `${BASE_URL}/feeds/${identifier}.xml`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function feedEmail(identifier: string): string {
|
function feedEmail(identifier: string): string {
|
||||||
return `${identifier}@kill-the-newsletter.com`;
|
return `${identifier}@${EMAIL_DOMAIN}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function urn(identifier: string): string {
|
function urn(identifier: string): string {
|
||||||
|
|
28
src/test.ts
28
src/test.ts
|
@ -1,4 +1,4 @@
|
||||||
import { webServer, emailServer, WEB_PORT, EMAIL_PORT } from ".";
|
import { webServer, emailServer, WEB_PORT, EMAIL_PORT, EMAIL_DOMAIN } from ".";
|
||||||
import nodemailer from "nodemailer";
|
import nodemailer from "nodemailer";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
|
@ -15,7 +15,7 @@ describe("receive email", () => {
|
||||||
const before = await getFeed(identifier);
|
const before = await getFeed(identifier);
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
html: "<p>HTML content</p>",
|
html: "<p>HTML content</p>",
|
||||||
});
|
});
|
||||||
|
@ -29,7 +29,7 @@ describe("receive email", () => {
|
||||||
const identifier = await createFeed();
|
const identifier = await createFeed();
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
html: "<p>HTML content</p>",
|
html: "<p>HTML content</p>",
|
||||||
});
|
});
|
||||||
|
@ -43,7 +43,7 @@ describe("receive email", () => {
|
||||||
const identifier = await createFeed();
|
const identifier = await createFeed();
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
text: "TEXT content",
|
text: "TEXT content",
|
||||||
});
|
});
|
||||||
|
@ -55,20 +55,20 @@ describe("receive email", () => {
|
||||||
const identifier = await createFeed();
|
const identifier = await createFeed();
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
text: "TEXT content\n\nhttps://www.kill-the-newsletter.com\n\nMore text",
|
text: "TEXT content\n\nhttps://www.leafac.com\n\nMore text",
|
||||||
});
|
});
|
||||||
const feed = await getFeed(identifier);
|
const feed = await getFeed(identifier);
|
||||||
expect(feed).toMatch("TEXT content");
|
expect(feed).toMatch("TEXT content");
|
||||||
expect(feed).toMatch(`href="https://www.kill-the-newsletter.com"`);
|
expect(feed).toMatch(`href="https://www.leafac.com"`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("invalid XML character in HTML", async () => {
|
test("invalid XML character in HTML", async () => {
|
||||||
const identifier = await createFeed();
|
const identifier = await createFeed();
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
html: "<p>Invalid XML character (backspace): ‘\b’</p>",
|
html: "<p>Invalid XML character (backspace): ‘\b’</p>",
|
||||||
});
|
});
|
||||||
|
@ -80,7 +80,7 @@ describe("receive email", () => {
|
||||||
const identifier = await createFeed();
|
const identifier = await createFeed();
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
text: "Invalid XML character (backspace): ‘\b’",
|
text: "Invalid XML character (backspace): ‘\b’",
|
||||||
});
|
});
|
||||||
|
@ -94,7 +94,7 @@ describe("receive email", () => {
|
||||||
const identifier = await createFeed();
|
const identifier = await createFeed();
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
});
|
});
|
||||||
const feed = await getFeed(identifier);
|
const feed = await getFeed(identifier);
|
||||||
|
@ -105,7 +105,7 @@ describe("receive email", () => {
|
||||||
const identifier = await createFeed();
|
const identifier = await createFeed();
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
html: "<p>HTML content</p>",
|
html: "<p>HTML content</p>",
|
||||||
});
|
});
|
||||||
const feed = await getFeed(identifier);
|
const feed = await getFeed(identifier);
|
||||||
|
@ -117,7 +117,7 @@ describe("receive email", () => {
|
||||||
for (const repetition of [...new Array(4).keys()])
|
for (const repetition of [...new Array(4).keys()])
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
text: `REPETITION ${repetition} `.repeat(10_000),
|
text: `REPETITION ${repetition} `.repeat(10_000),
|
||||||
});
|
});
|
||||||
|
@ -129,7 +129,7 @@ describe("receive email", () => {
|
||||||
test("nonexistent address", async () => {
|
test("nonexistent address", async () => {
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
from: "publisher@example.com",
|
from: "publisher@example.com",
|
||||||
to: "nonexistent@kill-the-newsletter.com",
|
to: `nonexistent@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
html: "<p>HTML content</p>",
|
html: "<p>HTML content</p>",
|
||||||
});
|
});
|
||||||
|
@ -138,7 +138,7 @@ describe("receive email", () => {
|
||||||
test("missing from", async () => {
|
test("missing from", async () => {
|
||||||
const identifier = await createFeed();
|
const identifier = await createFeed();
|
||||||
await emailClient.sendMail({
|
await emailClient.sendMail({
|
||||||
to: `${identifier}@kill-the-newsletter.com`,
|
to: `${identifier}@${EMAIL_DOMAIN}`,
|
||||||
subject: "New Message",
|
subject: "New Message",
|
||||||
html: "<p>HTML content</p>",
|
html: "<p>HTML content</p>",
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue