This commit is contained in:
Leandro Facchinetti 2021-03-10 10:30:08 +00:00
parent 6f7f1ffe3d
commit c051b786df
4 changed files with 78 additions and 32 deletions

14
configuration.local.js Normal file
View File

@ -0,0 +1,14 @@
module.exports = (require) => {
const killTheNewsletter = require(".").default;
const { webApplication, emailApplication } = killTheNewsletter();
webApplication.listen(new URL(webApplication.get("url")).port, () => {
console.log(`Web server started at ${webApplication.get("url")}`);
});
emailApplication.listen(webApplication.get("email port"), () => {
console.log(
`Email server started on port ${webApplication.get("email port")}`
);
});
};

42
package-lock.json generated
View File

@ -16,6 +16,7 @@
"crypto-random-string": "^3.3.1", "crypto-random-string": "^3.3.1",
"escape-string-regexp": "^4.0.0", "escape-string-regexp": "^4.0.0",
"express": "^4.17.1", "express": "^4.17.1",
"fs-extra": "^9.1.0",
"mailparser": "^3.1.0", "mailparser": "^3.1.0",
"smtp-server": "^3.8.0" "smtp-server": "^3.8.0"
}, },
@ -24,6 +25,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/express": "^4.17.11", "@types/express": "^4.17.11",
"@types/fs-extra": "^9.0.8",
"@types/jest": "^26.0.20", "@types/jest": "^26.0.20",
"@types/mailparser": "^3.0.2", "@types/mailparser": "^3.0.2",
"@types/node": "^14.14.33", "@types/node": "^14.14.33",
@ -1072,6 +1074,15 @@
"@types/range-parser": "*" "@types/range-parser": "*"
} }
}, },
"node_modules/@types/fs-extra": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.8.tgz",
"integrity": "sha512-bnlTVTwq03Na7DpWxFJ1dvnORob+Otb8xHyUqUWhqvz/Ksg8+JXPlR52oeMSZ37YEOa5PyccbgUNutiQdi13TA==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/graceful-fs": { "node_modules/@types/graceful-fs": {
"version": "4.1.5", "version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
@ -1557,7 +1568,6 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
"dev": true,
"engines": { "engines": {
"node": ">= 4.0.0" "node": ">= 4.0.0"
} }
@ -3481,7 +3491,6 @@
"version": "9.1.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
"dependencies": { "dependencies": {
"at-least-node": "^1.0.0", "at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0", "graceful-fs": "^4.2.0",
@ -3496,7 +3505,6 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
} }
@ -3722,8 +3730,7 @@
"node_modules/graceful-fs": { "node_modules/graceful-fs": {
"version": "4.2.6", "version": "4.2.6",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
"dev": true
}, },
"node_modules/growly": { "node_modules/growly": {
"version": "1.3.0", "version": "1.3.0",
@ -5116,7 +5123,6 @@
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"dependencies": { "dependencies": {
"universalify": "^2.0.0" "universalify": "^2.0.0"
}, },
@ -5128,7 +5134,6 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
} }
@ -9894,6 +9899,15 @@
"@types/range-parser": "*" "@types/range-parser": "*"
} }
}, },
"@types/fs-extra": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.8.tgz",
"integrity": "sha512-bnlTVTwq03Na7DpWxFJ1dvnORob+Otb8xHyUqUWhqvz/Ksg8+JXPlR52oeMSZ37YEOa5PyccbgUNutiQdi13TA==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/graceful-fs": { "@types/graceful-fs": {
"version": "4.1.5", "version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
@ -10308,8 +10322,7 @@
"at-least-node": { "at-least-node": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
"dev": true
}, },
"atob": { "atob": {
"version": "2.1.2", "version": "2.1.2",
@ -11793,7 +11806,6 @@
"version": "9.1.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
"requires": { "requires": {
"at-least-node": "^1.0.0", "at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0", "graceful-fs": "^4.2.0",
@ -11804,8 +11816,7 @@
"universalify": { "universalify": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
"dev": true
} }
} }
}, },
@ -11971,8 +11982,7 @@
"graceful-fs": { "graceful-fs": {
"version": "4.2.6", "version": "4.2.6",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
"dev": true
}, },
"growly": { "growly": {
"version": "1.3.0", "version": "1.3.0",
@ -13045,7 +13055,6 @@
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"requires": { "requires": {
"graceful-fs": "^4.1.6", "graceful-fs": "^4.1.6",
"universalify": "^2.0.0" "universalify": "^2.0.0"
@ -13054,8 +13063,7 @@
"universalify": { "universalify": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
"dev": true
} }
} }
}, },

