function wptuts_register_pointer_testing($p) { // only do this for administrators if (PostmanUtils::isAdmin()) { $p['postman16_log'] = array('target' => '.configure_manually', 'options' => array('content' => sprintf('<h3> %s </h3> <p> %s </p>', __('New for v1.6! Email Log', 'postman-smtp'), __('Enable to save a copy of all your emails. Great for troubleshooting or as a backup for messages that get lost. <b>Access the Email Log in the Tools menu.</b>', 'postman-smtp')), 'position' => array('edge' => 'top', 'align' => 'left'))); return $p; } }
function wptuts_register_pointer_testing($p) { // only do this for administrators if (PostmanUtils::isAdmin() && false) { $p['postman16_log'] = array('target' => '.configure_manually', 'options' => array('content' => '', 'position' => array('edge' => 'top', 'align' => 'left'))); return $p; } }
function check($ipAddress, $expectedresult) { $result = PostmanUtils::isHostAddressNotADomainName($ipAddress); $displaySuccess = 'fail'; if ($result == $expectedresult) { $displaySuccess = 'pass'; } print sprintf("%s: %s=%s\n", $displaySuccess, $ipAddress, $result); }
/** * Validate the email address * * @throws Exception */ public function validate() { if (!PostmanUtils::validateEmail($this->email)) { $message = 'Invalid e-mail address: ' . $this->email; $logger = new PostmanLogger(get_class($this)); $logger->warn($message); throw new Exception($message); } }
/** * Validate the email address * * @throws Exception */ public function validate($desc = '') { if (!PostmanUtils::validateEmail($this->email)) { if (empty($desc)) { /* Translators: Where %s is the email address */ $message = sprintf('Invalid e-mail address "%s"', $this->email); } else { /* Translators: Where (1) is the header name (eg. To) and (2) is the email address */ $message = sprintf('Invalid "%1$s" e-mail address "%2$s"', $desc, $this->email); } $logger = new PostmanLogger(get_class($this)); $logger->warn($message); throw new Exception($message); } }
/** * ********************************************** * If we have a code back from the OAuth 2.0 flow, * we need to exchange that for an access token. * We store the resultant access token * bundle in the session, and redirect to ourself. * ********************************************** */ public function processAuthorizationGrantCode($transactionId) { if (isset($_GET['code'])) { $code = $_GET['code']; $this->getLogger()->debug('Found authorization code in request header'); $postvals = array('client_id' => $this->getClientId(), 'client_secret' => $this->getClientSecret(), 'grant_type' => 'authorization_code', 'redirect_uri' => $this->getCallbackUri(), 'code' => $code); $response = PostmanUtils::remotePostGetBodyOnly($this->getTokenUrl(), $postvals); $this->processResponse($response); $this->getAuthorizationToken()->setVendorName(self::VENDOR_NAME); return true; } else { $this->getLogger()->debug('Expected code in the request header but found none - user probably denied request'); return false; } }
/** * Register and add settings */ private function registerSettings() { // only administrators should be able to trigger this if (PostmanUtils::isAdmin()) { // $sanitizer = new PostmanInputSanitizer(); register_setting(PostmanAdminController::SETTINGS_GROUP_NAME, PostmanOptions::POSTMAN_OPTIONS, array($sanitizer, 'sanitize')); // Sanitize add_settings_section('transport_section', __('Transport', Postman::TEXT_DOMAIN), array($this, 'printTransportSectionInfo'), 'transport_options'); add_settings_field(PostmanOptions::TRANSPORT_TYPE, _x('Type', '(i.e.) What kind is it?', Postman::TEXT_DOMAIN), array($this, 'transport_type_callback'), 'transport_options', 'transport_section'); // the Message From section add_settings_section(PostmanAdminController::MESSAGE_FROM_SECTION, _x('From Address', 'The Message Sender Email Address', Postman::TEXT_DOMAIN), array($this, 'printMessageFromSectionInfo'), PostmanAdminController::MESSAGE_FROM_OPTIONS); add_settings_field(PostmanOptions::MESSAGE_SENDER_EMAIL, __('Email Address', Postman::TEXT_DOMAIN), array($this, 'from_email_callback'), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION); add_settings_field(PostmanOptions::PREVENT_MESSAGE_SENDER_EMAIL_OVERRIDE, '', array($this, 'prevent_from_email_override_callback'), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION); add_settings_field(PostmanOptions::MESSAGE_SENDER_NAME, __('Name', Postman::TEXT_DOMAIN), array($this, 'sender_name_callback'), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION); add_settings_field(PostmanOptions::PREVENT_MESSAGE_SENDER_NAME_OVERRIDE, '', array($this, 'prevent_from_name_override_callback'), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION); // the Additional Addresses section add_settings_section(PostmanAdminController::MESSAGE_SECTION, __('Additional Email Addresses', Postman::TEXT_DOMAIN), array($this, 'printMessageSectionInfo'), PostmanAdminController::MESSAGE_OPTIONS); add_settings_field(PostmanOptions::REPLY_TO, __('Reply-To', Postman::TEXT_DOMAIN), array($this, 'reply_to_callback'), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION); add_settings_field(PostmanOptions::FORCED_TO_RECIPIENTS, __('To Recipient(s)', Postman::TEXT_DOMAIN), array($this, 'to_callback'), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION); add_settings_field(PostmanOptions::FORCED_CC_RECIPIENTS, __('Carbon Copy Recipient(s)', Postman::TEXT_DOMAIN), array($this, 'cc_callback'), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION); add_settings_field(PostmanOptions::FORCED_BCC_RECIPIENTS, __('Blind Carbon Copy Recipient(s)', Postman::TEXT_DOMAIN), array($this, 'bcc_callback'), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION); // the Additional Headers section add_settings_section(PostmanAdminController::MESSAGE_HEADERS_SECTION, __('Additional Headers', Postman::TEXT_DOMAIN), array($this, 'printAdditionalHeadersSectionInfo'), PostmanAdminController::MESSAGE_HEADERS_OPTIONS); add_settings_field(PostmanOptions::ADDITIONAL_HEADERS, __('Custom Headers', Postman::TEXT_DOMAIN), array($this, 'headers_callback'), PostmanAdminController::MESSAGE_HEADERS_OPTIONS, PostmanAdminController::MESSAGE_HEADERS_SECTION); // the Email Validation section add_settings_section(PostmanAdminController::EMAIL_VALIDATION_SECTION, __('Validation', Postman::TEXT_DOMAIN), array($this, 'printEmailValidationSectionInfo'), PostmanAdminController::EMAIL_VALIDATION_OPTIONS); add_settings_field(PostmanOptions::ENVELOPE_SENDER, __('Email Address', Postman::TEXT_DOMAIN), array($this, 'disable_email_validation_callback'), PostmanAdminController::EMAIL_VALIDATION_OPTIONS, PostmanAdminController::EMAIL_VALIDATION_SECTION); // the Logging section add_settings_section(PostmanAdminController::LOGGING_SECTION, __('Email Log Settings', Postman::TEXT_DOMAIN), array($this, 'printLoggingSectionInfo'), PostmanAdminController::LOGGING_OPTIONS); add_settings_field('logging_status', __('Enable Logging', Postman::TEXT_DOMAIN), array($this, 'loggingStatusInputField'), PostmanAdminController::LOGGING_OPTIONS, PostmanAdminController::LOGGING_SECTION); add_settings_field('logging_max_entries', __('Maximum Log Entries', 'Configuration Input Field', Postman::TEXT_DOMAIN), array($this, 'loggingMaxEntriesInputField'), PostmanAdminController::LOGGING_OPTIONS, PostmanAdminController::LOGGING_SECTION); add_settings_field(PostmanOptions::TRANSCRIPT_SIZE, __('Maximum Transcript Size', Postman::TEXT_DOMAIN), array($this, 'transcriptSizeInputField'), PostmanAdminController::LOGGING_OPTIONS, PostmanAdminController::LOGGING_SECTION); // the Network section add_settings_section(PostmanAdminController::NETWORK_SECTION, __('Network Settings', Postman::TEXT_DOMAIN), array($this, 'printNetworkSectionInfo'), PostmanAdminController::NETWORK_OPTIONS); add_settings_field('connection_timeout', _x('TCP Connection Timeout (sec)', 'Configuration Input Field', Postman::TEXT_DOMAIN), array($this, 'connection_timeout_callback'), PostmanAdminController::NETWORK_OPTIONS, PostmanAdminController::NETWORK_SECTION); add_settings_field('read_timeout', _x('TCP Read Timeout (sec)', 'Configuration Input Field', Postman::TEXT_DOMAIN), array($this, 'read_timeout_callback'), PostmanAdminController::NETWORK_OPTIONS, PostmanAdminController::NETWORK_SECTION); // the Advanced section add_settings_section(PostmanAdminController::ADVANCED_SECTION, _x('Miscellaneous Settings', 'Configuration Section Title', Postman::TEXT_DOMAIN), array($this, 'printAdvancedSectionInfo'), PostmanAdminController::ADVANCED_OPTIONS); add_settings_field(PostmanOptions::LOG_LEVEL, _x('PHP Log Level', 'Configuration Input Field', Postman::TEXT_DOMAIN), array($this, 'log_level_callback'), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION); add_settings_field(PostmanOptions::RUN_MODE, _x('Delivery Mode', 'Configuration Input Field', Postman::TEXT_DOMAIN), array($this, 'runModeCallback'), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION); add_settings_field(PostmanOptions::STEALTH_MODE, _x('Stealth Mode', 'This mode removes the Postman X-Mailer signature from emails', Postman::TEXT_DOMAIN), array($this, 'stealthModeCallback'), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION); add_settings_field(PostmanOptions::TEMPORARY_DIRECTORY, __('Temporary Directory', Postman::TEXT_DOMAIN), array($this, 'temporaryDirectoryCallback'), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION); } }
/** * After receiving the authorization code, your application can exchange the code * (along with a client ID and client secret) for an access token and, in some cases, * a refresh token. * * This code is identical for Google and Hotmail * * @see PostmanAuthenticationManager::processAuthorizationGrantCode() */ public function processAuthorizationGrantCode($transactionId) { if (isset($_GET['code'])) { $this->getLogger()->debug('Found authorization code in request header'); $code = $_GET['code']; if (isset($_GET['state']) && $_GET['state'] == $transactionId) { $this->getLogger()->debug('Found valid state in request header'); } else { $this->getLogger()->error('The grant code from Google had no accompanying state and may be a forgery'); throw new PostmanStateIdMissingException(); } $postvals = array('client_id' => $this->getClientId(), 'client_secret' => $this->getClientSecret(), 'grant_type' => 'authorization_code', 'redirect_uri' => $this->getCallbackUri(), 'code' => $code); $response = PostmanUtils::remotePostGetBodyOnly($this->getTokenUrl(), $postvals); $this->processResponse($response); $this->getAuthorizationToken()->setVendorName(self::VENDOR_NAME); return true; } else { $this->getLogger()->debug('Expected code in the request header but found none - user probably denied request'); return false; } }
/** * * @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); }
/** * Functions to execute on the admin_init event * * "Runs at the beginning of every admin page before the page is rendered." * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_an_Admin_Page_Request */ public function on_admin_init() { // only administrators should be able to trigger this if (PostmanUtils::isAdmin()) { $this->registerStylesAndScripts(); } }
/** * * @param unknown $email * @return Ambigous <number, boolean> */ private function validateEmail($email) { return PostmanUtils::validateEmail($email); }
/** * Create the main Postman class to start Postman */ function postman_start($startingMemory) { postman_setupPostman(); PostmanUtils::logMemoryUse($startingMemory, 'Postman'); }
/** * Get the settings option array and print one of its values */ public function basic_auth_password_callback() { print '<input tabindex="99" id="fake_password" name="fake[password]" style="position:absolute; top:-500px;" type="password" value="Safari Autofill Me">'; printf('<input type="password" id="input_basic_auth_password" name="postman_options[basic_auth_password]" value="%s" size="40" class="required" placeholder="Required"/>', null !== $this->options->getPassword() ? esc_attr(PostmanUtils::obfuscatePassword($this->options->getPassword())) : ''); print ' <input type="button" id="togglePasswordField" value="Show Password" class="button button-secondary" style="visibility:hidden" />'; }
/** * This Ajax function retrieves whether a TCP port is open or not */ function runSmtpsTest() { $hostname = trim(PostmanUtils::getRequestParameter('hostname')); $port = intval(PostmanUtils::getRequestParameter('port')); $transport = trim(PostmanUtils::getRequestParameter('transport')); $transportName = trim(PostmanUtils::getRequestParameter('transport_name')); $this->logger->debug(sprintf('testing SMTPS socket %s:%s (%s)', $hostname, $port, $transport)); $portTest = new PostmanPortTest($hostname, $port); $portTest->transportName = $transportName; $success = $portTest->testSmtpsPorts(); $this->buildResponse($hostname, $port, $portTest, $success, $transport); }
/** * Given a hostname, test if it has open ports * * @param string $hostname */ private function talkToMailServer($connectionString) { $this->logger->trace('talkToMailServer()'); $stream = $this->createStream($connectionString, $this->connectionTimeout); if ($stream) { $serverName = PostmanUtils::postmanGetServerName(); @stream_set_timeout($stream, $this->readTimeout); // see http://php.net/manual/en/transports.inet.php#113244 // see http://php.net/stream_socket_enable_crypto $result = $this->readSmtpResponse($stream); if ($result) { $this->reportedHostname = $result; $this->reportedHostnameDomainOnly = $this->getRegisteredDomain($this->reportedHostname); $this->logger->trace(sprintf('comparing %s with %s', $this->reportedHostnameDomainOnly, $this->hostnameDomainOnly)); $this->mitm = true; // MITM exceptions if ($this->reportedHostnameDomainOnly == 'google.com' && $this->hostnameDomainOnly == 'gmail.com') { $this->mitm = false; } elseif ($this->reportedHostnameDomainOnly == 'hotmail.com' && $this->hostnameDomainOnly == 'live.com') { $this->mitm = false; } elseif ($this->reportedHostnameDomainOnly == $this->hostnameDomainOnly) { $this->mitm = false; } $this->debug(sprintf('domain name: %s (%s)', $this->reportedHostname, $this->reportedHostnameDomainOnly)); $this->sendSmtpCommand($stream, sprintf('EHLO %s', $serverName)); $this->readSmtpResponse($stream); if ($this->checkStartTls) { $this->sendSmtpCommand($stream, 'STARTTLS'); $this->readSmtpResponse($stream); $starttlsSuccess = @stream_socket_enable_crypto($stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); if ($starttlsSuccess) { $this->startTls = true; $this->secure = true; $this->sendSmtpCommand($stream, sprintf('EHLO %s', $serverName)); $this->readSmtpResponse($stream); } else { $this->error('starttls failed'); } } fclose($stream); $this->debug('return true'); return true; } else { fclose($stream); $this->debug('return false'); return false; } } else { return false; } }
/** * Step 5: Exchange refresh token for new access token * After the access token expires, you can use the refresh token, which has a long lifetime, to get a new access token. */ public function refreshToken() { $this->getLogger()->debug('Refreshing Token'); $refreshUrl = $this->getTokenUrl(); $callbackUrl = $this->getCallbackUri(); assert(!empty($refreshUrl)); assert(!empty($callbackUrl)); $headers = array('Authorization' => sprintf("Basic %s", base64_encode($this->getClientId() . ':' . $this->getClientSecret()))); $postvals = array('redirect_uri' => $callbackUrl, 'grant_type' => 'refresh_token', 'refresh_token' => $this->getAuthorizationToken()->getRefreshToken()); $response = PostmanUtils::remotePostGetBodyOnly($this->getTokenUrl(), $postvals, $headers); $this->processResponse($response); }
/** */ public function mandrill_api_key_callback() { printf('<input type="password" autocomplete="off" id="mandrill_api_key" name="postman_options[mandrill_api_key]" value="%s" size="60" class="required" placeholder="%s"/>', null !== $this->options->getMandrillApiKey() ? esc_attr(PostmanUtils::obfuscatePassword($this->options->getMandrillApiKey())) : '', __('Required', Postman::TEXT_DOMAIN)); print ' <input type="button" id="toggleMandrillApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />'; }
/** * This is the general message that Postman requires configuration, to warn users who think * the plugin is ready-to-go as soon as it is activated. * This message only goes away once * the plugin is configured. */ public function display_configuration_required_warning() { $this->logger->debug('Displaying configuration required warning'); $message = sprintf(__('WordPress is still handling email delivery, <em>not</em> Postman.', 'postman-smtp')); $message .= ' '; /* translators: where %s is the URL to the Postman Setup page */ $message .= sprintf(__('<a href="%s">Configure</a> the plugin.', 'postman-smtp'), PostmanUtils::getSettingsPageUrl()); $this->messageHandler->printMessage($message, PostmanMessageHandler::WARNING_CLASS); }
/** * Constructor * * @param PostmanOptions $options */ function __construct() { $this->options = PostmanOptions::getInstance(); $this->authorizationToken = PostmanOAuthToken::getInstance(); $this->diagnostics = ''; PostmanUtils::registerAjaxHandler('postman_diagnostics', $this, 'getDiagnostics'); }
/** * Handles the authorization grant */ function handleAuthorizationGrant() { $logger = $this->logger; $options = $this->options; $authorizationToken = $this->authorizationToken; $logger->debug('Authorization in progress'); $transactionId = PostmanSession::getInstance()->getOauthInProgress(); // begin transaction PostmanUtils::lock(); $authenticationManager = PostmanAuthenticationManagerFactory::getInstance()->createAuthenticationManager(); try { if ($authenticationManager->processAuthorizationGrantCode($transactionId)) { $logger->debug('Authorization successful'); // save to database $authorizationToken->save(); $this->messageHandler->addMessage(__('The OAuth 2.0 authorization was successful. Ready to send e-mail.', Postman::TEXT_DOMAIN)); } else { $this->messageHandler->addError(__('Your email provider did not grant Postman permission. Try again.', Postman::TEXT_DOMAIN)); } } catch (PostmanStateIdMissingException $e) { $this->messageHandler->addError(__('The grant code from Google had no accompanying state and may be a forgery', Postman::TEXT_DOMAIN)); } catch (Exception $e) { $logger->error('Error: ' . get_class($e) . ' code=' . $e->getCode() . ' message=' . $e->getMessage()); /* translators: %s is the error message */ $this->messageHandler->addError(sprintf(__('Error authenticating with this Client ID. [%s]', Postman::TEXT_DOMAIN), '<em>' . $e->getMessage() . '</em>')); } // clean-up PostmanUtils::unlock(); PostmanSession::getInstance()->unsetOauthInProgress(); // redirect home PostmanUtils::redirect(PostmanUtils::POSTMAN_HOME_PAGE_RELATIVE_URL); }
/** * This is the general message that Postman requires configuration, to warn users who think * the plugin is ready-to-go as soon as it is activated. * This message only goes away once the plugin is configured. */ public function display_configuration_required_warning() { if (PostmanUtils::isAdmin()) { if ($this->logger->isDebug()) { $this->logger->debug('Displaying configuration required warning'); } $message = sprintf(PostmanTransportRegistry::getInstance()->getReadyMessage()); $goToSettings = sprintf('<a href="%s">%s</a>', PostmanUtils::getSettingsPageUrl(), __('Settings', Postman::TEXT_DOMAIN)); $goToEmailLog = sprintf('%s', _x('Email Log', 'The log of Emails that have been delivered', Postman::TEXT_DOMAIN)); if (PostmanOptions::getInstance()->isMailLoggingEnabled()) { $goToEmailLog = sprintf('<a href="%s">%s</a>', PostmanUtils::getEmailLogPageUrl(), $goToEmailLog); } $message .= sprintf(' %s | %s', $goToEmailLog, $goToSettings); $this->messageHandler->printMessage($message, PostmanMessageHandler::WARNING_CLASS); } }
/** * Handle activation of plugin */ private function handleOptionUpdates() { $this->logger->debug("Activating plugin"); // prior to version 0.2.5, $authOptions did not exist $authOptions = get_option('postman_auth_token'); $options = get_option('postman_options'); $postmanState = get_option('postman_state'); if (empty($authOptions) && !empty($options) && !empty($options['access_token'])) { $this->logger->debug("Upgrading database: copying Authorization token from postman_options to postman_auth_token"); // copy the variables from $options to $authToken $authOptions['access_token'] = $options['access_token']; $authOptions['refresh_token'] = $options['refresh_token']; // there was a bug where we weren't setting the expiry time if (!empty($options['auth_token_expires'])) { $authOptions['auth_token_expires'] = $options['auth_token_expires']; } update_option('postman_auth_token', $authOptions); } if (!isset($options['authorization_type']) && !isset($options['auth_type'])) { // prior to 1.0.0, access tokens were saved in authOptions without an auth type // prior to 0.2.5, access tokens were save in options without an auth type // either way, only oauth2 was supported if (isset($authOptions['access_token']) || isset($options['access_token'])) { $this->logger->debug("Upgrading database: setting authorization_type to 'oauth2'"); $options['authorization_type'] = 'oauth2'; update_option('postman_options', $options); } } if (!isset($options['enc_type'])) { // prior to 1.3, encryption type was combined with authentication type if (isset($options['authorization_type'])) { $this->logger->debug("Upgrading database: creating auth_type and enc_type from authorization_type"); $authType = $options['authorization_type']; switch ($authType) { case 'none': $options['auth_type'] = 'none'; $options['enc_type'] = 'none'; break; case 'basic-ssl': $options['auth_type'] = 'login'; $options['enc_type'] = 'ssl'; break; case 'basic-tls': $options['auth_type'] = 'login'; $options['enc_type'] = 'tls'; break; case 'oauth2': $options['auth_type'] = 'oauth2'; $options['enc_type'] = 'ssl'; break; default: } update_option('postman_options', $options); } } // prior to 1.3.3, the version identifier was not stored and the passwords were plaintext if (isset($options['enc_type']) && !(isset($options['version']) || isset($postmanState['version']))) { $this->logger->debug("Upgrading database: added plugin version and encoding password"); $options['version'] = '1.3.3'; if (isset($options['basic_auth_password'])) { $options['basic_auth_password'] = base64_encode($options['basic_auth_password']); } update_option('postman_options', $options); } // prior to 1.4.2, the transport was not identified and the auth token had no vendor if (isset($options['auth_type']) && !isset($options['transport_type'])) { $this->logger->debug("Upgrading database: added transport_type and vendor_name"); $options['transport_type'] = 'smtp'; update_option('postman_options', $options); if (isset($authOptions['access_token']) && isset($options['oauth_client_id'])) { // if there is a stored token.. if (PostmanUtils::endsWith($options['oauth_client_id'], 'googleusercontent.com')) { $authOptions['vendor_name'] = 'google'; } else { if (strlen($options['oauth_client_id'] < strlen($options['oauth_client_secret']))) { $authOptions['vendor_name'] = 'microsoft'; } else { $authOptions['vendor_name'] = 'yahoo'; } } update_option('postman_auth_token', $authOptions); } } // for version 1.6.18, the envelope from was introduced if (!empty($options['sender_email']) && empty($options['envelope_sender'])) { $this->logger->debug("Upgrading database: adding envelope_sender"); $options['envelope_sender'] = $options['sender_email']; update_option('postman_options', $options); } if (isset($postmanState['version']) && version_compare($postmanState['version'], '1.7.0', '<')) { if ($options['mail_log_max_entries'] == 10) { $options['mail_log_max_entries'] = 250; } $postmanStats = get_option('postman_stats'); $stateCleared = false; if (!isset($postmanState['delivery_success_total']) && isset($postmanStats['delivery_success_total'])) { $postmanState['delivery_success_total'] = $postmanStats['delivery_success_total']; $stateCleared = true; } if (!isset($postmanState['delivery_fail_total']) && isset($postmanStats['delivery_fail_total'])) { $postmanState['delivery_fail_total'] = $postmanStats['delivery_fail_total']; $stateCleared = true; } if ($stateCleared) { delete_option('postman_stats'); } } // can we create a tmp file? - this code is duplicated in InputSanitizer PostmanUtils::deleteLockFile(); $lockSuccess = PostmanUtils::createLockFile(); // &= does not work as expected in my PHP $lockSuccess = $lockSuccess && PostmanUtils::deleteLockFile(); $postmanState['locking_enabled'] = $lockSuccess; // always update the version number if (!isset($postmanState['install_date'])) { $this->logger->debug("Upgrading database: adding install_date"); $postmanState['install_date'] = time(); } $pluginData = apply_filters('postman_get_plugin_metadata', null); $postmanState['version'] = $pluginData['version']; update_option('postman_state', $postmanState); // delete_option('postman_session'); // reload options PostmanState::getInstance()->reload(); PostmanOptions::getInstance()->reload(); }
/** * From http://www.hughlashbrooke.com/2014/02/wordpress-add-items-glance-widget/ * http://coffeecupweb.com/how-to-add-custom-post-types-to-at-a-glance-dashboard-widget-in-wordpress/ * * @param unknown $items * @return string */ function customizeAtAGlanceDashboardWidget($items = array()) { // only modify the At-a-Glance for administrators if (PostmanUtils::isAdmin()) { $post_types = array(PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG); foreach ($post_types as $type) { if (!post_type_exists($type)) { continue; } $num_posts = wp_count_posts($type); if ($num_posts) { $published = intval($num_posts->publish); $privated = intval($num_posts->private); $post_type = get_post_type_object($type); $text = _n('%s ' . $post_type->labels->singular_name, '%s ' . $post_type->labels->name, $privated, Postman::TEXT_DOMAIN); $text = sprintf($text, number_format_i18n($privated)); $items[] = sprintf('<a class="%1$s-count" href="%3$s">%2$s</a>', $type, $text, PostmanUtils::getEmailLogPageUrl()) . "\n"; } } return $items; } }
/** * Clean up after sending the mail * * @param PostmanZendMailEngine $engine * @param unknown $startTime */ private function postSend(PostmanMailEngine $engine, $startTime, PostmanOptions $options, PostmanModuleTransport $transport) { // save the transcript $this->transcript = $engine->getTranscript(); // log the transcript if ($this->logger->isTrace()) { $this->logger->trace('Transcript:'); $this->logger->trace($this->transcript); } // delete the semaphore if ($transport->isLockingRequired()) { PostmanUtils::unlock(); } // stop the clock $endTime = microtime(true) * 1000; $this->totalTime = $endTime - $startTime; }
/** * Sanitize each setting field as needed * * @param array $input * Contains all settings fields as array keys */ public function sanitize($input) { $this->logger->debug("Sanitizing data before storage"); $new_input = array(); $success = true; $this->sanitizeString('Encryption Type', PostmanOptions::SECURITY_TYPE, $input, $new_input); $this->sanitizeString('Hostname', PostmanOptions::HOSTNAME, $input, $new_input); if (!empty($input[PostmanOptions::PORT])) { $port = absint($input[PostmanOptions::PORT]); if ($port > 0) { $this->sanitizeInt('Port', PostmanOptions::PORT, $input, $new_input); } else { $new_input[PostmanOptions::PORT] = $this->options->getPort(); add_settings_error(PostmanOptions::PORT, PostmanOptions::PORT, 'Invalid TCP Port', 'error'); $success = false; } } // check the auth type AFTER the hostname because we reset the hostname if auth is bad $this->sanitizeString('From Email', PostmanOptions::MESSAGE_SENDER_EMAIL, $input, $new_input); // the wizard doesn't set an envelope sender, so we'll default it to From Email $new_input[PostmanOptions::ENVELOPE_SENDER] = $new_input[PostmanOptions::MESSAGE_SENDER_EMAIL]; $this->sanitizeString('Sender Email', PostmanOptions::ENVELOPE_SENDER, $input, $new_input); $this->sanitizeString('Transport Type', PostmanOptions::TRANSPORT_TYPE, $input, $new_input); $this->sanitizeString('Authorization Type', PostmanOptions::AUTHENTICATION_TYPE, $input, $new_input); $this->sanitizeString('From Name', PostmanOptions::MESSAGE_SENDER_NAME, $input, $new_input); $this->sanitizeString('Client ID', PostmanOptions::CLIENT_ID, $input, $new_input); $this->sanitizeString('Client Secret', PostmanOptions::CLIENT_SECRET, $input, $new_input); $this->sanitizeString('Username', PostmanOptions::BASIC_AUTH_USERNAME, $input, $new_input); $this->sanitizePassword('Password', PostmanOptions::BASIC_AUTH_PASSWORD, $input, $new_input, $this->options->getPassword()); $this->sanitizePassword('Mandrill API Key', PostmanOptions::MANDRILL_API_KEY, $input, $new_input, $this->options->getMandrillApiKey()); $this->sanitizePassword('SendGrid API Key', PostmanOptions::SENDGRID_API_KEY, $input, $new_input, $this->options->getSendGridApiKey()); $this->sanitizeString('Reply-To', PostmanOptions::REPLY_TO, $input, $new_input); $this->sanitizeString('From Name Override', PostmanOptions::PREVENT_MESSAGE_SENDER_NAME_OVERRIDE, $input, $new_input); $this->sanitizeString('From Email Override', PostmanOptions::PREVENT_MESSAGE_SENDER_EMAIL_OVERRIDE, $input, $new_input); $this->sanitizeString('Disable Email Validation', PostmanOptions::DISABLE_EMAIL_VALIDAITON, $input, $new_input); $this->sanitizeString('Forced To Recipients', PostmanOptions::FORCED_TO_RECIPIENTS, $input, $new_input); $this->sanitizeString('Forced CC Recipients', PostmanOptions::FORCED_CC_RECIPIENTS, $input, $new_input); $this->sanitizeString('Forced BCC Recipients', PostmanOptions::FORCED_BCC_RECIPIENTS, $input, $new_input); $this->sanitizeString('Additional Headers', PostmanOptions::ADDITIONAL_HEADERS, $input, $new_input); $this->sanitizeInt('Read Timeout', PostmanOptions::READ_TIMEOUT, $input, $new_input); $this->sanitizeInt('Conenction Timeout', PostmanOptions::CONNECTION_TIMEOUT, $input, $new_input); $this->sanitizeInt('Log Level', PostmanOptions::LOG_LEVEL, $input, $new_input); $this->sanitizeString('Email Log Enabled', PostmanOptions::MAIL_LOG_ENABLED_OPTION, $input, $new_input); $this->sanitizeLogMax('Email Log Max Entries', PostmanOptions::MAIL_LOG_MAX_ENTRIES, $input, $new_input); $this->sanitizeString('Run Mode', PostmanOptions::RUN_MODE, $input, $new_input); $this->sanitizeString('Stealth Mode', PostmanOptions::STEALTH_MODE, $input, $new_input); $this->sanitizeInt('Transcript Size', PostmanOptions::TRANSCRIPT_SIZE, $input, $new_input); $this->sanitizeString('Temporary Directory', PostmanOptions::TEMPORARY_DIRECTORY, $input, $new_input); if ($new_input[PostmanOptions::CLIENT_ID] != $this->options->getClientId() || $new_input[PostmanOptions::CLIENT_SECRET] != $this->options->getClientSecret() || $new_input[PostmanOptions::HOSTNAME] != $this->options->getHostname()) { $this->logger->debug("Recognized new Client ID"); // the user entered a new client id and we should destroy the stored auth token delete_option(PostmanOAuthToken::OPTIONS_NAME); } // can we create a tmp file? - this code is duplicated in ActivationHandler PostmanUtils::deleteLockFile($new_input[PostmanOptions::TEMPORARY_DIRECTORY]); $lockSuccess = PostmanUtils::createLockFile($new_input[PostmanOptions::TEMPORARY_DIRECTORY]); // &= does not work as expected in my PHP $lockSuccess = $lockSuccess && PostmanUtils::deleteLockFile($new_input[PostmanOptions::TEMPORARY_DIRECTORY]); $this->logger->debug('FileLocking=' . $lockSuccess); PostmanState::getInstance()->setFileLockingEnabled($lockSuccess); if ($success) { PostmanSession::getInstance()->setAction(self::VALIDATION_SUCCESS); } else { PostmanSession::getInstance()->setAction(self::VALIDATION_FAILED); } return $new_input; }
/** * (non-PHPdoc) * * @see PostmanSmtpEngine::send() */ public function send(PostmanMessage $message) { $this->logger->debug("Prepping Zend"); $envelopeFrom = new PostmanEmailAddress($this->transport->getEnvelopeFromEmailAddress()); if ($this->transport->isEnvelopeFromValidationSupported()) { // validate the envelope from since we didn't do it in the Message $envelopeFrom->validate('Envelope From'); } // create the Message $charset = $message->getCharset(); $this->logger->debug('Building Postman_Zend_Mail with charset=' . $charset); $mail = new Postman_Zend_Mail($charset); // add the Postman signature - append it to whatever the user may have set if (!PostmanOptions::getInstance()->isStealthModeEnabled()) { $pluginData = apply_filters('postman_get_plugin_metadata', null); $mail->addHeader('X-Mailer', sprintf('Postman SMTP %s for WordPress (%s)', $pluginData['version'], 'https://wordpress.org/plugins/postman-smtp/')); } // add the headers - see http://framework.zend.com/manual/1.12/en/zend.mail.additional-headers.html foreach ((array) $message->getHeaders() as $header) { $this->logger->debug(sprintf('Adding user header %s=%s', $header['name'], $header['content'])); $mail->addHeader($header['name'], $header['content'], true); } // if the caller set a Content-Type header, use it $contentType = $message->getContentType(); if (!empty($contentType)) { $mail->addHeader('Content-Type', $contentType, false); $this->logger->debug('Adding content-type ' . $contentType); } // add the From Header $fromHeader = $this->addFrom($message, $mail); $fromHeader->log($this->logger, 'From'); // add the Sender Header, overriding what the user may have set $mail->addHeader('Sender', $this->transport->getFromEmailAddress(), false); // from RFC 5321: http://tools.ietf.org/html/rfc5321#section-4.4 // A message-originating SMTP system SHOULD NOT send a message that // already contains a Return-path header field. // I changed Zend/Mail/Mail.php to fix this $mail->setReturnPath($this->transport->getEnvelopeFromEmailAddress()); // add the to recipients foreach ((array) $message->getToRecipients() as $recipient) { $recipient->log($this->logger, 'To'); $mail->addTo($recipient->getEmail(), $recipient->getName()); } // add the cc recipients foreach ((array) $message->getCcRecipients() as $recipient) { $recipient->log($this->logger, 'Cc'); $mail->addCc($recipient->getEmail(), $recipient->getName()); } // add the to recipients foreach ((array) $message->getBccRecipients() as $recipient) { $recipient->log($this->logger, 'Bcc'); $mail->addBcc($recipient->getEmail(), $recipient->getName()); } // add the reply-to $replyTo = $message->getReplyTo(); // $replyTo is null or a PostmanEmailAddress object if (isset($replyTo)) { $mail->setReplyTo($replyTo->getEmail(), $replyTo->getName()); } // add the date $date = $message->getDate(); if (!empty($date)) { $mail->setDate($date); } // add the messageId $messageId = $message->getMessageId(); if (!empty($messageId)) { $mail->setMessageId($messageId); } // add the subject if (null !== $message->getSubject()) { $mail->setSubject($message->getSubject()); } $textPart = $message->getBodyTextPart(); if (!empty($textPart)) { $this->logger->debug('Adding body as text'); $mail->setBodyText($textPart); } $htmlPart = $message->getBodyHtmlPart(); if (!empty($htmlPart)) { $this->logger->debug('Adding body as html'); $mail->setBodyHtml($htmlPart); } // add attachments $this->logger->debug("Adding attachments"); $message->addAttachmentsToMail($mail); // create the SMTP transport $this->logger->debug("Create the Zend_Mail transport"); $zendTransport = $this->transport->createZendMailTransport($this->transport->getHostname(), array()); try { // send the message $this->logger->debug("Sending mail"); $mail->send($zendTransport); if ($this->logger->isInfo()) { $this->logger->info(sprintf('Message %d accepted for delivery', PostmanState::getInstance()->getSuccessfulDeliveries() + 1)); } // finally not supported?? if ($zendTransport->getConnection() && !PostmanUtils::isEmpty($zendTransport->getConnection()->getLog())) { $this->transcript = $zendTransport->getConnection()->getLog(); } else { if (method_exists($zendTransport, 'getTranscript') && !PostmanUtils::isEmpty($zendTransport->getTranscript())) { // then use the API response $this->transcript = $zendTransport->getTranscript(); } else { if (method_exists($zendTransport, 'getMessage') && !PostmanUtils::isEmpty($zendTransport->getMessage())) { // then use the Raw Message as the Transcript $this->transcript = $zendTransport->getMessage(); } } } } catch (Exception $e) { // finally not supported?? if ($zendTransport->getConnection() && !PostmanUtils::isEmpty($zendTransport->getConnection()->getLog())) { $this->transcript = $zendTransport->getConnection()->getLog(); } else { if (method_exists($zendTransport, 'getTranscript') && !PostmanUtils::isEmpty($zendTransport->getTranscript())) { // then use the API response $this->transcript = $zendTransport->getTranscript(); } else { if (method_exists($zendTransport, 'getMessage') && !PostmanUtils::isEmpty($zendTransport->getMessage())) { // then use the Raw Message as the Transcript $this->transcript = $zendTransport->getMessage(); } } } // get the current exception message $message = $e->getMessage(); if ($e->getCode() == 334) { // replace the unusable Google message with a better one in the case of code 334 $message = sprintf(__('Communication Error [334] - make sure the Envelope From email is the same account used to create the Client ID.', Postman::TEXT_DOMAIN)); } // create a new exception $newException = new Exception($message, $e->getCode()); // throw the new exception after handling throw $newException; } }
/** * Does this hostname belong to Google? * * @param unknown $hostname * @return boolean */ static function isGoogle($hostname) { return PostmanUtils::endsWith($hostname, 'gmail.com') || PostmanUtils::endsWith($hostname, 'googleapis.com'); }
/** */ public function outputTestEmailWizardContent() { print '<div class="wrap">'; $this->outputChildPageHeader(__('Send a Test Email', 'postman-smtp')); printf('<form id="postman_test_email_wizard" method="post" action="%s">', PostmanUtils::getSettingsPageUrl()); // Step 1 printf('<h5>%s</h5>', __('Specify the Recipient', 'postman-smtp')); print '<fieldset>'; printf('<legend>%s</legend>', __('Who is this message going to?', 'postman-smtp')); printf('<p>%s', __('This utility allows you to send an email message for testing.', 'postman-smtp')); print ' '; /* translators: where %d is an amount of time, in seconds */ printf('%s</p>', sprintf(_n('If there is a problem, Postman will give up after %d second.', 'If there is a problem, Postman will give up after %d seconds.', $this->options->getReadTimeout(), 'postman-smtp'), $this->options->getReadTimeout())); printf('<label for="postman_test_options[test_email]">%s</label>', _x('Recipient Email Address', 'Configuration Input Field', 'postman-smtp')); print $this->adminController->test_email_callback(); print '</fieldset>'; // Step 2 printf('<h5>%s</h5>', __('Send The Message', 'postman-smtp')); print '<fieldset>'; print '<legend>'; print __('Sending the message:', 'postman-smtp'); printf(' <span id="postman_test_message_status">%s</span>', _x('In Outbox', 'Email Test Status', 'postman-smtp')); print '</legend>'; print '<section>'; printf('<p><label>%s</label></p>', _x('Status', 'Was sending this email successful or not?', 'postman-smtp')); print '<textarea id="postman_test_message_error_message" readonly="readonly" cols="65" rows="4"></textarea>'; print '</section>'; print '</fieldset>'; // Step 3 printf('<h5>%s</h5>', __('Session Transcript', 'postman-smtp')); print '<fieldset>'; printf('<legend>%s</legend>', __('Examine the SMTP Session Transcript if you need to.', 'postman-smtp')); printf('<p>%s</p>', __('This is the conversation between Postman and your SMTP server. It can be useful for diagnosing problems. <b>DO NOT</b> post it on-line, it may contain your account password.', 'postman-smtp')); print '<section>'; printf('<p><label for="postman_test_message_transcript">%s</label></p>', __('SMTP Session Transcript', 'postman-smtp')); print '<textarea readonly="readonly" id="postman_test_message_transcript" cols="65" rows="8"></textarea>'; print '</section>'; print '</fieldset>'; print '</form>'; print '</div>'; }
public function isYahoo() { return PostmanUtils::endsWith($this->hostname, 'yahoo.com'); }
/** * (non-PHPdoc) * * @see PostmanSmtpEngine::send() */ public function send(PostmanMessage $message, $hostname) { $options = PostmanOptions::getInstance(); // create the Message $charset = $message->getCharset(); $this->logger->debug('Building Postman_Zend_Mail with charset=' . $charset); $mail = new Postman_Zend_Mail($charset); // add the Postman signature - append it to whatever the user may have set if (!$options->isStealthModeEnabled()) { $pluginData = apply_filters('postman_get_plugin_metadata', null); $mail->addHeader('X-Mailer', sprintf('Postman SMTP %s for WordPress (%s)', $pluginData['version'], 'https://wordpress.org/plugins/postman-smtp/')); } // add the headers - see http://framework.zend.com/manual/1.12/en/zend.mail.additional-headers.html foreach ((array) $message->getHeaders() as $header) { $this->logger->debug(sprintf('Adding user header %s=%s', $header['name'], $header['content'])); $mail->addHeader($header['name'], $header['content'], true); } // modify the content-type to include the boundary $contentType = $message->getContentType(); if (false !== stripos($contentType, 'multipart') && !empty($this->boundary)) { // Lines in email are terminated by CRLF ("\r\n") according to RFC2821 $contentType = sprintf("%s;\r\n\t boundary=\"%s\"", $contentType, $message->getBoundary()); } // if the caller set a Content-Type header, push it into the $mail object if (!empty($contentType)) { $mail->addHeader('Content-Type', $contentType, false); $this->logger->debug('Adding content-type ' . $contentType); } // add the From Header $fromHeader = $this->addFrom($message, $mail); $fromHeader->log($this->logger, 'From'); // add the Sender Header, overriding what the user may have set $mail->addHeader('Sender', $options->getEnvelopeSender(), false); // from RFC 5321: http://tools.ietf.org/html/rfc5321#section-4.4 // A message-originating SMTP system SHOULD NOT send a message that // already contains a Return-path header field. // I changed Zend/Mail/Mail.php to fix this $mail->setReturnPath($options->getEnvelopeSender()); // add the to recipients foreach ((array) $message->getToRecipients() as $recipient) { $recipient->log($this->logger, 'To'); $mail->addTo($recipient->getEmail(), $recipient->getName()); } // add the cc recipients foreach ((array) $message->getCcRecipients() as $recipient) { $recipient->log($this->logger, 'Cc'); $mail->addCc($recipient->getEmail(), $recipient->getName()); } // add the to recipients foreach ((array) $message->getBccRecipients() as $recipient) { $recipient->log($this->logger, 'Bcc'); $mail->addBcc($recipient->getEmail(), $recipient->getName()); } // add the reply-to $replyTo = $message->getReplyTo(); // $replyTo is null or a PostmanEmailAddress object if (isset($replyTo)) { $mail->setReplyTo($replyTo->getEmail(), $replyTo->getName()); } // add the date $date = $message->getDate(); if (!empty($date)) { $mail->setDate($date); } // add the messageId $messageId = $message->getMessageId(); if (!empty($messageId)) { $mail->setMessageId($messageId); } // add the subject if (null !== $message->getSubject()) { $mail->setSubject($message->getSubject()); } // add the message content as either text or html $bodyTextPart = $message->getBodyTextPart(); $bodyHtmlPart = $message->getBodyHtmlPart(); if (!empty($bodyTextPart) && empty($bodyHtmlPart)) { $this->logger->debug('Adding body as text'); $mail->setBodyText($message->getBody()); } else { if (empty($bodyTextPart) && !empty($bodyHtmlPart)) { $this->logger->debug('Adding body as html'); $mail->setBodyHtml($message->getBody()); } else { if (!empty($bodyTextPart) && !empty($bodyHtmlPart)) { $this->logger->debug('Adding body as text and html'); $mail->setBodyHtml($message->getBodyHtmlPart()); $mail->setBodyText($message->getBodyTextPart()); } else { if (empty($contentType) || substr($contentType, 0, 10) === 'text/plain') { $this->logger->debug('Adding body as text'); $mail->setBodyText($message->getBody()); } else { if (substr($contentType, 0, 9) === 'text/html') { $this->logger->debug('Adding body as html'); $mail->setBodyHtml($message->getBody()); } else { if (substr($contentType, 0, 21) === 'multipart/alternative') { $this->logger->debug('Adding body as multipart/alternative'); $arr = explode(PHP_EOL, $message->getBody()); $textBody = ''; $htmlBody = ''; $mode = ''; foreach ($arr as $s) { if (substr($s, 0, 25) === "Content-Type: text/plain;") { $mode = 'foundText'; } else { if (substr($s, 0, 24) === "Content-Type: text/html;") { $mode = 'foundHtml'; } else { if ($mode == 'textReading') { $textBody .= $s; } else { if ($mode == 'htmlReading') { $htmlBody .= $s; } else { if ($mode == 'foundText') { if ($s == '') { $mode = 'textReading'; } } else { if ($mode == 'foundHtml') { if ($s == '') { $mode = 'htmlReading'; } } } } } } } } $mail->setBodyHtml($htmlBody); $mail->setBodyText($textBody); } else { $this->logger->error('Unknown content-type: ' . $contentType); $mail->setBodyText($message->getBody()); } } } } } } // add attachments $this->logger->debug("Adding attachments"); $message->addAttachmentsToMail($mail); // get the transport configuration $this->logger->debug("Create the Zend_Mail transport configuration array"); $config = $this->authenticator->createConfig($this->transport); assert(!empty($config)); // create the SMTP transport $this->logger->debug("Create the Zend_Mail transport configuration"); $zendTransport = $this->transport->createZendMailTransport($hostname, $config); assert(!empty($zendTransport)); try { // send the message $this->logger->debug("Sending mail"); $mail->send($zendTransport); // finally not supported?? if ($zendTransport->getConnection() && !PostmanUtils::isEmpty($zendTransport->getConnection()->getLog())) { $this->transcript = $zendTransport->getConnection()->getLog(); $this->logger->trace($this->transcript); } else { if (method_exists($zendTransport, 'getMessage') && !PostmanUtils::isEmpty($zendTransport->getMessage())) { // then use the Raw Message as the Transcript $this->transcript = $zendTransport->getMessage(); $this->logger->trace($this->transcript); } } } catch (Exception $e) { // finally not supported?? if ($zendTransport->getConnection() && !PostmanUtils::isEmpty($zendTransport->getConnection()->getLog())) { $this->transcript = $zendTransport->getConnection()->getLog(); $this->logger->trace($this->transcript); } else { if (method_exists($zendTransport, 'getMessage') && !PostmanUtils::isEmpty($zendTransport->getMessage())) { // then use the Raw Message as the Transcript $this->transcript = $zendTransport->getMessage(); $this->logger->trace($this->transcript); } } // get the current exception message $message = $e->getMessage(); if ($e->getCode() == 334) { // replace the unusable Google message with a better one in the case of code 334 $message = sprintf(__('Communication Error [334] - make sure the Envelope From email is the same account used to create the Client ID.', 'postman-smtp')); } // create a new exception $newException = new Exception($message, $e->getCode()); // throw the new exception after handling throw $newException; } }