Skip to content

Commit

Permalink
MDL-61921 admin: Support XOAUTH2 for outgoing mail
Browse files Browse the repository at this point in the history
  • Loading branch information
HuongNV13 committed Oct 21, 2022
1 parent 44ca802 commit bc80531
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 3 deletions.
26 changes: 26 additions & 0 deletions admin/settings/server.php
Expand Up @@ -442,9 +442,35 @@
'CRAM-MD5' => 'CRAM-MD5',
];

// Get all the issuers.
$issuers = \core\oauth2\api::get_all_issuers();
$enabledissuers = [];
foreach ($issuers as $issuer) {
// Get the enabled issuer only.
if ($issuer->get('enabled')) {
$enabledissuers[] = $issuer;
}
}

if (count($enabledissuers) > 0) {
$authtypeoptions['XOAUTH2'] = 'XOAUTH2';
}

$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));

if (count($enabledissuers) > 0) {
$oauth2services = [
'' => new lang_string('none', 'admin'),
];
foreach ($enabledissuers as $issuer) {
$oauth2services[$issuer->get('id')] = s($issuer->get('name'));
}

$temp->add(new admin_setting_configselect('smtpoauthservice', new lang_string('issuer', 'auth_oauth2'),
new lang_string('configsmtpoauthservice', 'admin'), '', $oauth2services));
}

$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));

Expand Down
29 changes: 29 additions & 0 deletions admin/tests/behat/outgoing_mail.feature
@@ -0,0 +1,29 @@
@core @core_admin
Feature: Outgoing mail configuration
In order to send email from Moodle
As a Moodle administrator
I need to set mail configuration

Background:
Given I log in as "admin"

Scenario: SMTP Auth Type without OAuth 2 Service setup yet
Given I navigate to "Server > Email > Outgoing mail configuration" in site administration
And I should not see "XOAUTH2" in the "SMTP Auth Type" "select"
And I should see "LOGIN" in the "SMTP Auth Type" "select"
And I should see "PLAIN" in the "SMTP Auth Type" "select"

