From: Alexander Ebert Date: Thu, 20 Jul 2017 17:23:22 +0000 (+0200) Subject: Added a simple SMTP test X-Git-Tag: 3.1.0_Alpha_1~234 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=c6f36059e0992c2ed3551db2fe81b059c5f684be;p=GitHub%2FWoltLab%2FWCF.git Added a simple SMTP test Closes #2342 --- diff --git a/wcfsetup/install/files/acp/templates/__optionEmailSmtpTest.tpl b/wcfsetup/install/files/acp/templates/__optionEmailSmtpTest.tpl new file mode 100644 index 0000000000..6a22dc1a4a --- /dev/null +++ b/wcfsetup/install/files/acp/templates/__optionEmailSmtpTest.tpl @@ -0,0 +1,17 @@ +{if $category->categoryName === 'general'} + +{/if} diff --git a/wcfsetup/install/files/acp/templates/option.tpl b/wcfsetup/install/files/acp/templates/option.tpl index d8bd8941b2..c0dc383395 100644 --- a/wcfsetup/install/files/acp/templates/option.tpl +++ b/wcfsetup/install/files/acp/templates/option.tpl @@ -95,6 +95,7 @@ +{include file='__optionEmailSmtpTest'} {include file='__optionRewriteTest'} {include file='footer'} diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Option/EmailSmtpTest.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Option/EmailSmtpTest.js new file mode 100644 index 0000000000..22dc160aaf --- /dev/null +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Option/EmailSmtpTest.js @@ -0,0 +1,116 @@ +define(['Ajax', 'Core', 'Language'], function(Ajax, Core, Language) { + "use strict"; + + var _buttonRunTest = null; + var _container = null; + + return { + init: function () { + var smtpCheckbox = null; + elBySelAll('input[name="values[mail_send_method]"]', undefined, (function (radioCheckbox) { + radioCheckbox.addEventListener('change', this._onChange.bind(this)); + + if (radioCheckbox.value === 'smtp') smtpCheckbox = radioCheckbox; + }).bind(this)); + + Core.triggerEvent(smtpCheckbox, 'change'); + }, + + _onChange: function (event) { + var checkbox = event.currentTarget; + + if (checkbox.value === 'smtp' && checkbox.checked) { + if (_container === null) this._initUi(checkbox); + + elShow(_container); + } + else if (_container !== null) { + elHide(_container); + } + }, + + _initUi: function (checkbox) { + var html = '
' + Language.get('wcf.acp.email.smtp.test') + '
'; + html += '
'; + html += ''; + html += '' + Language.get('wcf.acp.email.smtp.test.description') + ''; + html += '
'; + + _container = elCreate('dl'); + _container.innerHTML = html; + + _buttonRunTest = elBySel('button', _container); + _buttonRunTest.addEventListener(WCF_CLICK_EVENT, this._onClick.bind(this)); + + var insertAfter = checkbox.closest('dl'); + insertAfter.parentNode.insertBefore(_container, insertAfter.nextSibling); + }, + + _onClick: function (event) { + event.preventDefault(); + + _buttonRunTest.disabled = true; + _buttonRunTest.innerHTML = ' ' + Language.get('wcf.global.loading'); + + var innerError = _buttonRunTest.nextElementSibling; + if (innerError && innerError.classList.contains('innerError')) elRemove(innerError); + + window.setTimeout((function () { + Ajax.api(this, { + parameters: { + host: elById('mail_smtp_host').value, + port: elById('mail_smtp_port').value, + startTls: elBySel('input[name="values[mail_smtp_starttls]"]:checked').value, + user: elById('mail_smtp_user').value, + password: elById('mail_smtp_password').value + } + }); + }).bind(this), 100); + }, + + _ajaxSuccess: function (data) { + var result = data.returnValues.validationResult; + if (result === '') { + this._resetButton(true); + } + else { + this._resetButton(false, result); + } + }, + + _ajaxFailure: function (data) { + var result = ''; + if (data && data.returnValues && data.returnValues.fieldName) { + result = Language.get('wcf.acp.email.smtp.test.error.empty.' + data.returnValues.fieldName); + } + + this._resetButton(false, result); + + return (result === ''); + }, + + _resetButton: function (success, errorMessage) { + _buttonRunTest.disabled = false; + + if (success) _buttonRunTest.innerHTML = ' ' + Language.get('wcf.acp.email.smtp.test.run.success'); + else _buttonRunTest.innerHTML = Language.get('wcf.acp.email.smtp.test.run'); + + if (errorMessage) { + var innerError = elCreate('small'); + innerError.className = 'innerError'; + innerError.textContent = errorMessage; + _buttonRunTest.parentNode.insertBefore(innerError, _buttonRunTest.nextElementSibling); + } + }, + + _ajaxSetup: function () { + return { + data: { + actionName: 'emailSmtpTest', + className: 'wcf\\data\\option\\OptionAction' + }, + silent: true + }; + } + }; +}); diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ajax.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ajax.js index 15a4947e9b..2f3b45f2e6 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ajax.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ajax.js @@ -26,6 +26,9 @@ define(['AjaxRequest', 'Core', 'ObjectMap'], function(AjaxRequest, Core, ObjectM * @return {AjaxRequest} */ api: function(callbackObject, data, success, failure) { + // Fetch AjaxRequest, as it cannot be provided because of a circular dependency + if (AjaxRequest === undefined) AjaxRequest = require('AjaxRequest'); + if (typeof data !== 'object') data = {}; var request = _requests.get(callbackObject); diff --git a/wcfsetup/install/files/lib/data/option/OptionAction.class.php b/wcfsetup/install/files/lib/data/option/OptionAction.class.php index f3de428e98..2f00dc81bd 100644 --- a/wcfsetup/install/files/lib/data/option/OptionAction.class.php +++ b/wcfsetup/install/files/lib/data/option/OptionAction.class.php @@ -1,6 +1,9 @@ - * @package WoltLabSuite\Core\Data$2 * + * @package WoltLabSuite\Core\Data\Option + * * @method Option create() * @method OptionEditor[] getObjects() * @method OptionEditor getSingleObject() @@ -37,7 +41,7 @@ class OptionAction extends AbstractDatabaseObjectAction { /** * @inheritDoc */ - protected $requireACP = ['create', 'delete', 'import', 'update', 'updateAll']; + protected $requireACP = ['create', 'delete', 'emailSmtpTest', 'import', 'update', 'updateAll']; /** * Validates permissions and parameters. @@ -68,4 +72,43 @@ class OptionAction extends AbstractDatabaseObjectAction { // create data call_user_func([$this->className, 'updateAll'], $this->parameters['data']); } + + /** + * Validates the basic SMTP connection parameters. + * + * @throws UserInputException + */ + public function validateEmailSmtpTest() { + WCF::getSession()->checkPermissions($this->permissionsUpdate); + + $this->readString('host'); + $this->readInteger('port'); + $this->readString('startTls'); + + $this->readString('user', true); + $this->readString('password', true); + if (!empty($this->parameters['user']) && empty($this->parameters['password'])) { + throw new UserInputException('password'); + } + else if (empty($this->parameters['user']) && !empty($this->parameters['password'])) { + throw new UserInputException('user'); + } + } + + /** + * Runs a simple test of the SMTP connection. + * + * @return string[] + */ + public function emailSmtpTest() { + $smtp = new SmtpEmailTransport( + $this->parameters['host'], + $this->parameters['port'], + $this->parameters['user'], + $this->parameters['password'], + $this->parameters['startTls'] + ); + + return ['validationResult' => $smtp->testConnection()]; + } } diff --git a/wcfsetup/install/files/lib/system/email/transport/SmtpEmailTransport.class.php b/wcfsetup/install/files/lib/system/email/transport/SmtpEmailTransport.class.php index e19c2964b9..717524a514 100644 --- a/wcfsetup/install/files/lib/system/email/transport/SmtpEmailTransport.class.php +++ b/wcfsetup/install/files/lib/system/email/transport/SmtpEmailTransport.class.php @@ -6,6 +6,7 @@ use wcf\system\email\Email; use wcf\system\email\Mailbox; use wcf\system\exception\SystemException; use wcf\system\io\RemoteFile; +use wcf\system\WCF; use wcf\util\StringUtil; /** @@ -107,6 +108,51 @@ class SmtpEmailTransport implements IEmailTransport { $this->disconnect(); } + /** + * Tests the connection by establishing a connection and optionally + * providing user credentials. Returns the error message or an empty + * string on success. + * + * @return string + */ + public function testConnection() { + try { + $this->connect(10); + $this->auth(); + } + catch (SystemException $e) { + if (strpos($e->getMessage(), 'Can not connect to') === 0) { + return WCF::getLanguage()->get('wcf.acp.email.smtp.test.error.hostUnknown'); + } + + return $e->getMessage(); + } + catch (PermanentFailure $e) { + if (strpos($e->getMessage(), 'Remote SMTP server does not support EHLO') === 0) { + return WCF::getLanguage()->get('wcf.acp.email.smtp.test.error.notTlsSupport'); + } + else if (strpos($e->getMessage(), 'Remote SMTP server does not advertise STARTTLS') === 0) { + return WCF::getLanguage()->get('wcf.acp.email.smtp.test.error.notTlsSupport'); + } + else if (strpos($e->getMessage(), "Remote SMTP server reported permanent error code: 535 (") === 0) { + return WCF::getLanguage()->get('wcf.acp.email.smtp.test.error.badAuth'); + } + + return $e->getMessage(); + } + catch (TransientFailure $e) { + if (strpos($e->getMessage(), 'Enabling TLS failed') === 0) { + return WCF::getLanguage()->get('wcf.acp.email.smtp.test.error.tlsFailed'); + } + + return $e->getMessage(); + } + + $this->disconnect(); + + return ''; + } + /** * Reads a server reply and validates it against the given expected status codes. * Returns a tuple [ status code, reply text ]. @@ -177,10 +223,13 @@ class SmtpEmailTransport implements IEmailTransport { * Connects to the server and enables STARTTLS if available. Bails * out if STARTTLS is not available and connection is set to 'encrypt'. * + * @param integer $overrideTimeout * @throws PermanentFailure */ - protected function connect() { - $this->connection = new RemoteFile($this->host, $this->port); + protected function connect($overrideTimeout = null) { + if ($overrideTimeout === null) $this->connection = new RemoteFile($this->host, $this->port); + else $this->connection = new RemoteFile($this->host, $this->port, $overrideTimeout); + $this->read([220]); try { diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index aa23d4a6b8..f3feabce91 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -396,6 +396,20 @@ + + +
Hinweis: Es handelt sich hierbei nur um einen sehr oberflächlichen Test. Ein erfolgreicher Versand von E-Mails kann auch beim Bestehen dieses Tests nicht abschließend garantiert werden.]]>
+ + + + + + + + + +
+ diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index 09a1bcb1bb..212d3b4b20 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -379,6 +379,20 @@ + + +
Notice: This is only a very basic test. Passing it does not guarantee emails to be successfully delivered!]]>
+ + + + + + + + + +
+