public function createAuthenticationManager(PostmanTransport $transport, PostmanOptions $options, PostmanOAuthToken $authorizationToken, PostmanConfigTextHelper $scribe = null) { $authenticationType = $options->getAuthenticationType(); $hostname = $options->getHostname(); $clientId = $options->getClientId(); $clientSecret = $options->getClientSecret(); $senderEmail = $options->getMessageSenderEmail(); if (!isset($scribe)) { $transport = PostmanTransportRegistry::getInstance()->getCurrentTransport(); $scribe = PostmanConfigTextHelperFactory::createScribe($hostname, $transport); } $redirectUrl = $scribe->getCallbackUrl(); if ($transport->isOAuthUsed($options->getAuthenticationType()) && $transport->isServiceProviderGoogle($hostname)) { $authenticationManager = new PostmanGoogleAuthenticationManager($clientId, $clientSecret, $authorizationToken, $redirectUrl, $senderEmail); } else { if ($transport->isOAuthUsed($options->getAuthenticationType()) && $transport->isServiceProviderMicrosoft($hostname)) { $authenticationManager = new PostmanMicrosoftAuthenticationManager($clientId, $clientSecret, $authorizationToken, $redirectUrl); } else { if ($transport->isOAuthUsed($options->getAuthenticationType()) && $transport->isServiceProviderYahoo($hostname)) { $authenticationManager = new PostmanYahooAuthenticationManager($clientId, $clientSecret, $authorizationToken, $redirectUrl); } else { $authenticationManager = new PostmanNonOAuthAuthenticationManager(); } } } $this->logger->debug('Created ' . get_class($authenticationManager)); return $authenticationManager; }
/** * Important: bind() may be called multiple times * * Replace wp_mail() after making sure: * 1) the plugin has not already bound to wp_mail and * 2) wp_mail is available for use * 3) the plugin is properly configured. * 4) the plugin's prerequisites are met. */ function bind() { if (!$this->bound) { $binderOptions = PostmanOptions::getInstance(); $binderAuthorizationToken = PostmanOAuthToken::getInstance(); $ready = true; if (function_exists('wp_mail')) { // If the function exists, it's probably because another plugin has // replaced the pluggable function first, and we set an error flag. // this is an error message because it is a Bind error $this->logger->error('wp_mail is already bound, Postman can not use it'); $this->bindError = true; } if (!PostmanTransportRegistry::getInstance()->isPostmanReadyToSendEmail($binderOptions, $binderAuthorizationToken)) { // this is a debug message because bound may be called again with a NEW transport that IS configured // this is a debug message because it is not up to the Binder to report transport errors $this->logger->debug('Transport is not configured and ready'); $ready = false; } if (!PostmanPreRequisitesCheck::isReady()) { // this is a debug message because it is not up to the Binder to report transport errors $this->logger->debug('Prerequisite check failed'); $ready = false; } if ($ready && !$this->bindError) { $this->logger->debug('Binding to wp_mail()'); $this->replacePluggableFunctionWpMail(); } } }
private function createManager(PostmanZendModuleTransport $transport) { $options = PostmanOptions::getInstance(); $authorizationToken = PostmanOAuthToken::getInstance(); $authenticationType = $options->getAuthenticationType(); $hostname = $options->getHostname(); $clientId = $options->getClientId(); $clientSecret = $options->getClientSecret(); $senderEmail = $options->getMessageSenderEmail(); $scribe = $transport->getScribe(); $redirectUrl = $scribe->getCallbackUrl(); if ($transport->isOAuthUsed($options->getAuthenticationType())) { if ($transport->isServiceProviderGoogle($hostname)) { $authenticationManager = new PostmanGoogleAuthenticationManager($clientId, $clientSecret, $authorizationToken, $redirectUrl, $senderEmail); } else { if ($transport->isServiceProviderMicrosoft($hostname)) { $authenticationManager = new PostmanMicrosoftAuthenticationManager($clientId, $clientSecret, $authorizationToken, $redirectUrl); } else { if ($transport->isServiceProviderYahoo($hostname)) { $authenticationManager = new PostmanYahooAuthenticationManager($clientId, $clientSecret, $authorizationToken, $redirectUrl); } else { assert(false); } } } } else { $authenticationManager = new PostmanNonOAuthAuthenticationManager(); } $this->logger->debug('Created ' . get_class($authenticationManager)); return $authenticationManager; }
function __construct($name) { $this->name = $name; $this->wpDebug = defined('WP_DEBUG'); if (class_exists('PostmanOptions')) { $this->logLevel = PostmanOptions::getInstance()->getLogLevel(); } else { $this->logLevel = self::OFF_INT; } }
/** * Constructor * * @param unknown $rootPluginFilenameAndPath */ public function __construct($rootPluginFilenameAndPath) { assert(!empty($rootPluginFilenameAndPath)); assert(PostmanUtils::isAdmin()); assert(is_admin()); $this->logger = new PostmanLogger(get_class($this)); $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath; $this->options = PostmanOptions::getInstance(); PostmanUtils::registerAdminMenu($this, 'addEmailTestSubmenu'); // hook on the init event add_action('init', array($this, 'on_init')); // initialize the scripts, stylesheets and form fields add_action('admin_init', array($this, 'on_admin_init')); }
public function createConfig(PostmanTransport $transport) { // retrieve the hostname and port form the transport $hostname = $transport->getHostname(); $port = $transport->getHostPort(); // the sender email is needed for the OAuth2 Bearer token $senderEmail = PostmanOptions::getInstance()->getEnvelopeSender(); assert(!empty($senderEmail)); // the vendor is required for Yahoo's OAuth2 implementation $vendor = $this->createVendorString($hostname); // create the OAuth2 SMTP Authentication string $initClientRequestEncoded = $this->createAuthenticationString($senderEmail, PostmanOAuthToken::getInstance()->getAccessToken(), $vendor); // create the Configuration structure for Zend_Mail $config = $this->createConfiguration($hostname, $port, $transport->getSecurityType(), $transport->getAuthenticationType(), $initClientRequestEncoded); // return the Configuration structure return $config; }
/** */ function __construct($rootPluginFilenameAndPath) { $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath; $this->logger = new PostmanLogger(get_class($this)); if (PostmanOptions::getInstance()->isMailLoggingEnabled()) { add_action('admin_menu', array($this, 'postmanAddMenuItem')); } else { $this->logger->trace('not creating PostmanEmailLog admin menu item'); } if (PostmanUtils::isCurrentPagePostmanAdmin('postman_email_log')) { $this->logger->trace('on postman email log page'); // $this->logger->debug ( 'Registering ' . $actionName . ' Action Post handler' ); add_action('admin_post_delete', array($this, 'delete_log_item')); add_action('admin_post_view', array($this, 'view_log_item')); add_action('admin_post_transcript', array($this, 'view_transcript_log_item')); add_action('admin_init', array($this, 'handle_bulk_action')); } }
/** * 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(); }
/** * (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; } }
/** * * @param unknown $data */ public function prepareOptionsForExport($data) { $data = parent::prepareOptionsForExport($data); $data[PostmanOptions::SENDGRID_API_KEY] = PostmanOptions::getInstance()->getSendGridApiKey(); return $data; }
/** * Validate an e-mail address * * @param unknown $email * @return number */ static function validateEmail($email) { if (PostmanOptions::getInstance()->isEmailValidationDisabled()) { return true; } require_once 'Postman-Mail/Zend-1.12.10/Exception.php'; require_once 'Postman-Mail/Zend-1.12.10/Registry.php'; require_once 'Postman-Mail/Zend-1.12.10/Validate/Exception.php'; require_once 'Postman-Mail/Zend-1.12.10/Validate/Interface.php'; require_once 'Postman-Mail/Zend-1.12.10/Validate/Abstract.php'; require_once 'Postman-Mail/Zend-1.12.10/Validate/Ip.php'; require_once 'Postman-Mail/Zend-1.12.10/Validate/Hostname.php'; require_once 'Postman-Mail/Zend-1.12.10/Validate/EmailAddress.php'; if (!isset(PostmanUtils::$emailValidator)) { PostmanUtils::$emailValidator = new Postman_Zend_Validate_EmailAddress(); } return PostmanUtils::$emailValidator->isValid($email); }
/** * * @param unknown $data */ public function prepareOptionsForExport($data) { $data = parent::prepareOptionsForExport($data); $data[PostmanOptions::MANDRILL_API_KEY] = PostmanOptions::getInstance()->getMandrillApiKey(); return $data; }
/** * * @return boolean */ private function isOAuth2SupportedHostConfigured() { $options = PostmanOptions::getInstance(); $hostname = $options->getHostname(); $supportedOAuthProvider = $this->isServiceProviderGoogle($hostname) || $this->isServiceProviderMicrosoft($hostname) || $this->isServiceProviderYahoo($hostname); return $supportedOAuthProvider; }
public function __construct() { $this->options = PostmanOptions::getInstance(); }
private function isSenderConfigured(PostmanOptions $options) { $envelopeFrom = $options->getEnvelopeSender(); $messageFrom = $options->getMessageSenderEmail(); return !(empty($envelopeFrom) || empty($messageFrom)); }
/** * Determine whether to show the Request Permission link on the main menu * * This link is displayed if * 1. the current transport requires OAuth 2.0 * 2. the transport is properly configured * 3. we have a valid Client ID and Client Secret without an Auth Token * * @param PostmanOptions $options * @return boolean */ public function isRequestOAuthPermissionAllowed(PostmanOptions $options, PostmanOAuthToken $authToken) { // does the current transport use OAuth 2.0 $oauthUsed = self::getCurrentTransport()->isOAuthUsed($options->getAuthenticationType()); // is the transport configured $configured = self::getCurrentTransport()->isConfigured($options, $authToken); return $oauthUsed && $configured; }
/** * * @return boolean */ protected function isPermissionNeeded() { $accessToken = $this->getOAuthToken()->getAccessToken(); $refreshToken = $this->getOAuthToken()->getRefreshToken(); return $this->isOAuthUsed(PostmanOptions::getInstance()->getAuthenticationType()) && (empty($accessToken) || empty($refreshToken)); }
public function getCredentialsSecret() { $options = PostmanOptions::getInstance(); if ($options->isAuthTypeOAuth2()) { return $options->getClientSecret(); } else { return $options->getPassword(); } }
/** */ public function outputPurgeDataContent() { $importTitle = __('Import', Postman::TEXT_DOMAIN); $exportTile = __('Export', Postman::TEXT_DOMAIN); $resetTitle = __('Reset Plugin', Postman::TEXT_DOMAIN); $options = $this->options; print '<div class="wrap">'; PostmanViewController::outputChildPageHeader(sprintf('%s/%s/%s', $importTitle, $exportTile, $resetTitle)); print '<section id="export_settings">'; printf('<h3><span>%s<span></h3>', $exportTile); printf('<p><span>%s</span></p>', __('Copy this data into another instance of Postman to duplicate the configuration.', Postman::TEXT_DOMAIN)); $data = ''; if (!PostmanPreRequisitesCheck::checkZlibEncode()) { $extraDeleteButtonAttributes = sprintf('disabled="true"'); $data = ''; } else { $extraDeleteButtonAttributes = ''; if (!$options->isNew()) { $data = $options->export(); } } printf('<textarea cols="80" rows="5" readonly="true" name="settings" %s>%s</textarea>', $extraDeleteButtonAttributes, $data); print '</section>'; print '<section id="import_settings">'; printf('<h3><span>%s<span></h3>', $importTitle); print '<form method="POST" action="' . get_admin_url() . 'admin-post.php">'; wp_nonce_field(PostmanAdminController::IMPORT_SETTINGS_SLUG); printf('<input type="hidden" name="action" value="%s" />', PostmanAdminController::IMPORT_SETTINGS_SLUG); print '<p>'; printf('<span>%s</span>', __('Paste data from another instance of Postman here to duplicate the configuration.', Postman::TEXT_DOMAIN)); if (PostmanTransportRegistry::getInstance()->getSelectedTransport()->isOAuthUsed(PostmanOptions::getInstance()->getAuthenticationType())) { $warning = __('Warning', Postman::TEXT_DOMAIN); $errorMessage = __('Using the same OAuth 2.0 Client ID and Client Secret from this site at the same time as another site will cause failures.', Postman::TEXT_DOMAIN); printf(' <span><b>%s</b>: %s</span>', $warning, $errorMessage); } print '</p>'; printf('<textarea cols="80" rows="5" name="settings" %s></textarea>', $extraDeleteButtonAttributes); submit_button(__('Import', Postman::TEXT_DOMAIN), 'primary', 'import', true, $extraDeleteButtonAttributes); print '</form>'; print '</section>'; print '<section id="delete_settings">'; printf('<h3><span>%s<span></h3>', $resetTitle); print '<form method="POST" action="' . get_admin_url() . 'admin-post.php">'; wp_nonce_field(PostmanAdminController::PURGE_DATA_SLUG); printf('<input type="hidden" name="action" value="%s" />', PostmanAdminController::PURGE_DATA_SLUG); printf('<p><span>%s</span></p><p><span>%s</span></p>', __('This will purge all of Postman\'s settings, including account credentials and the email log.', Postman::TEXT_DOMAIN), __('Are you sure?', Postman::TEXT_DOMAIN)); $extraDeleteButtonAttributes = 'style="background-color:red;color:white"'; if ($this->options->isNew()) { $extraDeleteButtonAttributes .= ' disabled="true"'; } submit_button($resetTitle, 'delete', 'submit', true, $extraDeleteButtonAttributes); print '</form>'; print '</section>'; print '</div>'; }
/** * Parse server response for successful codes * * Read the response from the stream and check for expected return code. * Throws a Postman_Zend_Mail_Protocol_Exception if an unexpected code is returned. * * @param string|array $code One or more codes that indicate a successful response * @throws Postman_Zend_Mail_Protocol_Exception * @return string Last line of response string */ protected function _expect($code, $timeout = null) { $userTimeout = PostmanOptions::getInstance()->getReadTimeout(); if ($timeout > $userTimeout) { $timeout = $userTimeout; } $this->_response = array(); $cmd = ''; $more = ''; $msg = ''; $errMsg = ''; if (!is_array($code)) { $code = array($code); } do { $this->_response[] = $result = $this->_receive($timeout); list($cmd, $more, $msg) = preg_split('/([\\s-]+)/', $result, 2, PREG_SPLIT_DELIM_CAPTURE); if ($errMsg !== '') { $errMsg .= ' ' . $msg; } elseif ($cmd === null || !in_array($cmd, $code)) { $errMsg = $msg; } } while (strpos($more, '-') === 0); // The '-' message prefix indicates an information string instead of a response string. if ($errMsg !== '') { /** * @see Postman_Zend_Mail_Protocol_Exception */ // require_once 'Zend/Mail/Protocol/Exception.php'; throw new Postman_Zend_Mail_Protocol_Exception($errMsg, $cmd); } return $msg; }
private function sanitizeLogMax($desc, $key, $input, &$new_input) { if (isset($input[$key])) { $value = absint($input[$key]); if ($value <= 0) { $new_input[$key] = PostmanOptions::getInstance()->getMailLoggingMaxEntries(); $h = new PostmanMessageHandler(); $h->addError(sprintf('%s %s', __('Maximum Log Entries', 'Configuration Input Field', Postman::TEXT_DOMAIN), __('must be greater than 0', Postman::TEXT_DOMAIN))); } else { $this->logSanitize($desc, $input[$key]); $new_input[$key] = $value; } } }
/** * Options page callback */ public function outputDefaultContent() { // Set class property print '<div class="wrap">'; $this->displayTopNavigation(); if (PostmanTransportRegistry::getInstance()->isPostmanReadyToSendEmail($this->options, $this->authorizationToken) && PostmanPreRequisitesCheck::isReady()) { if ($this->options->getRunMode() != PostmanOptions::RUN_MODE_PRODUCTION) { printf('<p><span style="background-color:yellow">%s</span></p>', __('Postman is in <em>non-Production</em> mode and is dumping all emails.', 'postman-smtp')); } else { printf('<p><span style="color:green;padding:2px 5px; font-size:1.2em">%s</span></p>', __('Postman is configured.', 'postman-smtp')); $currentTransport = PostmanTransportRegistry::getInstance()->getCurrentTransport(); $deliveryDetails = $currentTransport->getDeliveryDetails($this->options); printf('<p style="margin:0 10px"><span>%s</span></p>', $deliveryDetails); } /* translators: where %d is the number of emails delivered */ printf('<p style="margin:10px 10px"><span>%s', sprintf(_n('Postman has delivered <span style="color:green">%d</span> email for you.', 'Postman has delivered <span style="color:green">%d</span> emails for you.', PostmanStats::getInstance()->getSuccessfulDeliveries(), 'postman-smtp'), PostmanStats::getInstance()->getSuccessfulDeliveries())); if ($this->options->isMailLoggingEnabled()) { print ' '; printf('<a href="%s">%s</a>.</span></p>', PostmanUtils::getEmailLogPageUrl(), __('View the log', 'postman-smtp')); } if (PostmanState::getInstance()->isTimeToReviewPostman() && !PostmanOptions::getInstance()->isNew()) { print '</br><hr width="70%"></br>'; /* translators: where %s is the URL to the WordPress.org review and ratings page */ printf('%s</span></p>', sprintf(__('Please consider <a href="%s">leaving a review</a> to help spread the word! :D', 'postman-smtp'), 'https://wordpress.org/support/view/plugin-reviews/postman-smtp?filter=5')); } } else { printf('<p><span style="color:red; padding:2px 5px; font-size:1.1em">%s</span></p>', __('Postman is <em>not</em> handling email delivery.', 'postman-smtp')); if ($this->options->isNew()) { printf('<h3>%s</h3>', __('Thank-you for choosing Postman!', 'postman-smtp')); /* translators: where %s is the URL of the Setup Wizard */ printf('<p><span>%s</span></p>', sprintf(__('Let\'s get started! All users are strongly encouraged to <a href="%s">run the Setup Wizard</a>.', 'postman-smtp'), $this->getPageUrl(self::CONFIGURATION_WIZARD_SLUG))); } } }
/** * A convenient place for any code to inject a constructed PostmanMessage * (for example, from MyMail) * * The body parts may be set already at this time. * * @param PostmanMessage $message * @return boolean */ public function sendMessage(PostmanMessage $message, PostmanEmailLog $log) { // get the Options and AuthToken $options = PostmanOptions::getInstance(); $authorizationToken = PostmanOAuthToken::getInstance(); // get the transport and create the transportConfig and engine $transport = PostmanTransportRegistry::getInstance()->getActiveTransport(); // create the Mail Engine $engine = $transport->createMailEngine(); // add plugin-specific attributes to PostmanMessage $message->addHeaders($options->getAdditionalHeaders()); $message->addTo($options->getForcedToRecipients()); $message->addCc($options->getForcedCcRecipients()); $message->addBcc($options->getForcedBccRecipients()); // apply the WordPress filters // may impact the from address, from email, charset and content-type $message->applyFilters(); // create the body parts (if they are both missing) if ($message->isBodyPartsEmpty()) { $message->createBodyParts(); } // is this a test run? $testMode = apply_filters('postman_test_email', false); if ($this->logger->isDebug()) { $this->logger->debug('testMode=' . $testMode); } // start the clock $startTime = microtime(true) * 1000; try { // prepare the message $message->validate($transport); // send the message if ($options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION) { if ($transport->isLockingRequired()) { PostmanUtils::lock(); // may throw an exception attempting to contact the OAuth2 provider $this->ensureAuthtokenIsUpdated($transport, $options, $authorizationToken); } $this->logger->debug('Sending mail'); // may throw an exception attempting to contact the SMTP server $engine->send($message); // increment the success counter, unless we are just tesitng if (!$testMode) { PostmanState::getInstance()->incrementSuccessfulDelivery(); } } // clean up $this->postSend($engine, $startTime, $options, $transport); if ($options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY) { // log the successful delivery PostmanEmailLogService::getInstance()->writeSuccessLog($log, $message, $engine->getTranscript(), $transport); } // return successful return true; } catch (Exception $e) { // save the error for later $this->exception = $e; // write the error to the PHP log $this->logger->error(get_class($e) . ' code=' . $e->getCode() . ' message=' . trim($e->getMessage())); // increment the failure counter, unless we are just tesitng if (!$testMode && $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION) { PostmanState::getInstance()->incrementFailedDelivery(); } // clean up $this->postSend($engine, $startTime, $options, $transport); if ($options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY) { // log the failed delivery PostmanEmailLogService::getInstance()->writeFailureLog($log, $message, $engine->getTranscript(), $transport, $e->getMessage()); } // return failure return false; } }
/** * (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; } }
/** * This function handle the request to import plugin data */ public function importSettingsAction() { $this->logger->debug('is wpnonce import-settings?'); $success = true; if (wp_verify_nonce($_REQUEST['_wpnonce'], PostmanAdminController::IMPORT_SETTINGS_SLUG)) { $success = PostmanOptions::getInstance()->import($_POST['settings']); } else { $success = false; } if (!$success) { $this->messageHandler->addError(__('There was an error importing the data.', Postman::TEXT_DOMAIN)); $this->logger->error('There was an error importing the data'); } PostmanUtils::redirect(PostmanUtils::POSTMAN_HOME_PAGE_RELATIVE_URL); }
/** * Check for configuration errors and displays messages to the user */ public function check_for_configuration_errors() { $options = PostmanOptions::getInstance(); $authToken = PostmanOAuthToken::getInstance(); // did Postman fail binding to wp_mail()? if ($this->wpMailBinder->isUnboundDueToException()) { // this message gets printed on ANY WordPress admin page, as it's a pretty fatal error that // may occur just by activating a new plugin if (PostmanUtils::isAdmin() && is_admin()) { // I noticed the wpMandrill and SendGrid plugins have the exact same error message here // I've adopted their error message as well, for shits and giggles .... :D $this->messageHandler->addError(__('Postman: wp_mail has been declared by another plugin or theme, so you won\'t be able to use Postman until the conflict is resolved.', 'postman-smtp')); // $this->messageHandler->addError ( __ ( 'Error: Postman is properly configured, but the current theme or another plugin is preventing service.', 'postman-smtp' ) ); } } else { if (!$this->wpMailBinder->isBound()) { $transport = PostmanTransportRegistry::getInstance()->getCurrentTransport(); $scribe = PostmanConfigTextHelperFactory::createScribe($options->getHostname(), $transport); $readyToSend = PostmanTransportRegistry::getInstance()->isPostmanReadyToSendEmail($options, $authToken); $virgin = $options->isNew(); if (!$readyToSend && !$virgin) { // if the configuration is broken, and the user has started to configure the plugin // show this error message $message = PostmanTransportRegistry::getInstance()->getCurrentTransport()->getMisconfigurationMessage($scribe, $options, $authToken); if ($message) { // output the warning message $this->logger->warn('Transport has a configuration problem: ' . $message); // on pages that are Postman admin pages only, show this error message if (PostmanUtils::isAdmin() && PostmanUtils::isCurrentPagePostmanAdmin()) { $this->messageHandler->addError($message); } } } // on pages that are NOT Postman admin pages only, show this error message if (!PostmanUtils::isCurrentPagePostmanAdmin() && !$readyToSend) { // on pages that are *NOT* Postman admin pages only.... // if the configuration is broken // show this error message add_action('admin_notices', array($this, 'display_configuration_required_warning')); } } } }
/** * Apply the WordPress filters to the email */ public function applyFilters() { if ($this->logger->isDebug()) { $this->logger->debug('Applying WordPress filters'); } /** * Filter the email address to send from. * * @since 2.2.0 * * @param string $from_email * Email address to send from. */ $filteredEmail = apply_filters('wp_mail_from', $this->getFromAddress()->getEmail()); if ($this->logger->isTrace()) { $this->logger->trace('wp_mail_from: ' . $filteredEmail); } if ($this->getFromAddress()->getEmail() !== $filteredEmail) { $this->logger->debug(sprintf('Filtering From email address: before=%s after=%s', $this->getFromAddress()->getEmail(), $filteredEmail)); $this->getFromAddress()->setEmail($filteredEmail); } /** * Filter the name to associate with the "from" email address. * * @since 2.3.0 * * @param string $from_name * Name associated with the "from" email address. */ $filteredName = apply_filters('wp_mail_from_name', $this->getFromAddress()->getName()); if ($this->logger->isTrace()) { $this->logger->trace('wp_mail_from_name: ' . $filteredName); } if ($this->getFromAddress()->getName() !== $filteredName) { $this->logger->debug(sprintf('Filtering From email name: before=%s after=%s', $this->getFromAddress()->getName(), $filteredName)); $this->getFromAddress()->setName($filteredName); } /** * Filter the default wp_mail() charset. * * @since 2.3.0 * * @param string $charset * Default email charset. */ $filteredCharset = apply_filters('wp_mail_charset', $this->getCharset()); if ($this->logger->isTrace()) { $this->logger->trace('wp_mail_charset: ' . $filteredCharset); } if ($this->getCharset() !== $filteredCharset) { $this->logger->debug(sprintf('Filtering Charset: before=%s after=%s', $this->getCharset(), $filteredCharset)); $this->setCharset($filteredCharset); } /** * Filter the wp_mail() content type. * * @since 2.3.0 * * @param string $content_type * Default wp_mail() content type. */ $filteredContentType = apply_filters('wp_mail_content_type', $this->getContentType()); if ($this->logger->isTrace()) { $this->logger->trace(sprintf('wp_mail_content_type: "%s"', $filteredContentType)); } if ($this->getContentType() != $filteredContentType) { $this->logger->debug(sprintf('Filtering Content-Type: before=%s after=%s', $this->getContentType(), $filteredContentType)); $this->setContentType($filteredContentType); } // Postman has it's own 'user override' filter $options = PostmanOptions::getInstance(); $forcedEmailAddress = $options->getMessageSenderEmail(); if ($options->isSenderEmailOverridePrevented() && $this->getFromAddress()->getEmail() !== $forcedEmailAddress) { $this->logger->debug(sprintf('Forced From email address: before=%s after=%s', $this->getFromAddress()->getEmail(), $forcedEmailAddress)); $this->getFromAddress()->setEmail($forcedEmailAddress); } $forcedEmailName = $options->getMessageSenderName(); if ($options->isSenderNameOverridePrevented() && $this->getFromAddress()->getName() !== $forcedEmailName) { $this->logger->debug(sprintf('Forced From email name: before=%s after=%s', $this->getFromAddress()->getName(), $forcedEmailName)); $this->getFromAddress()->setName($forcedEmailName); } }
/** * Constructor * * @param PostmanOptions $options */ function __construct() { $this->options = PostmanOptions::getInstance(); $this->authorizationToken = PostmanOAuthToken::getInstance(); $this->diagnostics = ''; PostmanUtils::registerAjaxHandler('postman_diagnostics', $this, 'getDiagnostics'); }
/** * Creates the pathname of the lockfile * * @param unknown $tempDirectory * @return string */ private static function calculateTemporaryLockPath($tempDirectory) { if (empty($tempDirectory)) { $options = PostmanOptions::getInstance(); $tempDirectory = $options->getTempDirectory(); } $fullPath = sprintf('%s/.postman_%s.lock', $tempDirectory, self::generateUniqueLockKey()); return $fullPath; }