Added email debug, DNS MX check on all outbound emails.

This commit is contained in:
Ylian Saint-Hilaire 2020-03-21 23:13:53 -07:00
parent d089062167
commit 383f757e23
4 changed files with 115 additions and 64 deletions

View File

@ -137,74 +137,103 @@ module.exports.CreateMeshMail = function (parent) {
// Send account login mail / 2 factor token // Send account login mail / 2 factor token
obj.sendAccountLoginMail = function (domain, email, token) { obj.sendAccountLoginMail = function (domain, email, token) {
var template = getTemplateEx('account-login', domain); obj.checkEmail(email, function (checked) {
if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, invitation not possible. if (checked) {
parent.debug('email', "Sending login token to " + email);
// Set all the options. var template = getTemplateEx('account-login', domain);
var options = { email: email, servername: domain.title ? domain.title : 'MeshCentral', token: token }; if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, invitation not possible.
// Send the email // Set all the options.
obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); var options = { email: email, servername: domain.title ? domain.title : 'MeshCentral', token: token };
sendNextMail();
// Send the email
obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) });
sendNextMail();
}
});
}; };
// Send account invitation mail // Send account invitation mail
obj.sendAccountInviteMail = function (domain, username, accountname, email, password) { obj.sendAccountInviteMail = function (domain, username, accountname, email, password) {
var template = getTemplateEx('account-invite', domain); obj.checkEmail(email, function (checked) {
if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, invitation not possible. if (checked) {
parent.debug('email', "Sending account invitation to " + email);
// Set all the options. var template = getTemplateEx('account-invite', domain);
var options = { username: username, accountname: accountname, email: email, servername: domain.title ? domain.title : 'MeshCentral', password: password }; if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, invitation not possible.
// Send the email // Set all the options.
obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); var options = { username: username, accountname: accountname, email: email, servername: domain.title ? domain.title : 'MeshCentral', password: password };
sendNextMail();
// Send the email
obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) });
sendNextMail();
}
});
}; };
// Send account check mail // Send account check mail
obj.sendAccountCheckMail = function (domain, username, email) { obj.sendAccountCheckMail = function (domain, username, email) {
var template = getTemplateEx('account-check', domain); obj.checkEmail(email, function (checked) {
if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, no reset possible. if (checked) {
parent.debug('email', "Sending email verification to " + email);
// Set all the options. var template = getTemplateEx('account-check', domain);
var options = { username: username, email: email, servername: domain.title ? domain.title : 'MeshCentral' }; if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, no reset possible.
options.cookie = obj.parent.encodeCookie({ u: domain.id + '/' + username.toLowerCase(), e: email, a: 1 }, obj.mailCookieEncryptionKey);
// Send the email // Set all the options.
obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); var options = { username: username, email: email, servername: domain.title ? domain.title : 'MeshCentral' };
sendNextMail(); options.cookie = obj.parent.encodeCookie({ u: domain.id + '/' + username.toLowerCase(), e: email, a: 1 }, obj.mailCookieEncryptionKey);
// Send the email
obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) });
sendNextMail();
}
});
}; };
// Send account reset mail // Send account reset mail
obj.sendAccountResetMail = function (domain, username, email) { obj.sendAccountResetMail = function (domain, username, email) {
var template = getTemplateEx('account-reset', domain); obj.checkEmail(email, function (checked) {
if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, don't validate the email address. if (checked) {
parent.debug('email', "Sending account password reset to " + email);
// Set all the options. var template = getTemplateEx('account-reset', domain);
var options = { username: username, email: email, servername: domain.title ? domain.title : 'MeshCentral' }; if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, don't validate the email address.
options.cookie = obj.parent.encodeCookie({ u: domain.id + '/' + username, e: email, a: 2 }, obj.mailCookieEncryptionKey);
// Send the email // Set all the options.
obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); var options = { username: username, email: email, servername: domain.title ? domain.title : 'MeshCentral' };
sendNextMail(); options.cookie = obj.parent.encodeCookie({ u: domain.id + '/' + username, e: email, a: 2 }, obj.mailCookieEncryptionKey);
// Send the email
obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) });
sendNextMail();
}
});
}; };
// Send agent invite mail // Send agent invite mail
obj.sendAgentInviteMail = function (domain, username, email, meshid, name, os, msg, flags, expirehours) { obj.sendAgentInviteMail = function (domain, username, email, meshid, name, os, msg, flags, expirehours) {
var template = getTemplateEx('mesh-invite', domain); obj.checkEmail(email, function (checked) {
if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, don't validate the email address. if (checked) {
parent.debug('email', "Sending agent install invitation to " + email);
var template = getTemplateEx('mesh-invite', domain);
if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, don't validate the email address.
// Set all the template replacement options and generate the final email text (both in txt and html formats). // Set all the template replacement options and generate the final email text (both in txt and html formats).
var options = { username: username, name: name, email: email, installflags: flags, msg: msg, meshid: meshid, meshidhex: meshid.split('/')[2], servername: domain.title ? domain.title : 'MeshCentral' }; var options = { username: username, name: name, email: email, installflags: flags, msg: msg, meshid: meshid, meshidhex: meshid.split('/')[2], servername: domain.title ? domain.title : 'MeshCentral' };
options.windows = ((os == 0) || (os == 1)) ? 1 : 0; options.windows = ((os == 0) || (os == 1)) ? 1 : 0;
options.linux = ((os == 0) || (os == 2)) ? 1 : 0; options.linux = ((os == 0) || (os == 2)) ? 1 : 0;
options.osx = ((os == 0) || (os == 3)) ? 1 : 0; options.osx = ((os == 0) || (os == 3)) ? 1 : 0;
options.link = (os == 4) ? 1 : 0; options.link = (os == 4) ? 1 : 0;
options.linkurl = createInviteLink(domain, meshid, flags, expirehours); options.linkurl = createInviteLink(domain, meshid, flags, expirehours);
// Send the email // Send the email
obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) });
sendNextMail(); sendNextMail();
}
});
}; };
// Send out the next mail in the pending list // Send out the next mail in the pending list
@ -223,6 +252,7 @@ module.exports.CreateMeshMail = function (parent) {
sendNextMail(); // Send the next mail sendNextMail(); // Send the next mail
} else { } else {
obj.retry++; obj.retry++;
parent.debug('email', 'SMTP server failed: ' + JSON.stringify(err));
console.log('SMTP server failed: ' + JSON.stringify(err)); console.log('SMTP server failed: ' + JSON.stringify(err));
if (obj.retry < 6) { setTimeout(sendNextMail, 60000); } // Wait and try again if (obj.retry < 6) { setTimeout(sendNextMail, 60000); } // Wait and try again
} }
@ -238,6 +268,7 @@ module.exports.CreateMeshMail = function (parent) {
// Remove all non-object types from error to avoid a JSON stringify error. // Remove all non-object types from error to avoid a JSON stringify error.
var err2 = {}; var err2 = {};
for (var i in err) { if (typeof (err[i]) != 'object') { err2[i] = err[i]; } } for (var i in err) { if (typeof (err[i]) != 'object') { err2[i] = err[i]; } }
parent.debug('email', 'SMTP mail server ' + parent.config.smtp.host + ' failed: ' + JSON.stringify(err2));
console.log('SMTP mail server ' + parent.config.smtp.host + ' failed: ' + JSON.stringify(err2)); console.log('SMTP mail server ' + parent.config.smtp.host + ' failed: ' + JSON.stringify(err2));
} }
}); });
@ -260,5 +291,18 @@ module.exports.CreateMeshMail = function (parent) {
return '/agentinvite?c=' + parent.encodeCookie({ a: 4, mid: meshid, f: flags, expire: expirehours * 60 }, parent.invitationLinkEncryptionKey); return '/agentinvite?c=' + parent.encodeCookie({ a: 4, mid: meshid, f: flags, expire: expirehours * 60 }, parent.invitationLinkEncryptionKey);
} }
// Check the email domain DNS MX record.
obj.approvedEmailDomains = {};
obj.checkEmail = function (email, func) {
var emailSplit = email.split('@');
if (emailSplit.length != 2) { func(false); return; }
if (obj.approvedEmailDomains[emailSplit[1]] === true) { func(true); return; }
require('dns').resolveMx(emailSplit[1], function (err, addresses) {
parent.debug('email', "checkEmail: " + email + ", " + (err == null));
if (err == null) { obj.approvedEmailDomains[emailSplit[1]] = true; }
func(err == null);
});
}
return obj; return obj;
}; };

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.5.0-q", "version": "0.5.0-r",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

