summaryrefslogtreecommitdiff
path: root/Postman/Postman-Mail/PostmanModuleTransport.php
diff options
context:
space:
mode:
Diffstat (limited to 'Postman/Postman-Mail/PostmanModuleTransport.php')
-rw-r--r--Postman/Postman-Mail/PostmanModuleTransport.php758
1 files changed, 758 insertions, 0 deletions
diff --git a/Postman/Postman-Mail/PostmanModuleTransport.php b/Postman/Postman-Mail/PostmanModuleTransport.php
new file mode 100644
index 0000000..a0874e3
--- /dev/null
+++ b/Postman/Postman-Mail/PostmanModuleTransport.php
@@ -0,0 +1,758 @@
+<?php
+if ( ! defined( 'ABSPATH' ) ) {
+ exit; // Exit if accessed directly
+}
+
+/**
+ * Keep the interface_exists check here for Postman Gmail API Extension users!
+ *
+ * @author jasonhendriks
+ */
+if (! interface_exists ( 'PostmanTransport' )) {
+ interface PostmanTransport {
+ public function isServiceProviderGoogle($hostname);
+ public function isServiceProviderMicrosoft($hostname);
+ public function isServiceProviderYahoo($hostname);
+ // @deprecated
+ public function isOAuthUsed($authType);
+ public function isTranscriptSupported();
+ public function getSlug();
+ public function getName();
+ // @deprecated
+ public function createPostmanMailAuthenticator(PostmanOptions $options, PostmanOAuthToken $authToken);
+ public function createZendMailTransport($fakeHostname, $fakeConfig);
+ public function isConfigured(PostmanOptionsInterface $options, PostmanOAuthToken $token);
+ public function isReady(PostmanOptionsInterface $options, PostmanOAuthToken $token);
+ // @deprecated
+ public function getMisconfigurationMessage(PostmanConfigTextHelper $scribe, PostmanOptionsInterface $options, PostmanOAuthToken $token);
+ // @deprecated
+ public function getConfigurationRecommendation($hostData);
+ // @deprecated
+ public function getHostsToTest($hostname);
+ }
+}
+interface PostmanModuleTransport extends PostmanTransport {
+ const RAW_MESSAGE_FOLLOWS = '
+
+--Raw message follows--
+
+';
+ public function getDeliveryDetails();
+ public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess);
+ public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer);
+ public function isLockingRequired();
+ public function createMailEngine();
+ public function isWizardSupported();
+ public function isConfiguredAndReady();
+ public function isReadyToSendMail();
+ public function getFromEmailAddress();
+ public function getFromName();
+ public function getHostname();
+ public function getProtocol();
+ public function isEmailValidationSupported();
+ public function getPort();
+ public function init();
+}
+interface PostmanZendModuleTransport extends PostmanModuleTransport {
+ public function getAuthenticationType();
+ public function getSecurityType();
+ public function getCredentialsId();
+ public function getCredentialsSecret();
+ public function getEnvelopeFromEmailAddress();
+}
+
+/**
+ *
+ * @author jasonhendriks
+ *
+ */
+abstract class PostmanAbstractModuleTransport implements PostmanModuleTransport {
+ private $configurationMessages;
+ private $configuredAndReady;
+
+ /**
+ * These internal variables are exposed for the subclasses to use
+ *
+ * @var mixed
+ */
+ protected $logger;
+ protected $options;
+ protected $rootPluginFilenameAndPath;
+ protected $scribe;
+
+ /**
+ */
+ public function __construct($rootPluginFilenameAndPath = null) {
+ $this->logger = new PostmanLogger ( get_class ( $this ) );
+ $this->options = PostmanOptions::getInstance ();
+ $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
+ }
+
+ /**
+ * Initialize the Module
+ *
+ * Perform validation and create configuration error messages.
+ * The module is not in a configured-and-ready state until initialization
+ */
+ public function init() {
+ // create the scribe
+ $hostname = $this->getHostname ();
+ $this->scribe = $this->createScribe ( $hostname );
+
+ // validate the transport and generate error messages
+ $this->configurationMessages = $this->validateTransportConfiguration ();
+ }
+
+ /**
+ * SendGrid API doesn't care what the hostname or guessed SMTP Server is; it runs it's port test no matter what
+ */
+ public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess) {
+ $hosts = array (
+ self::createSocketDefinition ( $this->getHostname (), $this->getPort () )
+ );
+ return $hosts;
+ }
+
+ /**
+ * Creates a single socket for the Wizard to test
+ */
+ protected function createSocketDefinition($hostname, $port) {
+ $socket = array ();
+ $socket ['host'] = $hostname;
+ $socket ['port'] = $port;
+ $socket ['id'] = sprintf ( '%s-%s', $this->getSlug (), $port );
+ $socket ['transport_id'] = $this->getSlug ();
+ $socket ['transport_name'] = $this->getName ();
+ $socket ['smtp'] = false;
+ return $socket;
+ }
+
+ /**
+ *
+ * @param mixed $data
+ */
+ public function prepareOptionsForExport($data) {
+ // no-op
+ return $data;
+ }
+
+ /**
+ */
+ public function printActionMenuItem() {
+ printf ( '<li><div class="welcome-icon send_test_email">%s</div></li>', $this->getScribe ()->getRequestPermissionLinkText () );
+ }
+
+ /**
+ *
+ * @param mixed $queryHostname
+ */
+ protected function createScribe($hostname) {
+ $scribe = new PostmanNonOAuthScribe ( $hostname );
+ return $scribe;
+ }
+
+ /**
+ */
+ public function enqueueScript() {
+ // no-op, this for subclasses
+ }
+
+ /**
+ * This method is for internal use
+ */
+ protected function validateTransportConfiguration() {
+ $this->configuredAndReady = true;
+ $messages = array ();
+ return $messages;
+ }
+
+ /**
+ */
+ protected function setNotConfiguredAndReady() {
+ $this->configuredAndReady = false;
+ }
+
+ /**
+ * A short-hand way of showing the complete delivery method
+ *
+ * @param PostmanModuleTransport $transport
+ * @return string
+ */
+ public function getPublicTransportUri() {
+ $name = $this->getSlug ();
+ $host = $this->getHostname ();
+ $port = $this->getPort ();
+ $protocol = $this->getProtocol ();
+ return sprintf ( '%s://%s:%s', $protocol, $host, $port );
+ }
+
+ /**
+ * The Message From Address
+ */
+ public function getFromEmailAddress() {
+ return PostmanOptions::getInstance ()->getMessageSenderEmail ();
+ }
+
+ /**
+ * The Message From Name
+ */
+ public function getFromName() {
+ return PostmanOptions::getInstance ()->getMessageSenderName ();
+ }
+ public function getEnvelopeFromEmailAddress() {
+ return PostmanOptions::getInstance ()->getEnvelopeSender ();
+ }
+ public function isEmailValidationSupported() {
+ return ! PostmanOptions::getInstance ()->isEmailValidationDisabled ();
+ }
+
+ /**
+ * Make sure the Senders are configured
+ *
+ * @param PostmanOptions $options
+ * @return boolean
+ */
+ protected function isSenderConfigured() {
+ $options = PostmanOptions::getInstance ();
+ $messageFrom = $options->getMessageSenderEmail ();
+ return ! empty ( $messageFrom );
+ }
+
+ /**
+ * Get the configuration error messages
+ */
+ public function getConfigurationMessages() {
+ return $this->configurationMessages;
+ }
+
+ /**
+ * (non-PHPdoc)
+ *
+ * @see PostmanModuleTransport::isConfiguredAndReady()
+ */
+ public function isConfiguredAndReady() {
+ return $this->configuredAndReady;
+ }
+
+ /**
+ * (non-PHPdoc)
+ *
+ * @see PostmanModuleTransport::isReadyToSendMail()
+ */
+ public function isReadyToSendMail() {
+ return $this->isConfiguredAndReady ();
+ }
+
+ /**
+ * Determines whether Mail Engine locking is needed
+ *
+ * @see PostmanModuleTransport::requiresLocking()
+ */
+ public function isLockingRequired() {
+ return false;
+ }
+ public function isOAuthUsed($authType) {
+ return $authType == PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
+ }
+
+ /**
+ * (non-PHPdoc)
+ *
+ * @see PostmanModuleTransport::isWizardSupported()
+ */
+ public function isWizardSupported() {
+ return false;
+ }
+
+ /**
+ * This is for step 2 of the Wizard
+ */
+ public function printWizardMailServerHostnameStep() {
+ }
+
+ /**
+ * This is for step 4 of the Wizard
+ */
+ public function printWizardAuthenticationStep() {
+ }
+
+ /**
+ *
+ * @return PostmanNonOAuthScribe
+ */
+ public function getScribe() {
+ return $this->scribe;
+ }
+
+ /**
+ *
+ * @param mixed $hostname
+ * @param mixed $response
+ */
+ public function populateConfiguration($hostname) {
+ $configuration = array ();
+ return $configuration;
+ }
+ /**
+ *
+ * @param mixed $winningRecommendation
+ * @param mixed $response
+ */
+ public function populateConfigurationFromRecommendation($winningRecommendation) {
+ $configuration = array ();
+ $configuration ['message'] = $winningRecommendation ['message'];
+ $configuration [PostmanOptions::TRANSPORT_TYPE] = $winningRecommendation ['transport'];
+ return $configuration;
+ }
+
+ /**
+ */
+ public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
+ $overrideItem = array ();
+ $overrideItem ['secure'] = $socket->secure;
+ $overrideItem ['mitm'] = $socket->mitm;
+ $overrideItem ['hostname_domain_only'] = $socket->hostnameDomainOnly;
+ $overrideItem ['reported_hostname_domain_only'] = $socket->reportedHostnameDomainOnly;
+ $overrideItem ['value'] = $socket->id;
+ $overrideItem ['description'] = $socket->label;
+ $overrideItem ['selected'] = ($winningRecommendation ['id'] == $overrideItem ['value']);
+ return $overrideItem;
+ }
+
+ /*
+ * ******************************************************************
+ * Not deprecated, but I wish they didn't live here on the superclass
+ */
+ public function isServiceProviderGoogle($hostname) {
+ return PostmanUtils::endsWith ( $hostname, 'gmail.com' ) || PostmanUtils::endsWith ( $hostname, 'googleapis.com' );
+ }
+ public function isServiceProviderMicrosoft($hostname) {
+ return PostmanUtils::endsWith ( $hostname, 'live.com' );
+ }
+ public function isServiceProviderYahoo($hostname) {
+ return strpos ( $hostname, 'yahoo' );
+ }
+
+ /*
+ * ********************************
+ * Unused, deprecated methods follow
+ * *********************************
+ */
+
+ /**
+ *
+ * @deprecated (non-PHPdoc)
+ * @see PostmanTransport::createZendMailTransport()
+ */
+ public function createZendMailTransport($hostname, $config) {
+ }
+
+ /**
+ *
+ * @deprecated (non-PHPdoc)
+ * @see PostmanTransport::isTranscriptSupported()
+ */
+ public function isTranscriptSupported() {
+ return false;
+ }
+
+ /**
+ * Only here because I can't remove it from the Interface
+ */
+ public final function getMisconfigurationMessage(PostmanConfigTextHelper $scribe, PostmanOptionsInterface $options, PostmanOAuthToken $token) {
+ }
+ public final function isReady(PostmanOptionsInterface $options, PostmanOAuthToken $token) {
+ return ! ($this->isConfiguredAndReady ());
+ }
+ public final function isConfigured(PostmanOptionsInterface $options, PostmanOAuthToken $token) {
+ return ! ($this->isConfiguredAndReady ());
+ }
+ /**
+ *
+ * @deprecated (non-PHPdoc)
+ * @see PostmanTransport::getConfigurationRecommendation()
+ */
+ public final function getConfigurationRecommendation($hostData) {
+ }
+ /**
+ *
+ * @deprecated (non-PHPdoc)
+ * @see PostmanTransport::getHostsToTest()
+ */
+ public final function getHostsToTest($hostname) {
+ }
+ protected final function isHostConfigured(PostmanOptions $options) {
+ $hostname = $options->getHostname ();
+ $port = $options->getPort ();
+ return ! (empty ( $hostname ) || empty ( $port ));
+ }
+ /**
+ *
+ * @deprecated (non-PHPdoc)
+ * @see PostmanTransport::createPostmanMailAuthenticator()
+ */
+ public final function createPostmanMailAuthenticator(PostmanOptions $options, PostmanOAuthToken $authToken) {
+ }
+}
+
+/**
+ * For the transports which depend on Zend_Mail
+ *
+ * @author jasonhendriks
+ *
+ */
+abstract class PostmanAbstractZendModuleTransport extends PostmanAbstractModuleTransport implements PostmanZendModuleTransport {
+ private $oauthToken;
+ private $readyForOAuthGrant;
+
+ /**
+ */
+ public function __construct($rootPluginFilenameAndPath) {
+ parent::__construct ( $rootPluginFilenameAndPath );
+ $this->oauthToken = PostmanOAuthToken::getInstance ();
+ }
+ public function getOAuthToken() {
+ return $this->oauthToken;
+ }
+ public function getProtocol() {
+ if ($this->getSecurityType () == PostmanOptions::SECURITY_TYPE_SMTPS)
+ return 'smtps';
+ else
+ return 'smtp';
+ }
+ public function getSecurityType() {
+ return PostmanOptions::getInstance ()->getEncryptionType ();
+ }
+
+ /**
+ *
+ * @param mixed $data
+ */
+ public function prepareOptionsForExport($data) {
+ $data = parent::prepareOptionsForExport ( $data );
+ $data [PostmanOptions::BASIC_AUTH_PASSWORD] = PostmanOptions::getInstance ()->getPassword ();
+ return $data;
+ }
+
+ /**
+ *
+ * @return boolean
+ */
+ public function isEnvelopeFromValidationSupported() {
+ return $this->isEmailValidationSupported ();
+ }
+
+ /**
+ */
+ protected function setReadyForOAuthGrant() {
+ $this->readyForOAuthGrant = true;
+ }
+
+ /**
+ */
+ public function printActionMenuItem() {
+ if ($this->readyForOAuthGrant && $this->getAuthenticationType () == PostmanOptions::AUTHENTICATION_TYPE_OAUTH2) {
+ printf ( '<li><a href="%s" class="welcome-icon send-test-email">%s</a></li>', PostmanUtils::getGrantOAuthPermissionUrl (), $this->getScribe ()->getRequestPermissionLinkText () );
+ } else {
+ parent::printActionMenuItem ();
+ }
+ }
+
+ /**
+ *
+ * @param mixed $queryHostname
+ */
+ protected function createScribe($hostname) {
+ $scribe = null;
+ if ($this->isServiceProviderGoogle ( $hostname )) {
+ $scribe = new PostmanGoogleOAuthScribe ();
+ } else if ($this->isServiceProviderMicrosoft ( $hostname )) {
+ $scribe = new PostmanMicrosoftOAuthScribe ();
+ } else if ($this->isServiceProviderYahoo ( $hostname )) {
+ $scribe = new PostmanYahooOAuthScribe ();
+ } else {
+ $scribe = new PostmanNonOAuthScribe ( $hostname );
+ }
+ return $scribe;
+ }
+
+ /**
+ * A short-hand way of showing the complete delivery method
+ *
+ * @param PostmanModuleTransport $transport
+ * @return string
+ */
+ public function getPublicTransportUri() {
+ $transportName = $this->getSlug ();
+ $options = PostmanOptions::getInstance ();
+ $auth = $this->getAuthenticationType ( $options );
+ $protocol = $this->getProtocol ();
+ $security = $this->getSecurityType ();
+ $host = $this->getHostname ( $options );
+ $port = $this->getPort ( $options );
+ if (! empty ( $security ) && $security != 'ssl') {
+ return sprintf ( '%s:%s:%s://%s:%s', $protocol, $security, $auth, $host, $port );
+ } else {
+ return sprintf ( '%s:%s://%s:%s', $protocol, $auth, $host, $port );
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ *
+ * @see PostmanModuleTransport::getDeliveryDetails()
+ */
+ public function getDeliveryDetails() {
+ $this->options = $this->options;
+ $deliveryDetails ['transport_name'] = $this->getTransportDescription ( $this->getSecurityType () );
+ $deliveryDetails ['host'] = $this->getHostname () . ':' . $this->getPort ();
+ $deliveryDetails ['auth_desc'] = $this->getAuthenticationDescription ( $this->getAuthenticationType () );
+
+ if ( $deliveryDetails ['host'] == 'localhost:25' ) {
+ $deliveryDetails ['transport_name'] = __( 'Sendmail (server defualt - not SMTP)', 'post-smtp');
+ }
+
+ /* translators: where (1) is the transport type, (2) is the host, and (3) is the Authentication Type (e.g. Postman will send mail via smtp.gmail.com:465 using OAuth 2.0 authentication.) */
+ return sprintf ( __ ( 'Postman will send mail via %1$s to %2$s using %3$s authentication.', 'post-smtp' ), '<b>' . $deliveryDetails ['transport_name'] . '</b>', '<b>' . $deliveryDetails ['host'] . '</b>', '<b>' . $deliveryDetails ['auth_desc'] . '</b>' );
+ }
+
+ /**
+ *
+ * @param mixed $encType
+ * @return string
+ */
+ protected function getTransportDescription($encType) {
+ $deliveryDetails = '🔓SMTP';
+ if ($encType == PostmanOptions::SECURITY_TYPE_SMTPS) {
+ /* translators: where %1$s is the Transport type (e.g. SMTP or SMTPS) and %2$s is the encryption type (e.g. SSL or TLS) */
+ $deliveryDetails = '🔐SMTPS';
+ } else if ($encType == PostmanOptions::SECURITY_TYPE_STARTTLS) {
+ /* translators: where %1$s is the Transport type (e.g. SMTP or SMTPS) and %2$s is the encryption type (e.g. SSL or TLS) */
+ $deliveryDetails = '🔐SMTP-STARTTLS';
+ }
+ return $deliveryDetails;
+ }
+
+ /**
+ *
+ * @param mixed $authType
+ */
+ protected function getAuthenticationDescription($authType) {
+ if (PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $authType) {
+ return 'OAuth 2.0';
+ } else if (PostmanOptions::AUTHENTICATION_TYPE_NONE == $authType) {
+ return _x ( 'no', 'as in "There is no Spoon"', 'post-smtp' );
+ } else {
+ switch ($authType) {
+ case PostmanOptions::AUTHENTICATION_TYPE_CRAMMD5 :
+ $authDescription = 'CRAM-MD5';
+ break;
+
+ case PostmanOptions::AUTHENTICATION_TYPE_LOGIN :
+ $authDescription = 'Login';
+ break;
+
+ case PostmanOptions::AUTHENTICATION_TYPE_PLAIN :
+ $authDescription = 'Plain';
+ break;
+
+ default :
+ $authDescription = $authType;
+ break;
+ }
+ return sprintf ( '%s (%s)', __ ( 'Password', 'post-smtp' ), $authDescription );
+ }
+ }
+
+ /**
+ * Make sure the Senders are configured
+ *
+ * @param PostmanOptions $options
+ * @return boolean
+ */
+ protected function isEnvelopeFromConfigured() {
+ $options = PostmanOptions::getInstance ();
+ $envelopeFrom = $options->getEnvelopeSender ();
+ return ! empty ( $envelopeFrom );
+ }
+
+ /**
+ * (non-PHPdoc)
+ *
+ * @see PostmanTransport::getMisconfigurationMessage()
+ */
+ protected function validateTransportConfiguration() {
+ parent::validateTransportConfiguration ();
+ $messages = parent::validateTransportConfiguration ();
+ if (! $this->isSenderConfigured ()) {
+ array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
+ $this->setNotConfiguredAndReady ();
+ }
+ if ($this->getAuthenticationType () == PostmanOptions::AUTHENTICATION_TYPE_OAUTH2) {
+ if (! $this->isOAuth2ClientIdAndClientSecretConfigured ()) {
+ /* translators: %1$s is the Client ID label, and %2$s is the Client Secret label (e.g. Warning: OAuth 2.0 authentication requires an OAuth 2.0-capable Outgoing Mail Server, Sender Email Address, Client ID, and Client Secret.) */
+ array_push ( $messages, sprintf ( __ ( 'OAuth 2.0 authentication requires a %1$s and %2$s.', 'post-smtp' ), $this->getScribe ()->getClientIdLabel (), $this->getScribe ()->getClientSecretLabel () ) );
+ $this->setNotConfiguredAndReady ();
+ }
+ }
+ return $messages;
+ }
+
+ /**
+ *
+ * @return boolean
+ */
+ protected function isOAuth2ClientIdAndClientSecretConfigured() {
+ $options = PostmanOptions::getInstance ();
+ $clientId = $options->getClientId ();
+ $clientSecret = $options->getClientSecret ();
+ return ! (empty ( $clientId ) || empty ( $clientSecret ));
+ }
+
+ /**
+ *
+ * @return boolean
+ */
+ protected function isPasswordAuthenticationConfigured(PostmanOptions $options) {
+ $username = $options->getUsername ();
+ $password = $options->getPassword ();
+ return $this->options->isAuthTypePassword () && ! (empty ( $username ) || empty ( $password ));
+ }
+
+ /**
+ *
+ * @return boolean
+ */
+ protected function isPermissionNeeded() {
+ $accessToken = $this->getOAuthToken ()->getAccessToken ();
+ $refreshToken = $this->getOAuthToken ()->getRefreshToken ();
+ return $this->isOAuthUsed ( PostmanOptions::getInstance ()->getAuthenticationType () ) && (empty ( $accessToken ) || empty ( $refreshToken ));
+ }
+
+ /**
+ *
+ * @param mixed $hostname
+ * @param mixed $response
+ */
+ public function populateConfiguration($hostname) {
+ $response = parent::populateConfiguration ( $hostname );
+ $this->logger->debug ( sprintf ( 'populateConfigurationFromRecommendation for hostname %s', $hostname ) );
+ $scribe = $this->createScribe ( $hostname );
+ // checks to see if the host is an IP address and sticks the result in the response
+ // IP addresses are not allowed in the Redirect URL
+ $urlParts = parse_url ( $scribe->getCallbackUrl () );
+ $response ['dot_notation_url'] = false;
+ if (isset ( $urlParts ['host'] )) {
+ if (PostmanUtils::isHostAddressNotADomainName ( $urlParts ['host'] )) {
+ $response ['dot_notation_url'] = true;
+ }
+ }
+ $response ['redirect_url'] = $scribe->getCallbackUrl ();
+ $response ['callback_domain'] = $scribe->getCallbackDomain ();
+ $response ['help_text'] = $scribe->getOAuthHelp ();
+ $response ['client_id_label'] = $scribe->getClientIdLabel ();
+ $response ['client_secret_label'] = $scribe->getClientSecretLabel ();
+ $response ['redirect_url_label'] = $scribe->getCallbackUrlLabel ();
+ $response ['callback_domain_label'] = $scribe->getCallbackDomainLabel ();
+ return $response;
+ }
+
+ /**
+ * Populate the Ajax response for the Setup Wizard / Manual Configuration
+ *
+ * @param mixed $hostname
+ * @param mixed $response
+ */
+ public function populateConfigurationFromRecommendation($winningRecommendation) {
+ $response = parent::populateConfigurationFromRecommendation ( $winningRecommendation );
+ $response [PostmanOptions::AUTHENTICATION_TYPE] = $winningRecommendation ['auth'];
+ if (isset ( $winningRecommendation ['enc'] )) {
+ $response [PostmanOptions::SECURITY_TYPE] = $winningRecommendation ['enc'];
+ }
+ if (isset ( $winningRecommendation ['port'] )) {
+ $response [PostmanOptions::PORT] = $winningRecommendation ['port'];
+ }
+ if (isset ( $winningRecommendation ['hostname'] )) {
+ $response [PostmanOptions::HOSTNAME] = $winningRecommendation ['hostname'];
+ }
+ if (isset ( $winningRecommendation ['display_auth'] )) {
+ $response ['display_auth'] = $winningRecommendation ['display_auth'];
+ }
+ return $response;
+ }
+
+ /**
+ */
+ public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
+ $overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
+ $selected = $overrideItem ['selected'];
+
+ // only smtp can have multiple auth options
+ $overrideAuthItems = array ();
+ $passwordMode = false;
+ $oauth2Mode = false;
+ $noAuthMode = false;
+ if (isset ( $userAuthOverride ) || isset ( $userSocketOverride )) {
+ if ($userAuthOverride == 'password') {
+ $passwordMode = true;
+ } elseif ($userAuthOverride == 'oauth2') {
+ $oauth2Mode = true;
+ } else {
+ $noAuthMode = true;
+ }
+ } else {
+ if ($winningRecommendation ['display_auth'] == 'password') {
+ $passwordMode = true;
+ } elseif ($winningRecommendation ['display_auth'] == 'oauth2') {
+ $oauth2Mode = true;
+ } else {
+ $noAuthMode = true;
+ }
+ }
+ if ($selected) {
+ if ($socket->auth_crammd5 || $socket->auth_login || $socket->authPlain) {
+ array_push ( $overrideAuthItems, array (
+ 'selected' => $passwordMode,
+ 'name' => __ ( 'Password (requires username and password)', 'post-smtp' ),
+ 'value' => 'password'
+ ) );
+ }
+ if ($socket->auth_xoauth || $winningRecommendation ['auth'] == 'oauth2') {
+ array_push ( $overrideAuthItems, array (
+ 'selected' => $oauth2Mode,
+ 'name' => __ ( 'OAuth 2.0 (requires Client ID and Client Secret)', 'post-smtp' ),
+ 'value' => 'oauth2'
+ ) );
+ }
+ if ($socket->auth_none) {
+ array_push ( $overrideAuthItems, array (
+ 'selected' => $noAuthMode,
+ 'name' => __ ( 'None', 'post-smtp' ),
+ 'value' => 'none'
+ ) );
+ }
+
+ // marks at least one item as selected if none are selected
+ $atLeastOneSelected = false;
+ $firstItem = null;
+ // don't use variable reference see http://stackoverflow.com/questions/15024616/php-foreach-change-original-array-values
+ foreach ( $overrideAuthItems as $key => $field ) {
+ if (! $firstItem) {
+ $firstItem = $key;
+ }
+ if ($field ['selected']) {
+ $atLeastOneSelected = true;
+ }
+ }
+ if (! $atLeastOneSelected) {
+ $this->logger->debug ( 'nothing selected - forcing a selection on the *first* overrided auth item' );
+ $overrideAuthItems [$firstItem] ['selected'] = true;
+ }
+
+ // push the authentication options into the $overrideItem structure
+ $overrideItem ['auth_items'] = $overrideAuthItems;
+ }
+ return $overrideItem;
+ }
+}
+