summary refs log tree commit diff
diff options
context:
space:
mode:
authorPuyodead1 <puyodead@proton.me>2023-01-21 13:03:17 -0500
committerPuyodead1 <puyodead@protonmail.com>2023-02-23 22:35:07 -0500
commit4383fcd4497c67e34d27fc0806824650df34466a (patch)
tree2ec4b966660bfec18e8bb78f0b821d88952c52f9
parentrename SMTPConfigurations to EmailConfiguration (diff)
downloadserver-4383fcd4497c67e34d27fc0806824650df34466a.tar.xz
Add Mailgun transport
-rw-r--r--package-lock.json84
-rw-r--r--package.json3
-rw-r--r--src/util/config/types/EmailConfiguration.ts13
-rw-r--r--src/util/config/types/subconfigurations/email/MailGun.ts22
-rw-r--r--src/util/config/types/subconfigurations/email/SMTP.ts25
-rw-r--r--src/util/config/types/subconfigurations/email/index.ts20
-rw-r--r--src/util/util/Email.ts51
7 files changed, 207 insertions, 11 deletions
diff --git a/package-lock.json b/package-lock.json
index 8d7b1db2..a07a7ec7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -81,6 +81,7 @@
 			},
 			"optionalDependencies": {
 				"erlpack": "^0.1.4",
+				"nodemailer-mailgun-transport": "^2.1.5",
 				"sqlite3": "^5.1.4"
 			}
 		},
@@ -2646,11 +2647,28 @@
 			"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 			"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
 		},
+		"node_modules/axios": {
+			"version": "1.3.4",
+			"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
+			"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
+			"optional": true,
+			"dependencies": {
+				"follow-redirects": "^1.15.0",
+				"form-data": "^4.0.0",
+				"proxy-from-env": "^1.1.0"
+			}
+		},
 		"node_modules/balanced-match": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
 			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
 		},
+		"node_modules/base-64": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
+			"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
+			"optional": true
+		},
 		"node_modules/base64-js": {
 			"version": "1.5.1",
 			"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -2722,6 +2740,12 @@
 			"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
 			"optional": true
 		},
+		"node_modules/bluebird": {
+			"version": "3.7.2",
+			"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+			"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+			"optional": true
+		},
 		"node_modules/body-parser": {
 			"version": "1.20.1",
 			"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
@@ -3203,6 +3227,18 @@
 			"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
 			"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
 		},
+		"node_modules/consolidate": {
+			"version": "0.15.1",
+			"resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz",
+			"integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==",
+			"optional": true,
+			"dependencies": {
+				"bluebird": "^3.1.1"
+			},
+			"engines": {
+				"node": ">= 0.10.0"
+			}
+		},
 		"node_modules/content-disposition": {
 			"version": "0.5.4",
 			"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -4348,6 +4384,26 @@
 			"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
 			"dev": true
 		},
+		"node_modules/follow-redirects": {
+			"version": "1.15.2",
+			"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+			"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+			"funding": [
+				{
+					"type": "individual",
+					"url": "https://github.com/sponsors/RubenVerborgh"
+				}
+			],
+			"optional": true,
+			"engines": {
+				"node": ">=4.0"
+			},
+			"peerDependenciesMeta": {
+				"debug": {
+					"optional": true
+				}
+			}
+		},
 		"node_modules/form-data": {
 			"version": "4.0.0",
 			"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
@@ -5201,6 +5257,17 @@
 				"yallist": "^3.0.2"
 			}
 		},
+		"node_modules/mailgun.js": {
+			"version": "8.1.0",
+			"resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-8.1.0.tgz",
+			"integrity": "sha512-dHGWuG9v8PEOnjMiuSuYvcnEy7sZ/4uJq4ZfYs50fZhUh4qPtVCFwc58JbhM2obvNSstNw4YvsHaVe4Lj/1RsA==",
+			"optional": true,
+			"dependencies": {
+				"axios": "^1.3.3",
+				"base-64": "^1.0.0",
+				"url-join": "^4.0.1"
+			}
+		},
 		"node_modules/make-dir": {
 			"version": "3.1.0",
 			"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -5841,6 +5908,17 @@
 				"node": ">=6.0.0"
 			}
 		},
