HEX
Server: Apache
System: Linux WWW 6.1.0-40-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20) x86_64
User: web11 (1011)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/apklausos/application/core/plugins/GoogleOAuthSMTP/GoogleOAuthSMTP.php
<?php

use League\OAuth2\Client\Provider\Google;
use LimeSurvey\PluginManager\SmtpOAuthPluginBase;
use PHPMailer\PHPMailer\PHPMailer;

class GoogleOAuthSMTP extends SmtpOAuthPluginBase
{
    protected $storage = 'DbStorage';
    protected static $description = 'Core: Adds Google OAuth support for email sending';
    protected static $name = 'GoogleOAuthSMTP';

    /** @inheritdoc this plugin doesn't have any public method */
    public $allowedPublicMethods = [];

    /** @inheritdoc */
    protected $credentialAttributes = ['clientId', 'clientSecret'];

    protected $settings = [
        'help' => [
            'type' => 'info',
            'content' => '',
        ],
        'clientId' => [
            'type' => 'string',
            'label' => 'Client ID',
        ],
        'clientSecret' => [
            'type' => 'string',
            'label' => 'Client Secret',
        ],
    ];

    public function init()
    {
        $this->subscribe('listEmailPlugins');
        $this->subscribe('afterSelectEmailPlugin');
        $this->subscribe('MailerConstruct');    // Handler defined in SmtpOAuthPluginBase
        $this->subscribe('beforePrepareRedirectToAuthPage');
        $this->subscribe('beforeRedirectToAuthPage');   // Handler defined in SmtpOAuthPluginBase
        $this->subscribe('afterReceiveOAuthResponse');  // Handler defined in SmtpOAuthPluginBase

        $this->subscribe('beforeEmailDispatch');
    }

    /**
     * @inheritdoc
     * Update the information content
     */
    public function getPluginSettings($getValues = true)
    {
        $settings = parent::getPluginSettings($getValues);
        $settings['help']['content'] = $this->getHelpContent();
        $settings['clientId']['label'] = gT("Client ID");
        $settings['clientSecret']['label'] = gT("Client Secret");

        return $settings;
    }

    private function getHelpContent()
    {
        $this->subscribe('getPluginTwigPath');
        $data = [
            'redirectUri' => $this->getRedirectUri(),
            'isHttps' => (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on'),
        ];
        return Yii::app()->twigRenderer->renderPartial('/Help.twig', $data);

        // Translations here just so the translations bot can pick them up.
        $lang = [
            gT("Help"),
            gT("Prerequisites:"),
            gT("Access LimeSurvey over HTTPS."),
            gT("Currently not served over HTTPS"),
            gT("Instructions:"),
            gT("Setup the OAuth 2.0 Web Application in %s."),
            gT("Google Cloud Platform Console"),
            gT("Redirect URI:"),
            gT("You can find more details %shere%s."),
            gT("Activate the plugin."),
            gT("Set the 'Client ID' and 'Client Secret' below and save the settings."),
            gT("Click the 'Get Token' button to open Google's consent screen in a new window."),
            gT("Follow the steps in the consent screen and check the requested permissions."),
            gT("Switch the 'Enabled' setting to 'On' and save."),
        ];
    }

    /**
     * @inheritdoc
     */
    protected function getProvider($credentials)
    {
        $redirectUri = $this->getRedirectUri();
        $params = [
            'clientId' => $credentials['clientId'],
            'clientSecret' => $credentials['clientSecret'],
            'redirectUri' => $redirectUri,
            'accessType' => 'offline',
            'prompt' => 'consent',
        ];
        return new Google($params);
    }

    /**
     * Adds view's path to twig system
     */
    public function getPluginTwigPath()
    {
        $viewPath = dirname(__FILE__) . "/views";
        $this->getEvent()->append('add', array($viewPath));
    }

    /**
     * Adds the plugin to the list of SMTP OAuth plugins
     */
    public function listEmailPlugins()
    {
        $event = $this->getEvent();
        $event->append('plugins', [
            'google' => $this->getEmailPluginInfo()
        ]);
    }

    /**
     * @inheritdoc
     */
    public function getOAuthConfigForMailer()
    {
        try {
            $credentials = $this->getCredentials();
        } catch (Exception $ex) {
            $this->log("GoogleOAuthSMTP is enabled but credentials are incomplete.", CLogger::LEVEL_WARNING);
            return;
        }

        $refreshToken = $this->get("refreshToken");
        if (empty($refreshToken)) {
            $this->log("GoogleOAuthSMTP is enabled but there is no refresh token stored.", CLogger::LEVEL_WARNING);
            return;
        }

        $emailAddress = $this->get("email");
        if (empty($emailAddress)) {
            $this->log("GoogleOAuthSMTP is enabled but there is no email address. Please generate a new token.", CLogger::LEVEL_WARNING);
            return;
        }

        $provider = $this->getProvider($credentials);
        $config = [
            'provider' => $provider,
            'clientId' => $credentials['clientId'],
            'clientSecret' => $credentials['clientSecret'],
            'refreshToken' => $refreshToken,
            'userName' => $emailAddress,
        ];

        return $config;
    }

    /**
     * @inheritdoc
     * Add Google specific settings to the mailer
     */
    protected function setupMailer($mailer)
    {
        parent::setupMailer($mailer);
        $mailer->Host = 'smtp.gmail.com';
        $mailer->Port = 465;
        $mailer->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
    }

    /**
     * Handles the afterSelectEmailPlugin event, triggered when the plugin
     * is selected as the SMTP OAuth plugin in Global Settings
     */
    public function afterSelectEmailPlugin()
    {
        $setupStatus = $this->getSetupStatus();
        if ($setupStatus !== self::SETUP_STATUS_VALID_REFRESH_TOKEN) {
            $event = $this->getEvent();
            $event->set('warning', sprintf(gT("The %s plugin is not configured correctly. Please check the plugin settings."), self::getName()));
        }
    }

    /**
     * @inheritdoc
     */
    protected function getAuthorizationOptions()
    {
        return [
            'scope' => [
                'https://mail.google.com/'
            ]
        ];
    }

    /**
     * Handles the beforeEmailDispatch event, triggered right before an email is sent.
     * This is used to set the "Reply To" header, because Google automatically overrides
     * the sender with the logged user.
     */
    public function beforeEmailDispatch()
    {
        // Don't do anything if the current plugin is not the one selected.
        if (!$this->isCurrentEmailPlugin()) {
            return;
        }

        $event = $this->getEvent();

        /** @var LimeMailer */
        $limeMailer = $event->get('mailer');
        // Set "Reply To" because Gmail overrides the From/Sender with the logged user.
        $limeMailer->AddReplyTo($limeMailer->From, $limeMailer->FromName);
    }

    /**
     * @inheritdoc
     */
    protected function getDisplayName()
    {
        return 'Google';
    }

    public function beforePrepareRedirectToAuthPage()
    {
        $event = $this->getEvent();
        $event->set('width', 600);
        $event->set('height', 700);
        $event->set('providerName', $this->getDisplayName());

        $setupStatus = $this->getSetupStatus();
        $description = $this->getSetupStatusDescription($setupStatus);
        $event->setContent($this, $description);
    }
}