/**
  *
  * @param unknown $queryHostData        	
  */
 function __construct($queryHostData)
 {
     $this->hostname = $queryHostData['hostname'];
     $this->hostnameDomainOnly = $queryHostData['hostname_domain_only'];
     $this->port = $queryHostData['port'];
     $this->protocol = $queryHostData['protocol'];
     $this->secure = PostmanUtils::parseBoolean($queryHostData['secure']);
     $this->mitm = PostmanUtils::parseBoolean($queryHostData['mitm']);
     $this->reportedHostname = $queryHostData['reported_hostname'];
     $this->reportedHostnameDomainOnly = $queryHostData['reported_hostname_domain_only'];
     $this->message = $queryHostData['message'];
     $this->startTls = PostmanUtils::parseBoolean($queryHostData['start_tls']);
     $this->authPlain = PostmanUtils::parseBoolean($queryHostData['auth_plain']);
     $this->auth_login = PostmanUtils::parseBoolean($queryHostData['auth_login']);
     $this->auth_crammd5 = PostmanUtils::parseBoolean($queryHostData['auth_crammd5']);
     $this->auth_xoauth = PostmanUtils::parseBoolean($queryHostData['auth_xoauth']);
     $this->auth_none = PostmanUtils::parseBoolean($queryHostData['auth_none']);
     $this->try_smtps = PostmanUtils::parseBoolean($queryHostData['try_smtps']);
     $this->success = PostmanUtils::parseBoolean($queryHostData['success']);
     $this->transport = $queryHostData['transport'];
     assert(!empty($this->transport));
     $this->id = sprintf('%s_%s', $this->hostname, $this->port);
 }
 /**
  *
  * @param unknown $queryHostData        	
  * @return multitype:
  */
 private function createOverrideMenu($queryHostData, $winningRecommendation, $userSocketOverride, $userAuthOverride)
 {
     $overrideMenu = array();
     foreach ($queryHostData as $id => $value) {
         if (filter_var($value['success'], FILTER_VALIDATE_BOOLEAN)) {
             $overrideItem = array();
             $overrideItem['secure'] = PostmanUtils::parseBoolean($value['secure']);
             $overrideItem['mitm'] = PostmanUtils::parseBoolean($value['mitm']);
             $overrideItem['hostname_domain_only'] = $value['hostname_domain_only'];
             $overrideItem['reported_hostname_domain_only'] = $value['reported_hostname_domain_only'];
             $overrideItem['value'] = sprintf('%s_%s', $value['hostname'], $value['port']);
             $selected = $winningRecommendation['id'] == $overrideItem['value'];
             $overrideItem['selected'] = $selected;
             $hostnameToDisplay = $value['hostname'];
             $overrideItem['description'] = sprintf('%s:%s', $hostnameToDisplay, $value['port']);
             $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 ($value['auth_crammd5'] || $value['auth_login'] || $value['auth_plain']) {
                     array_push($overrideAuthItems, array('selected' => $passwordMode, 'name' => __('Password (requires username and password)', 'postman-smtp'), 'value' => 'password'));
                 }
                 if ($value['auth_xoauth'] || $winningRecommendation['auth'] == 'oauth2') {
                     array_push($overrideAuthItems, array('selected' => $oauth2Mode, 'name' => __('OAuth 2.0 (requires Client ID and Client Secret)', 'postman-smtp'), 'value' => 'oauth2'));
                 }
                 if ($value['auth_none']) {
                     array_push($overrideAuthItems, array('selected' => $noAuthMode, 'name' => _x('None', 'As in type used: None', 'postman-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;
             }
             array_push($overrideMenu, $overrideItem);
         }
     }
     return $overrideMenu;
 }
 private function scrubUserOverride($hostData, $userAuthOverride)
 {
     $this->logger->trace('before scrubbing userAuthOverride: ' . $userAuthOverride);
     // validate the userAuthOverride
     $oauthIsAllowed = false;
     $passwordIsAllowed = false;
     $noneIsAllowed = false;
     if (!PostmanUtils::parseBoolean($hostData['auth_xoauth'])) {
         if ($userAuthOverride == 'oauth2') {
             $userAuthOverride = null;
         }
     }
     if (!PostmanUtils::parseBoolean($hostData['auth_crammd5']) && !PostmanUtils::parseBoolean($hostData['auth_plain']) && !PostmanUtils::parseBoolean($hostData['auth_login'])) {
         if ($userAuthOverride == 'password') {
             $userAuthOverride = null;
         }
     }
     if (!PostmanUtils::parseBoolean($hostData['auth_none'])) {
         if ($userAuthOverride == 'none') {
             $userAuthOverride = null;
         }
     }
     $this->logger->trace('after scrubbing userAuthOverride: ' . $userAuthOverride);
     return $userAuthOverride;
 }
 /**
  * First choose the auth method, in this order: XOAUTH (4000), CRAM-MD5 (3000), PLAIN (2000), LOGIN (1000)
  * Second, choose the port, in this order: 587/STARTLS (300), 465/SMTPS (200), 25/SMTP (100), 443/GMAIL (150)
  *
  * SMTP supports sending with these combinations in this order of preferences:
  *
  * @param unknown $hostData        	
  */
 public function getConfigurationBid($hostData, $userAuthOverride, $originalSmtpServer)
 {
     $port = $hostData['port'];
     $hostname = $hostData['hostname'];
     // because some servers, like smtp.broadband.rogers.com, report XOAUTH2 but have no OAuth2 front-end
     $supportedOAuth2Provider = $this->isServiceProviderGoogle($hostname) || $this->isServiceProviderMicrosoft($hostname) || $this->isServiceProviderYahoo($hostname);
     $score = 0;
     $recommendation = array();
     // increment score for auth type
     if (isset($hostData['mitm']) && PostmanUtils::parseBoolean($hostData['mitm'])) {
         $this->logger->debug('Losing points for MITM');
         $score -= 10000;
         $recommendation['mitm'] = true;
     }
     if (!empty($originalSmtpServer) && $hostname != $originalSmtpServer) {
         $this->logger->debug('Losing points for Not The Original SMTP server');
         $score -= 10000;
     }
     $secure = true;
     if (PostmanUtils::parseBoolean($hostData['start_tls'])) {
         // STARTTLS was formalized in 2002
         // http://www.rfc-editor.org/rfc/rfc3207.txt
         $recommendation['enc'] = PostmanOptions::ENCRYPTION_TYPE_TLS;
         $score += 30000;
     } elseif ($hostData['protocol'] == 'SMTPS') {
         // "The hopelessly confusing and imprecise term, SSL,
         // has often been used to indicate the SMTPS wrapper and
         // TLS to indicate the STARTTLS protocol extension."
         // http://stackoverflow.com/a/19942206/4368109
         $recommendation['enc'] = PostmanOptions::ENCRYPTION_TYPE_SSL;
         $score += 28000;
     } elseif ($hostData['protocol'] == 'SMTP') {
         $recommendation['enc'] = PostmanOptions::ENCRYPTION_TYPE_NONE;
         $score += 26000;
         $secure = false;
     }
     // if there is a way to send mail....
     if ($score > 10) {
         // determine the authentication type
         if (PostmanUtils::parseBoolean($hostData['auth_xoauth']) && $supportedOAuth2Provider && (empty($userAuthOverride) || $userAuthOverride == 'oauth2')) {
             $recommendation['auth'] = PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
             $recommendation['display_auth'] = 'oauth2';
             $score += 500;
             if (!$secure) {
                 $this->logger->debug('Losing points for sending credentials in the clear');
                 $score -= 10000;
             }
         } elseif (PostmanUtils::parseBoolean($hostData['auth_crammd5']) && (empty($userAuthOverride) || $userAuthOverride == 'password')) {
             $recommendation['auth'] = PostmanOptions::AUTHENTICATION_TYPE_CRAMMD5;
             $recommendation['display_auth'] = 'password';
             $score += 400;
             if (!$secure) {
                 $this->logger->debug('Losing points for sending credentials in the clear');
                 $score -= 10000;
             }
         } elseif (PostmanUtils::parseBoolean($hostData['auth_plain']) && (empty($userAuthOverride) || $userAuthOverride == 'password')) {
             $recommendation['auth'] = PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
             $recommendation['display_auth'] = 'password';
             $score += 300;
             if (!$secure) {
                 $this->logger->debug('Losing points for sending credentials in the clear');
                 $score -= 10000;
             }
         } elseif (PostmanUtils::parseBoolean($hostData['auth_login']) && (empty($userAuthOverride) || $userAuthOverride == 'password')) {
             $recommendation['auth'] = PostmanOptions::AUTHENTICATION_TYPE_LOGIN;
             $recommendation['display_auth'] = 'password';
             $score += 200;
             if (!$secure) {
                 $this->logger->debug('Losing points for sending credentials in the clear');
                 $score -= 10000;
             }
         } else {
             if (empty($userAuthOverride) || $userAuthOverride == 'none') {
                 $recommendation['auth'] = PostmanOptions::AUTHENTICATION_TYPE_NONE;
                 $recommendation['display_auth'] = 'none';
                 $score += 100;
             }
         }
         // tiny weighting to prejudice the port selection, all things being equal
         if ($port == 587) {
             $score += 4;
         } elseif ($port == 25) {
             // "due to the prevalence of machines that have worms,
             // viruses, or other malicious software that generate large amounts of
             // spam, many sites now prohibit outbound traffic on the standard SMTP
             // port (port 25), funneling all mail submissions through submission
             // servers."
             // http://www.rfc-editor.org/rfc/rfc6409.txt
             $score += 3;
         } elseif ($port == 465) {
             // use of port 465 for SMTP was deprecated in 1998
             // http://www.imc.org/ietf-apps-tls/mail-archive/msg00204.html
             $score += 2;
         } else {
             $score += 1;
         }
         // create the recommendation message for the user
         // this can only be set if there is a valid ['auth'] and ['enc']
         $transportDescription = $this->getTransportDescription($recommendation['enc']);
         $authDesc = $this->getAuthenticationDescription($recommendation['auth']);
         /* translators: where %1$s is a description of the transport (eg. SMTPS-SSL), %2$s is a description of the authentication (eg. Password-CRAMMD5), %3$d is the TCP port (eg. 465), %4$d is the hostname */
         $recommendation['message'] = sprintf(__('Your recommended settings are %1$s with %2$s authentication to host %4$s on port %3$d.', 'postman-smtp'), $transportDescription, $authDesc, $port, $hostname);
     }
     // fill-in the rest of the recommendation
     $recommendation['transport'] = PostmanSmtpModuleTransport::SLUG;
     $recommendation['priority'] = $score;
     $recommendation['port'] = $port;
     $recommendation['hostname'] = $hostname;
     $recommendation['transport'] = self::SLUG;
     return $recommendation;
 }