mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-02-03 21:30:06 +01:00
feat: closes #13009, add dedicated test smtp button
which uses the dirty settings on the page add clarification under send test email button add missing lang keys
This commit is contained in:
@@ -30,14 +30,20 @@
|
||||
"smtp-transport.pool-help": "Pooling connections prevents NodeBB from creating a new connection for every email. This option only applies if SMTP Transport is enabled.",
|
||||
"smtp-transport.allow-self-signed": "Allow self-signed certificates",
|
||||
"smtp-transport.allow-self-signed-help": "Enabling this setting will allow you to use self-signed or invalid TLS certificates.",
|
||||
"smtp-transport.test-success": "SMTP Test email sent successfully.",
|
||||
|
||||
"template": "Edit Email Template",
|
||||
"template.select": "Select Email Template",
|
||||
"template.revert": "Revert to Original",
|
||||
"test-smtp-settings": "Test SMTP Settings",
|
||||
"testing": "Email Testing",
|
||||
"testing.success": "Test Email Sent.",
|
||||
"testing.select": "Select Email Template",
|
||||
"testing.send": "Send Test Email",
|
||||
"testing.send-help": "The test email will be sent to the currently logged in user's email address.",
|
||||
"testing.send-help-plugin": "<strong>\"%1\"</strong> will be used to send test emails.",
|
||||
"testing.send-help-smtp": "SMTP transport is enabled and will be used to send emails.",
|
||||
"testing.send-help-no-plugin": "No emailer plugin is installed to send emails, nodemailer will be used by default.",
|
||||
"testing.send-help": "The test email will be sent to the currently logged in user's email address using the saved settings on this page. ",
|
||||
"subscriptions": "Email Digests",
|
||||
"subscriptions.disable": "Disable email digests",
|
||||
"subscriptions.hour": "Digest Hour",
|
||||
|
||||
@@ -6,6 +6,7 @@ define('admin/settings/email', ['ace/ace', 'alerts', 'admin/settings'], function
|
||||
let emailEditor;
|
||||
|
||||
module.init = function () {
|
||||
configureSmtpTester();
|
||||
configureEmailTester();
|
||||
configureEmailEditor();
|
||||
handleDigestHourChange();
|
||||
@@ -26,6 +27,29 @@ define('admin/settings/email', ['ace/ace', 'alerts', 'admin/settings'], function
|
||||
socket.emit('admin.user.restartJobs');
|
||||
}
|
||||
|
||||
function configureSmtpTester() {
|
||||
$('[data-action="email.smtp.test"]').on('click', function () {
|
||||
const smtpOptions = {};
|
||||
$('[data-field^="email:smtp"]').each(function (index, el) {
|
||||
const $el = $(el);
|
||||
const key = $el.attr('data-field');
|
||||
if ($el.is(':checkbox')) {
|
||||
smtpOptions[key] = $el.is(':checked');
|
||||
} else {
|
||||
smtpOptions[key] = $el.val();
|
||||
}
|
||||
});
|
||||
|
||||
socket.emit('admin.email.testSmtp', { smtp: smtpOptions }, function (err) {
|
||||
if (err) {
|
||||
console.error(err.message);
|
||||
return alerts.error(err);
|
||||
}
|
||||
alerts.success('[[admin/settings/email:smtp-transport.test-success]]');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function configureEmailTester() {
|
||||
$('button[data-action="email.test"]').off('click').on('click', function () {
|
||||
socket.emit('admin.email.test', { template: $('#test-email').val() }, function (err) {
|
||||
@@ -33,7 +57,7 @@ define('admin/settings/email', ['ace/ace', 'alerts', 'admin/settings'], function
|
||||
console.error(err.message);
|
||||
return alerts.error(err);
|
||||
}
|
||||
alerts.success('Test Email Sent');
|
||||
alerts.success('[[admin/settings/email:testing.success]]');
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ const api = require('../../api');
|
||||
const pagination = require('../../pagination');
|
||||
const helpers = require('../helpers');
|
||||
const translator = require('../../translator');
|
||||
const plugins = require('../../plugins');
|
||||
|
||||
const settingsController = module.exports;
|
||||
|
||||
@@ -114,9 +115,14 @@ settingsController.uploads = async (req, res) => {
|
||||
|
||||
settingsController.email = async (req, res) => {
|
||||
const emails = await emailer.getTemplates(meta.config);
|
||||
const hooks = plugins.loadedHooks['static:email.send'];
|
||||
const emailerPlugin = hooks && hooks.length ? hooks[0].id : null;
|
||||
const smtpEnabled = parseInt(meta.config['email:smtpTransport:enabled'], 10) === 1;
|
||||
|
||||
res.render('admin/settings/email', {
|
||||
title: '[[admin/menu:settings/email]]',
|
||||
emailerPlugin,
|
||||
smtpEnabled,
|
||||
emails: emails,
|
||||
sendable: emails.filter(e => !e.path.includes('_plaintext') && !e.path.includes('partials')).map(tpl => tpl.path),
|
||||
services: emailer.listServices(),
|
||||
|
||||
@@ -56,8 +56,7 @@ const smtpSettingsChanged = (config) => {
|
||||
|
||||
const getHostname = () => {
|
||||
const configUrl = nconf.get('url');
|
||||
const parsed = url.parse(configUrl);
|
||||
return parsed.hostname;
|
||||
return new URL(configUrl).hostname;
|
||||
};
|
||||
|
||||
const buildCustomTemplates = async (config) => {
|
||||
@@ -120,51 +119,55 @@ Emailer.setupFallbackTransport = (config) => {
|
||||
winston.verbose('[emailer] Setting up fallback transport');
|
||||
// Enable SMTP transport if enabled in ACP
|
||||
if (parseInt(config['email:smtpTransport:enabled'], 10) === 1) {
|
||||
const smtpOptions = {
|
||||
name: getHostname(),
|
||||
pool: config['email:smtpTransport:pool'],
|
||||
};
|
||||
|
||||
if (config['email:smtpTransport:user'] || config['email:smtpTransport:pass']) {
|
||||
smtpOptions.auth = {
|
||||
user: config['email:smtpTransport:user'],
|
||||
pass: config['email:smtpTransport:pass'],
|
||||
};
|
||||
}
|
||||
|
||||
if (config['email:smtpTransport:service'] === 'nodebb-custom-smtp') {
|
||||
smtpOptions.port = config['email:smtpTransport:port'];
|
||||
smtpOptions.host = config['email:smtpTransport:host'];
|
||||
|
||||
if (config['email:smtpTransport:security'] === 'NONE') {
|
||||
smtpOptions.secure = false;
|
||||
smtpOptions.requireTLS = false;
|
||||
smtpOptions.ignoreTLS = true;
|
||||
} else if (config['email:smtpTransport:security'] === 'STARTTLS') {
|
||||
smtpOptions.secure = false;
|
||||
smtpOptions.requireTLS = true;
|
||||
smtpOptions.ignoreTLS = false;
|
||||
} else {
|
||||
// meta.config['email:smtpTransport:security'] === 'ENCRYPTED' or undefined
|
||||
smtpOptions.secure = true;
|
||||
smtpOptions.requireTLS = true;
|
||||
smtpOptions.ignoreTLS = false;
|
||||
}
|
||||
} else {
|
||||
smtpOptions.service = String(config['email:smtpTransport:service']);
|
||||
}
|
||||
if (config['email:smtpTransport:allow-self-signed']) {
|
||||
smtpOptions.tls = {
|
||||
rejectUnauthorized: false,
|
||||
};
|
||||
}
|
||||
Emailer.transports.smtp = nodemailer.createTransport(smtpOptions);
|
||||
Emailer.transports.smtp = Emailer.createSmtpTransport(config);
|
||||
Emailer.fallbackTransport = Emailer.transports.smtp;
|
||||
} else {
|
||||
Emailer.fallbackTransport = Emailer.transports.sendmail;
|
||||
}
|
||||
};
|
||||
|
||||
Emailer.createSmtpTransport = (config) => {
|
||||
const smtpOptions = {
|
||||
name: getHostname(),
|
||||
pool: config['email:smtpTransport:pool'],
|
||||
};
|
||||
|
||||
if (config['email:smtpTransport:user'] || config['email:smtpTransport:pass']) {
|
||||
smtpOptions.auth = {
|
||||
user: config['email:smtpTransport:user'],
|
||||
pass: config['email:smtpTransport:pass'],
|
||||
};
|
||||
}
|
||||
|
||||
if (config['email:smtpTransport:service'] === 'nodebb-custom-smtp') {
|
||||
smtpOptions.port = config['email:smtpTransport:port'];
|
||||
smtpOptions.host = config['email:smtpTransport:host'];
|
||||
|
||||
if (config['email:smtpTransport:security'] === 'NONE') {
|
||||
smtpOptions.secure = false;
|
||||
smtpOptions.requireTLS = false;
|
||||
smtpOptions.ignoreTLS = true;
|
||||
} else if (config['email:smtpTransport:security'] === 'STARTTLS') {
|
||||
smtpOptions.secure = false;
|
||||
smtpOptions.requireTLS = true;
|
||||
smtpOptions.ignoreTLS = false;
|
||||
} else {
|
||||
// meta.config['email:smtpTransport:security'] === 'ENCRYPTED' or undefined
|
||||
smtpOptions.secure = true;
|
||||
smtpOptions.requireTLS = true;
|
||||
smtpOptions.ignoreTLS = false;
|
||||
}
|
||||
} else {
|
||||
smtpOptions.service = String(config['email:smtpTransport:service']);
|
||||
}
|
||||
if (config['email:smtpTransport:allow-self-signed']) {
|
||||
smtpOptions.tls = {
|
||||
rejectUnauthorized: false,
|
||||
};
|
||||
}
|
||||
return nodemailer.createTransport(smtpOptions);
|
||||
};
|
||||
|
||||
Emailer.registerApp = (expressApp) => {
|
||||
app = expressApp;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const nconf = require('nconf');
|
||||
const winston = require('winston');
|
||||
|
||||
const meta = require('../../meta');
|
||||
@@ -8,6 +9,7 @@ const userEmail = require('../../user/email');
|
||||
const notifications = require('../../notifications');
|
||||
const emailer = require('../../emailer');
|
||||
const utils = require('../../utils');
|
||||
const user = require('../../user');
|
||||
|
||||
const Email = module.exports;
|
||||
|
||||
@@ -72,3 +74,25 @@ Email.test = async function (socket, data) {
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
Email.testSmtp = async (socket, data) => {
|
||||
try {
|
||||
const smtp = emailer.createSmtpTransport(data.smtp);
|
||||
const content = 'This is a test email sent from NodeBB to verify your SMTP settings are correct.';
|
||||
const { hostname } = new URL(nconf.get('url'));
|
||||
const toEmail = await user.getUserField(socket.uid, 'email');
|
||||
await smtp.sendMail({
|
||||
to: toEmail,
|
||||
subject: `[${meta.config.title}] SMTP Settings Test Email`,
|
||||
html: content,
|
||||
text: content,
|
||||
from: {
|
||||
name: meta.config['email:from_name'] || 'NodeBB',
|
||||
address: meta.config['email:from'] || `no-reply@${hostname}`,
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
winston.error(err.stack);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
@@ -167,10 +167,13 @@
|
||||
[[admin/settings/email:smtp-transport.username-help]]
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="email:smtpTransport:pass">[[admin/settings/email:smtp-transport.password]]</label>
|
||||
<input id="email:smtpTransport:pass" type="password" class="form-control input-lg" data-field="email:smtpTransport:pass" autocomplete="off" />
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-primary text-nowrap" type="button" data-action="email.smtp.test">[[admin/settings/email:test-smtp-settings]]</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="email-testing" class="mb-4">
|
||||
@@ -181,14 +184,23 @@
|
||||
<div class="d-flex justify-content-between gap-1">
|
||||
<select id="test-email" class="form-select">
|
||||
{{{ each sendable }}}
|
||||
<option value="{@value}">{@value}</option>
|
||||
<option value="{@value}" {{{ if (@value == "test")}}} selected{{{ end }}}>{@value}</option>
|
||||
{{{ end }}}
|
||||
</select>
|
||||
<button class="btn btn-primary text-nowrap" type="button" data-action="email.test">[[admin/settings/email:testing.send]]</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="form-text">
|
||||
[[admin/settings/email:testing.send-help]]
|
||||
[[admin/settings/email:testing.send-help]]<br/>
|
||||
{{{ if emailerPlugin }}}
|
||||
[[admin/settings/email:testing.send-help-plugin, {emailerPlugin}]]
|
||||
{{{ else }}}
|
||||
{{{ if smtpEnabled }}}
|
||||
[[admin/settings/email:testing.send-help-smtp]]
|
||||
{{{ else }}}
|
||||
[[admin/settings/email:testing.send-help-no-plugin]]
|
||||
{{{ end }}}
|
||||
{{{ end }}}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user