Scenario: SMTP Auth Type with OAuth 2 Service setup
Given I navigate to "Server > OAuth 2 services" in site administration
And I press "Google"
And I should see "Create new service: Google"
And I set the following fields to these values:
| Name | Testing service |
| Client ID | thisistheclientid |
| Client secret | supersecret |
And I press "Save changes"
When I navigate to "Server > Email > Outgoing mail configuration" in site administration
Then I should see "XOAUTH2" in the "SMTP Auth Type" "select"
And I should see "LOGIN" in the "SMTP Auth Type" "select"
And I should see "PLAIN" in the "SMTP Auth Type" "select"
And I should see "Testing service" in the "OAuth 2 Service" "select"
1 change: 1 addition & 0 deletions lang/en/admin.php
Expand Up @@ -363,6 +363,7 @@
$string['configslasharguments'] = '\'Slash arguments\' (using <em>PATH_INFO</em>) is required for SCORM packages and multiple-file resources to display correctly. If your web server doesn\'t support \'slash arguments\' and you are unable to configure it, this setting can be disabled, though it will result in things not working.<br />Note: The use of \'slash arguments\' will be required in future versions of Moodle.';
$string['configsmartpix'] = 'With this on, icons are served through a PHP script that searches the current theme, then all parent themes, then the Moodle /pix folder. This reduces the need to duplicate image files within themes, but has a slight performance cost.';
$string['configsmtpauthtype'] = 'This sets the authentication type to use on smtp server.';
$string['configsmtpoauthservice'] = 'Select the OAuth 2 service that is configured to talk to the smtp server. If the service does not exist yet, you will need to create it. Please note: This setting only runs if the SMTP Auth Type is set to XOAUTH2';
$string['configsmtphosts'] = 'Give the full name of one or more local SMTP servers that Moodle should use to send mail (eg \'mail.a.com\' or \'mail.a.com;mail.b.com\'). To specify a non-default port (i.e other than port 25), you can use the [server]:[port] syntax (eg \'mail.a.com:587\'). For secure connections, port 465 is usually used with SSL, port 587 is usually used with TLS, specify security protocol below if required. If you leave this field blank, Moodle will use the PHP default method of sending mail.';
$string['configsmtpmaxbulk'] = 'Maximum number of messages sent per SMTP session. Grouping messages may speed up the sending of emails. Values lower than 2 force creation of new SMTP session for each email.';
$string['configsmtpsecure'] = 'If SMTP server requires secure connection, specify the correct protocol type.';
Expand Down
36 changes: 34 additions & 2 deletions lib/phpmailer/moodle_phpmailer.php
Expand Up @@ -54,6 +54,10 @@ public function __construct(){

if (!empty($CFG->smtpauthtype)) {
$this->AuthType = $CFG->smtpauthtype;

if ($this->AuthType == 'XOAUTH2') {
$this->process_oauth();
}
}

// Some MTAs may do double conversion of LF if CRLF used, CRLF is required line ending in RFC 822bis.
Expand All @@ -65,7 +69,7 @@ public function __construct(){
}

/**
* Extended AddCustomHeader function in order to stop duplicate
* Extended AddCustomHeader function in order to stop duplicate
* message-ids
* http://tracker.moodle.org/browse/MDL-3681
*/
Expand All @@ -83,7 +87,7 @@ public function addCustomHeader($custom_header, $value = null) {

/**
* Use internal moodles own core_text to encode mimeheaders.
* Fall back to phpmailers inbuilt functions if not
* Fall back to phpmailers inbuilt functions if not
*/
public function encodeHeader($str, $position = 'text') {
$encoded = core_text::encode_mimeheader($str, $this->CharSet);
Expand Down Expand Up @@ -142,4 +146,32 @@ public function postSend() {
return parent::postSend();
}
}

/**
* Config the PHPMailer to use OAUTH if necessary.
*/
private function process_oauth(): void {
global $CFG;

require_once($CFG->libdir . '/phpmailer/moodle_phpmailer_oauth.php');
if (!empty($CFG->smtpoauthservice)) {
// Get the issuer.
$issuer = \core\oauth2\api::get_issuer($CFG->smtpoauthservice);
// Validate the issuer and check if it is enabled or not.
if ($issuer && $issuer->get('enabled')) {
// Get the OAuth Client.
if ($oauthclient = \core\oauth2\api::get_system_oauth_client($issuer)) {
$oauth = new moodle_phpmailer_oauth([
'provider' => $oauthclient,
'clientId' => $oauthclient->get_clientid(),
'clientSecret' => $oauthclient->get_clientsecret(),
'refreshToken' => $oauthclient->get_refresh_token(),
'userName' => $CFG->smtpuser,
]);
// Set the OAuth.
$this->setOAuth($oauth);
}
}
}
}
}
30 changes: 30 additions & 0 deletions lib/phpmailer/moodle_phpmailer_oauth.php
@@ -0,0 +1,30 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Moodle Customised version of the PHPMailer OAuth class
*
* @package core
* @copyright 2022 Huong Nguyen <huongnv13@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class moodle_phpmailer_oauth extends \PHPMailer\PHPMailer\OAuth {

protected function getToken() {
return $this->provider->get_accesstoken()->token;
}

}
2 changes: 1 addition & 1 deletion lib/phpmailer/readme_moodle.txt
Expand Up @@ -7,7 +7,7 @@ For more information on this version of PHPMailer, check out https://github.com/

To upgrade this library:
1. Download the latest release of PHPMailer in https://github.com/PHPMailer/PHPMailer/releases.
2. Remove everything inside lib/phpmailer/ folder except README_MOODLE.txt and moodle_phpmailer.php.
2. Remove everything inside lib/phpmailer/ folder except README_MOODLE.txt, moodle_phpmailer.php and moodle_phpmailer_oauth.php.
3. Extract the contents of the release archive to lib/phpmailer.
4. Remove the following files that were extracted:
- composer.json
Expand Down

0 comments on commit bc80531

Please sign in to comment.