diff --git a/meshcentral-config-schema.json b/meshcentral-config-schema.json
index 93f91183..60ca628b 100644
--- a/meshcentral-config-schema.json
+++ b/meshcentral-config-schema.json
@@ -785,15 +785,39 @@
"description": "Connects MeshCentral to a SMTP email server, allows MeshCentral to send email messages for 2FA or user notification.",
"type": "object",
"properties": {
- "host": { "type": "string", "format": "hostname" },
- "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
- "from": { "type": "string", "format": "email", "description": "Email address used in the messages from field." },
+ "host": {
+ "type": "string",
+ "format": "hostname"
+ },
+ "port": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 65535
+ },
+ "from": {
+ "type": "string",
+ "format": "email",
+ "description": "Email address used in the messages from field."
+ },
"tls": { "type": "boolean" },
+ "auth": {
+ "type": "object",
+ "properties": {
+ "clientId": { "type": "string" },
+ "clientSecret": { "type": "string" },
+ "refreshTfoken": { "type": "string" }
+ },
+ "required": [ "clientId", "clientSecret", "refreshToken" ]
+ },
"tlscertcheck": { "type": "boolean" },
"tlsstrict": { "type": "boolean" },
- "verifyemail": { "type": "boolean", "default": true, "description": "When set to false, the email format and DNS MX record are not checked." }
+ "verifyemail": {
+ "type": "boolean",
+ "default": true,
+ "description": "When set to false, the email format and DNS MX record are not checked."
+ }
},
- "required": [ "host", "port", "from", "tls" ]
+ "required": [ "from" ]
},
"sendmail": {
"title" : "Send email using the sendmail command",
diff --git a/meshcentral.js b/meshcentral.js
index efc6abe5..49f0aa95 100644
--- a/meshcentral.js
+++ b/meshcentral.js
@@ -1636,7 +1636,7 @@ function CreateMeshCentralServer(config, args) {
obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
obj.mailserver.verify();
if (obj.args.lanonly == true) { addServerWarning("SendGrid server has limited use in LAN mode.", 17); }
- } else if ((obj.config.smtp != null) && (obj.config.smtp.host != null) && (obj.config.smtp.from != null)) {
+ } else if (obj.config.smtp != null) {
// SMTP server
obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
obj.mailserver.verify();
diff --git a/meshmail.js b/meshmail.js
index 71d52fff..589d7be5 100644
--- a/meshmail.js
+++ b/meshmail.js
@@ -30,7 +30,7 @@ module.exports.CreateMeshMail = function (parent, domain) {
const sortCollator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' })
const constants = (obj.parent.crypto.constants ? obj.parent.crypto.constants : require('constants')); // require('constants') is deprecated in Node 11.10, use require('crypto').constants instead.
- function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(//g, '>').replace(//g, '>').replace(/').replace(/\n/g, '').replace(/\t/g, ' '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
// Setup where we read our configuration from
@@ -49,8 +49,19 @@ module.exports.CreateMeshMail = function (parent, domain) {
if (obj.config.smtp.port != null) { options.port = obj.config.smtp.port; }
if (obj.config.smtp.tlscertcheck === false) { options.tls.rejectUnauthorized = false; }
if (obj.config.smtp.tlsstrict === true) { options.tls.secureProtocol = 'SSLv23_method'; options.tls.ciphers = 'RSA+AES:!aNULL:!MD5:!DSS'; options.tls.secureOptions = constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE; }
- if ((obj.config.smtp.user != null) && (obj.config.smtp.pass != null)) { options.auth = { user: obj.config.smtp.user, pass: obj.config.smtp.pass }; }
+ if ((obj.config.smtp.auth != null) && (typeof obj.config.smtp.auth == 'object')) {
+ var user = obj.config.smtp.from;
+ if ((user == null) && (obj.config.smtp.user != null)) { user = obj.config.smtp.user; }
+ if ((obj.config.smtp.auth.user != null) && (typeof obj.config.smtp.auth.user == 'string')) { user = obj.config.smtp.auth.user; }
+ if (user.toLowerCase().endsWith('@gmail.com')) { options = { service: 'gmail', auth: { user: user } }; obj.config.smtp.host = 'gmail'; } else { options.auth = { user: user } }
+ if (obj.config.smtp.auth.type) { options.auth.type = obj.config.smtp.auth.type; }
+ if (obj.config.smtp.auth.clientid) { options.auth.clientId = obj.config.smtp.auth.clientid; options.auth.type = 'OAuth2'; }
+ if (obj.config.smtp.auth.clientsecret) { options.auth.clientSecret = obj.config.smtp.auth.clientsecret; }
+ if (obj.config.smtp.auth.refreshtoken) { options.auth.refreshToken = obj.config.smtp.auth.refreshtoken; }
+ }
+ else if ((obj.config.smtp.user != null) && (obj.config.smtp.pass != null)) { options.auth = { user: obj.config.smtp.user, pass: obj.config.smtp.pass }; }
if (obj.config.smtp.verifyemail == true) { obj.verifyemail = true; }
+
obj.smtpServer = nodemailer.createTransport(options);
} else if (obj.config.sendmail != null) {
// Setup Sendmail
@@ -464,7 +475,11 @@ module.exports.CreateMeshMail = function (parent, domain) {
if (obj.smtpServer == null) return;
obj.smtpServer.verify(function (err, info) {
if (err == null) {
- console.log('SMTP mail server ' + obj.config.smtp.host + ' working as expected.');
+ if (obj.config.smtp.host == 'gmail') {
+ console.log('Gmail server with OAuth working as expected.');
+ } else {
+ console.log('SMTP mail server ' + obj.config.smtp.host + ' working as expected.');
+ }
} else {
// Remove all non-object types from error to avoid a JSON stringify error.
var err2 = {};
diff --git a/package.json b/package.json
index 7d16097d..e77938fd 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,8 @@
"sample-config-advanced.json"
],
"dependencies": {
+ "@yetzt/nedb": "^1.8.0",
+ "archiver": "^4.0.2",
"body-parser": "^1.19.0",
"cbor": "~5.2.0",
"compression": "^1.7.4",
@@ -43,13 +45,24 @@
"express": "^4.17.0",
"express-handlebars": "^5.3.5",
"express-ws": "^4.0.0",
+ "googleapis": "^96.0.0",
+ "image-size": "^1.0.1",
"ipcheck": "^0.1.0",
+ "loadavg-windows": "^1.1.1",
"minimist": "^1.2.5",
"multiparty": "^4.2.1",
- "@yetzt/nedb": "^1.8.0",
"node-forge": "^1.0.0",
+ "node-rdpjs-2": "^0.3.5",
+ "node-windows": "^0.1.4",
+ "nodemailer": "^6.7.2",
+ "otplib": "^10.2.3",
+ "pg": "^8.7.1",
+ "pgtools": "^0.3.2",
+ "ssh2": "^1.7.0",
+ "web-push": "^3.4.5",
"ws": "^5.2.3",
- "yauzl": "^2.10.0"
+ "yauzl": "^2.10.0",
+ "yubikeyotp": "^0.2.0"
},
"engines": {
"node": ">=10.0.0"
diff --git a/public/commander.htm b/public/commander.htm
index ff4dbef2..4f9d5348 100644
--- a/public/commander.htm
+++ b/public/commander.htm
@@ -1,4 +1,4 @@
-
Disconnected
Loading...
System Status
Hardware Information
Event Log
Network Settings
User Accounts
Serial-over-LAN Terminal
Intel® AMT Redirection port or Serial-over-LAN feature is disabled, click here to enable it.
Remote computer is not powered on, click here to issue a power command.
Remote Desktop
Intel® AMT Redirection port or KVM feature is disabled, click here to enable it.
Remote computer is not powered on, click here to issue a power command.
Audit Log
Security Settings
Internet Settings
System Defense
Agent Presence
Storage
Event Subscriptions
Wake Alarms