View File

@ -16,7 +16,7 @@
"bugs": "https://github.com/leafac/kill-the-newsletter/issues", "bugs": "https://github.com/leafac/kill-the-newsletter/issues",
"homepage": "https://github.com/leafac/kill-the-newsletter#readme", "homepage": "https://github.com/leafac/kill-the-newsletter#readme",
"scripts": { "scripts": {
"start": "ts-node-dev --poll src/index.ts", "start": "ts-node-dev --poll src/index.ts configuration.local.js",
"test": "prettier --check \"src/**/*\" --end-of-line auto && jest", "test": "prettier --check \"src/**/*\" --end-of-line auto && jest",
"prepare": "tsc" "prepare": "tsc"
}, },
@ -28,11 +28,13 @@
"crypto-random-string": "^3.3.1", "crypto-random-string": "^3.3.1",
"escape-string-regexp": "^4.0.0", "escape-string-regexp": "^4.0.0",
"express": "^4.17.1", "express": "^4.17.1",
"fs-extra": "^9.1.0",
"mailparser": "^3.1.0", "mailparser": "^3.1.0",
"smtp-server": "^3.8.0" "smtp-server": "^3.8.0"
}, },
"devDependencies": { "devDependencies": {
"@types/express": "^4.17.11", "@types/express": "^4.17.11",
"@types/fs-extra": "^9.0.8",
"@types/jest": "^26.0.20", "@types/jest": "^26.0.20",
"@types/mailparser": "^3.0.2", "@types/mailparser": "^3.0.2",
"@types/node": "^14.14.33", "@types/node": "^14.14.33",

View File

@ -1,22 +1,41 @@
import path from "path";
import express from "express"; import express from "express";
import { SMTPServer } from "smtp-server"; import { SMTPServer } from "smtp-server";
import mailparser from "mailparser"; import mailparser from "mailparser";
import * as sanitizeXMLString from "sanitize-xml-string"; import escapeStringRegexp from "escape-string-regexp";
import * as entities from "entities"; import fs from "fs-extra";
import R from "escape-string-regexp";
import { JSDOM } from "jsdom";
import { promises as fs } from "fs";
import writeFileAtomic from "write-file-atomic";
import cryptoRandomString from "crypto-random-string"; import cryptoRandomString from "crypto-random-string";
import html from "tagged-template-noop";
export const WEB_PORT = process.env.WEB_PORT ?? 8000; const VERSION = require("../package.json").version;
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 ?? "localhost";
export const ISSUE_REPORT =
process.env.ISSUE_REPORT ?? "mailto:kill-the-newsletter@leafac.com";
export default function killTheNewsletter(
rootDirectory: string
): { webApplication: express.Express; emailApplication: SMTPServer } {
const webApplication = express();
webApplication.set("url", "http://localhost:4000");
webApplication.set("email port", 2525);
webApplication.set("email host", "localhost");
webApplication.set("administrator", "kill-the-newsletter@leafac.com");
const emailApplication = new SMTPServer();
return { webApplication, emailApplication };
}
if (require.main === module) {
console.log(`Kill the Newsletter!/${VERSION}`);
const configurationFile = path.resolve(
process.argv[2] ?? path.join(process.cwd(), "configuration.js")
);
require(configurationFile)(require);
console.log(`Configuration file loaded from ${configurationFile}.`);
}
/*
export const webServer = express() export const webServer = express()
.use(["/feeds", "/alternate"], (req, res, next) => { .use(["/feeds", "/alternate"], (req, res, next) => {
res.header("X-Robots-Tag", "noindex"); res.header("X-Robots-Tag", "noindex");
@ -97,7 +116,9 @@ export const emailServer = new SMTPServer({
session.envelope.rcptTo.map(({ address }) => address) session.envelope.rcptTo.map(({ address }) => address)
)) { )) {
const match = address.match( const match = address.match(
new RegExp(`^(?<identifier>\\w+)@${R(EMAIL_DOMAIN)}$`) new RegExp(
`^(?<identifier>\\w+)@${escapeStringRegexp(EMAIL_DOMAIN)}$`
)
); );
if (match?.groups === undefined) continue; if (match?.groups === undefined) continue;
const identifier = match.groups.identifier.toLowerCase(); const identifier = match.groups.identifier.toLowerCase();
@ -340,3 +361,4 @@ function X(string: string): string {
function H(string: string): string { function H(string: string): string {
return entities.encodeHTML(sanitizeXMLString.sanitize(string)); return entities.encodeHTML(sanitizeXMLString.sanitize(string));
} }
*/