+		"node_modules/nodemailer-mailgun-transport": {
+			"version": "2.1.5",
+			"resolved": "https://registry.npmjs.org/nodemailer-mailgun-transport/-/nodemailer-mailgun-transport-2.1.5.tgz",
+			"integrity": "sha512-hF7POkaxFgMvYEd5aHLaQJI2511ld+aQlQi7JH6bGjhjlZ33cIbTB9PimlIrLu5XC3z76Kde6e65OIwL9lOdTA==",
+			"optional": true,
+			"dependencies": {
+				"consolidate": "^0.15.1",
+				"form-data": "^4.0.0",
+				"mailgun.js": "^8.0.1"
+			}
+		},
 		"node_modules/nopt": {
 			"version": "5.0.0",
 			"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@@ -7495,6 +7573,12 @@
 				"punycode": "^2.1.0"
 			}
 		},
+		"node_modules/url-join": {
+			"version": "4.0.1",
+			"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
+			"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
+			"optional": true
+		},
 		"node_modules/url-parse": {
 			"version": "1.5.10",
 			"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
diff --git a/package.json b/package.json
index eabc247e..8a6c0405 100644
--- a/package.json
+++ b/package.json
@@ -115,6 +115,7 @@
 	},
 	"optionalDependencies": {
 		"erlpack": "^0.1.4",
-		"sqlite3": "^5.1.4"
+		"sqlite3": "^5.1.4",
+		"nodemailer-mailgun-transport": "^2.1.5"
 	}
 }
diff --git a/src/util/config/types/EmailConfiguration.ts b/src/util/config/types/EmailConfiguration.ts
index 1e4a0361..34550f4c 100644
--- a/src/util/config/types/EmailConfiguration.ts
+++ b/src/util/config/types/EmailConfiguration.ts
@@ -16,10 +16,13 @@
 	along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
 
+import {
+	MailGunConfiguration,
+	SMTPConfiguration,
+} from "./subconfigurations/email";
+
 export class EmailConfiguration {
-	host: string | null = null;
-	port: number | null = null;
-	secure: boolean | null = null;
-	username: string | null = null;
-	password: string | null = null;
+	provider: string | null = null;
+	smtp: SMTPConfiguration = new SMTPConfiguration();
+	mailgun: MailGunConfiguration = new MailGunConfiguration();
 }
