/** * * @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; }