View File

@ -3764,7 +3764,7 @@
"pt": "Tem certeza de que deseja {0} o plug-in: {1}", "pt": "Tem certeza de que deseja {0} o plug-in: {1}",
"ru": "Вы уверенны, что {0} плагин: {1}", "ru": "Вы уверенны, что {0} плагин: {1}",
"xloc": [ "xloc": [
"default.handlebars->27->1553" "default.handlebars->27->1554"
], ],
"zh-chs": "您確定要{0}插件嗎:{1}" "zh-chs": "您確定要{0}插件嗎:{1}"
}, },
@ -4408,7 +4408,7 @@
"pt": "Servidor CIRA", "pt": "Servidor CIRA",
"ru": "CIRA Сервер", "ru": "CIRA Сервер",
"xloc": [ "xloc": [
"default.handlebars->27->1544" "default.handlebars->27->1545"
], ],
"zh-chs": "CIRA服務器" "zh-chs": "CIRA服務器"
}, },
@ -4425,7 +4425,7 @@
"pt": "Comandos do servidor CIRA", "pt": "Comandos do servidor CIRA",
"ru": "CIRA Сервер команды", "ru": "CIRA Сервер команды",
"xloc": [ "xloc": [
"default.handlebars->27->1545" "default.handlebars->27->1546"
], ],
"zh-chs": "CIRA服務器命令" "zh-chs": "CIRA服務器命令"
}, },
@ -4548,7 +4548,7 @@
"pt": "Erro de chamada", "pt": "Erro de chamada",
"ru": "Ошибка вызова", "ru": "Ошибка вызова",
"xloc": [ "xloc": [
"default.handlebars->27->1554" "default.handlebars->27->1555"
], ],
"zh-chs": "通話錯誤" "zh-chs": "通話錯誤"
}, },
@ -4966,7 +4966,7 @@
"pt": "Verificando ...", "pt": "Verificando ...",
"ru": "Проверка...", "ru": "Проверка...",
"xloc": [ "xloc": [
"default.handlebars->27->1550", "default.handlebars->27->1551",
"default.handlebars->27->778" "default.handlebars->27->778"
], ],
"zh-chs": "檢查..." "zh-chs": "檢查..."
@ -5824,7 +5824,7 @@
"pt": "Encaminhador de conexão", "pt": "Encaminhador de conexão",
"ru": "Ретранслятор подключения", "ru": "Ретранслятор подключения",
"xloc": [ "xloc": [
"default.handlebars->27->1543" "default.handlebars->27->1544"
], ],
"zh-chs": "連接繼電器" "zh-chs": "連接繼電器"
}, },
@ -8723,6 +8723,12 @@
], ],
"zh-chs": "郵件認證" "zh-chs": "郵件認證"
}, },
{
"en": "Email Traffic",
"xloc": [
"default.handlebars->27->1538"
]
},
{ {
"cs": "Ověření e-mailu", "cs": "Ověření e-mailu",
"de": "E-Mail-Verifizierung", "de": "E-Mail-Verifizierung",
@ -11386,7 +11392,7 @@
"default.handlebars->27->1223", "default.handlebars->27->1223",
"default.handlebars->27->1229", "default.handlebars->27->1229",
"default.handlebars->27->1521", "default.handlebars->27->1521",
"default.handlebars->27->1542" "default.handlebars->27->1543"
], ],
"zh-chs": "英特爾AMT" "zh-chs": "英特爾AMT"
}, },
@ -13186,7 +13192,7 @@
"pt": "Menos", "pt": "Menos",
"ru": "Меньше", "ru": "Меньше",
"xloc": [ "xloc": [
"default.handlebars->27->1556" "default.handlebars->27->1557"
], ],
"zh-chs": "減" "zh-chs": "減"
}, },
@ -15252,7 +15258,7 @@
"pt": "Mais", "pt": "Mais",
"ru": "Еще", "ru": "Еще",
"xloc": [ "xloc": [
"default.handlebars->27->1555" "default.handlebars->27->1556"
], ],
"zh-chs": "更多" "zh-chs": "更多"
}, },
@ -17996,7 +18002,7 @@
"pt": "Ação do Plugin", "pt": "Ação do Plugin",
"ru": "Действие плагина", "ru": "Действие плагина",
"xloc": [ "xloc": [
"default.handlebars->27->1552", "default.handlebars->27->1553",
"default.handlebars->27->159" "default.handlebars->27->159"
], ],
"zh-chs": "插件動作" "zh-chs": "插件動作"
@ -20738,7 +20744,7 @@
"pt": "Rastreamento de servidor", "pt": "Rastreamento de servidor",
"ru": "Трассировка сервера", "ru": "Трассировка сервера",
"xloc": [ "xloc": [
"default.handlebars->27->1546" "default.handlebars->27->1547"
], ],
"zh-chs": "服務器跟踪" "zh-chs": "服務器跟踪"
}, },
@ -24177,7 +24183,7 @@
"pt": "Atualizado", "pt": "Atualizado",
"ru": "Актуально", "ru": "Актуально",
"xloc": [ "xloc": [
"default.handlebars->27->1551" "default.handlebars->27->1552"
], ],
"zh-chs": "最新" "zh-chs": "最新"
}, },
@ -25251,8 +25257,8 @@
"pt": "Servidor web", "pt": "Servidor web",
"ru": "Веб-сервер", "ru": "Веб-сервер",
"xloc": [ "xloc": [
"default.handlebars->27->1538", "default.handlebars->27->1539",
"default.handlebars->27->1539" "default.handlebars->27->1540"
], ],
"zh-chs": "網絡服務器" "zh-chs": "網絡服務器"
}, },
@ -25269,7 +25275,7 @@
"pt": "Solicitações de servidor Web", "pt": "Solicitações de servidor Web",
"ru": "Запросы веб-сервера", "ru": "Запросы веб-сервера",
"xloc": [ "xloc": [
"default.handlebars->27->1540" "default.handlebars->27->1541"
], ],
"zh-chs": "Web服務器請求" "zh-chs": "Web服務器請求"
}, },
@ -25286,7 +25292,7 @@
"pt": "Encaminhador de soquete da Web", "pt": "Encaminhador de soquete da Web",
"ru": "Ретранслятор Web Socket", "ru": "Ретранслятор Web Socket",
"xloc": [ "xloc": [
"default.handlebars->27->1541" "default.handlebars->27->1542"
], ],
"zh-chs": "Web套接字中繼" "zh-chs": "Web套接字中繼"
}, },
@ -26123,7 +26129,7 @@
"pt": "\\\\'", "pt": "\\\\'",
"ru": "\\\\'", "ru": "\\\\'",
"xloc": [ "xloc": [
"default.handlebars->27->1549" "default.handlebars->27->1550"
], ],
"zh-chs": "\\\\'" "zh-chs": "\\\\'"
}, },
@ -26656,7 +26662,7 @@
"pt": "servertrace.csv", "pt": "servertrace.csv",
"ru": "servertrace.csv", "ru": "servertrace.csv",
"xloc": [ "xloc": [
"default.handlebars->27->1548" "default.handlebars->27->1549"
], ],
"zh-chs": "servertrace.csv" "zh-chs": "servertrace.csv"
}, },
@ -26722,7 +26728,7 @@
"pt": "hora, fonte, mensagem", "pt": "hora, fonte, mensagem",
"ru": "time, source, message", "ru": "time, source, message",
"xloc": [ "xloc": [
"default.handlebars->27->1547" "default.handlebars->27->1548"
], ],
"zh-chs": "時間,來源,訊息" "zh-chs": "時間,來源,訊息"
}, },