diff --git a/src/util/config/types/subconfigurations/email/MailGun.ts b/src/util/config/types/subconfigurations/email/MailGun.ts
new file mode 100644
index 00000000..52cd9069
--- /dev/null
+++ b/src/util/config/types/subconfigurations/email/MailGun.ts
@@ -0,0 +1,22 @@
+/*
+	Fosscord: A FOSS re-implementation and extension of the Discord.com backend.
+	Copyright (C) 2023 Fosscord and Fosscord Contributors
+	
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU Affero General Public License as published
+	by the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+	
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU Affero General Public License for more details.
+	
+	You should have received a copy of the GNU Affero General Public License
+	along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+export class MailGunConfiguration {
+	apiKey: string | null = null;
+	domain: string | null = null;
+}
diff --git a/src/util/config/types/subconfigurations/email/SMTP.ts b/src/util/config/types/subconfigurations/email/SMTP.ts
new file mode 100644
index 00000000..11eb9e14
--- /dev/null
+++ b/src/util/config/types/subconfigurations/email/SMTP.ts
@@ -0,0 +1,25 @@
+/*
+	Fosscord: A FOSS re-implementation and extension of the Discord.com backend.
+	Copyright (C) 2023 Fosscord and Fosscord Contributors
+	
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU Affero General Public License as published
+	by the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+	
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU Affero General Public License for more details.
+	
+	You should have received a copy of the GNU Affero General Public License
+	along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+export class SMTPConfiguration {
+	host: string | null = null;
+	port: number | null = null;
+	secure: boolean | null = null;
+	username: string | null = null;
+	password: string | null = null;
+}
diff --git a/src/util/config/types/subconfigurations/email/index.ts b/src/util/config/types/subconfigurations/email/index.ts
new file mode 100644
index 00000000..92fe9184
--- /dev/null
+++ b/src/util/config/types/subconfigurations/email/index.ts
@@ -0,0 +1,20 @@
+/*
+	Fosscord: A FOSS re-implementation and extension of the Discord.com backend.
+	Copyright (C) 2023 Fosscord and Fosscord Contributors
+	
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU Affero General Public License as published
+	by the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+	
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU Affero General Public License for more details.
+	
+	You should have received a copy of the GNU Affero General Public License
+	along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+export * from "./MailGun";
+export * from "./SMTP";
diff --git a/src/util/util/Email.ts b/src/util/util/Email.ts
index 9688c3c5..b8019cbd 100644
--- a/src/util/util/Email.ts
+++ b/src/util/util/Email.ts
@@ -55,6 +55,8 @@ export function adjustEmail(email?: string): string | undefined {
 export const Email: {
 	transporter: Transporter | null;
 	init: () => Promise<void>;
+	initSMTP: () => Promise<void>;
+	initMailgun: () => Promise<void>;
 	generateVerificationLink: (id: string, email: string) => Promise<string>;
 	sendVerificationEmail: (user: User, email: string) => Promise<any>;
 	doReplacements: (
@@ -72,9 +74,22 @@ export const Email: {
 } = {
 	transporter: null,
 	init: async function () {
-		const { host, port, secure, username, password } = Config.get().smtp;
-		if (!host || !port || !secure || !username || !password) return;
-		console.log(`[SMTP] connect: ${host}`);
+		const { provider } = Config.get().email;
+		if (!provider) return;
+
+		if (provider === "smtp") await this.initSMTP();
+		else if (provider === "mailgun") await this.initMailgun();
+		else throw new Error(`Unknown email provider: ${provider}`);
+	},
+	initSMTP: async function () {
+		const { host, port, secure, username, password } =
+			Config.get().email.smtp;
+		if (!host || !port || !secure || !username || !password)
+			return console.error(
+				"[Email] SMTP has not been configured correctly.",
+			);
+
+		console.log(`[Email] Initializing SMTP transport: ${host}`);
 		this.transporter = nodemailer.createTransport({
 			host,
 			port,
@@ -87,14 +102,40 @@ export const Email: {
 
 		await this.transporter.verify((error, _) => {
 			if (error) {
-				console.error(`[SMTP] error: ${error}`);
+				console.error(`[Email] SMTP error: ${error}`);
 				this.transporter?.close();
 				this.transporter = null;
 				return;
 			}
-			console.log(`[SMTP] Ready`);
+			console.log(`[Email] Ready`);
 		});
 	},
+	initMailgun: async function () {
+		const { apiKey, domain } = Config.get().email.mailgun;
+		if (!apiKey || !domain)
+			return console.error(
+				"[Email] Mailgun has not been configured correctly.",
+			);
+
+		try {
+			const mg = require("nodemailer-mailgun-transport");
+			const auth = {
+				auth: {
+					api_key: apiKey,
+					domain: domain,
+				},
+			};
+
+			console.log(`[Email] Initializing Mailgun transport...`);
+			this.transporter = nodemailer.createTransport(mg(auth));
+			console.log(`[Email] Ready`);
+		} catch {
+			console.error(
+				"[Email] Mailgun transport is not installed. Please run `npm install nodemailer-mailgun-transport --save` to install it.",
+			);
+			return;
+		}
+	},
 	/**
 	 * Replaces all placeholders in an email template with the correct values
 	 */