View File

@ -10805,6 +10805,7 @@
x += '<div><label><input type=checkbox id=p41c14 ' + ((serverTraceSources.indexOf('agentupdate') >= 0) ? 'checked' : '') + '>' + "MeshAgent update" + '</label></div>'; x += '<div><label><input type=checkbox id=p41c14 ' + ((serverTraceSources.indexOf('agentupdate') >= 0) ? 'checked' : '') + '>' + "MeshAgent update" + '</label></div>';
x += '<div><label><input type=checkbox id=p41c16 ' + ((serverTraceSources.indexOf('cert') >= 0) ? 'checked' : '') + '>' + "Server Certificate" + '</label></div>'; x += '<div><label><input type=checkbox id=p41c16 ' + ((serverTraceSources.indexOf('cert') >= 0) ? 'checked' : '') + '>' + "Server Certificate" + '</label></div>';
x += '<div><label><input type=checkbox id=p41c17 ' + ((serverTraceSources.indexOf('db') >= 0) ? 'checked' : '') + '>' + "Server Database" + '</label></div>'; x += '<div><label><input type=checkbox id=p41c17 ' + ((serverTraceSources.indexOf('db') >= 0) ? 'checked' : '') + '>' + "Server Database" + '</label></div>';
x += '<div><label><input type=checkbox id=p41c18 ' + ((serverTraceSources.indexOf('email') >= 0) ? 'checked' : '') + '>' + "Email Traffic" + '</label></div>';
x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>' + "Web Server" + '</b></div>'; x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>' + "Web Server" + '</b></div>';
x += '<div><label><input type=checkbox id=p41c5 ' + ((serverTraceSources.indexOf('web') >= 0) ? 'checked' : '') + '>' + "Web Server" + '</label></div>'; x += '<div><label><input type=checkbox id=p41c5 ' + ((serverTraceSources.indexOf('web') >= 0) ? 'checked' : '') + '>' + "Web Server" + '</label></div>';
x += '<div><label><input type=checkbox id=p41c6 ' + ((serverTraceSources.indexOf('webrequest') >= 0) ? 'checked' : '') + '>' + "Web Server Requests" + '</label></div>'; x += '<div><label><input type=checkbox id=p41c6 ' + ((serverTraceSources.indexOf('webrequest') >= 0) ? 'checked' : '') + '>' + "Web Server Requests" + '</label></div>';
@ -10821,8 +10822,8 @@
} }
function setServerTracingEx(b) { function setServerTracingEx(b) {
var sources = [], allsources = ['cookie', 'dispatch', 'main', 'peer', 'web', 'webrequest', 'relay', 'webrelaydata', 'webrelay', 'mps', 'mpscmd', 'swarm', 'swarmcmd', 'agentupdate', 'agent', 'cert', 'db']; var sources = [], allsources = ['cookie', 'dispatch', 'main', 'peer', 'web', 'webrequest', 'relay', 'webrelaydata', 'webrelay', 'mps', 'mpscmd', 'swarm', 'swarmcmd', 'agentupdate', 'agent', 'cert', 'db', 'email'];
if (b == 1) { for (var i = 1; i < 18; i++) { try { if (Q('p41c' + i).checked) { sources.push(allsources[i - 1]); } } catch (ex) { } } } if (b == 1) { for (var i = 1; i < 19; i++) { try { if (Q('p41c' + i).checked) { sources.push(allsources[i - 1]); } } catch (ex) { } } }
meshserver.send({ action: 'traceinfo', traceSources: sources }); meshserver.send({ action: 'traceinfo', traceSources: sources });
} }